Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ea61400

Browse files
Revert "Delete part2.md"
This reverts commit 03e9567.
1 parent e799e19 commit ea61400

File tree

1 file changed

+219
-0
lines changed

1 file changed

+219
-0
lines changed

getting-started/part2.md

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
---
2+
title: "Getting Started, Part 2: Creating and Building Your App"
3+
---
4+
5+
In [Getting Started, Part 1: Orientation and Setup](index.md), you heard an
6+
overview of what containers are, what the
7+
Docker platform does, and what we'll be covering in this multi-part tutorial.
8+
You also got Docker installed on your machine.
9+
10+
In this section, you will write, build, run, and share an app, the Docker way.
11+
12+
## Your development environment
13+
14+
In the past, if you were to start writing a Python app, your first
15+
order of business was to install a Python runtime onto your machine. But,
16+
that creates a situation where the environment on your machine has to be just
17+
so in order for your app to run as expected; ditto for the server that runs
18+
your app.
19+
20+
With Docker, you can just grab a portable Python runtime as an image, no
21+
installation necessary. Then, your build can include the base Python image
22+
right alongside your app code, ensuring that your app, its dependencies, and the
23+
runtime, all travel together.
24+
25+
These builds are configured with something called a `Dockerfile`.
26+
27+
## Your first Dockerfile
28+
29+
Create an empty directory and put this file in it, with the name `Dockerfile`.
30+
`Dockerfile` will define what goes on in the environment inside your
31+
container. Access to resources like networking interfaces and disk drives is
32+
virtualized inside this environment, which is isolated from the rest of your
33+
system, so you have to map ports to the outside world, and
34+
be specific about what files you want to "copy in" to that environment. However,
35+
after doing that, you can expect that the build of your app defined in this
36+
`Dockerfile` will behave exactly the same wherever it runs.
37+
38+
{% gist johndmulhausen/c31813e076827178216b74e6a6f4a087 %}
39+
40+
This `Dockerfile` refers to a couple of things we haven't created yet, namely
41+
`app.py` and `requirements.txt`. We'll get there. But here's what this
42+
`Dockerfile` is saying:
43+
44+
- Download the official image of the Python 2.7 runtime and include it here.
45+
- Create `/app` and set it as the current working directory inside the container
46+
- Copy the contents of the current directory on my machine into `/app` inside the container
47+
- Install any Python packages that I list inside `requirements.txt`
48+
- Ensure that port 80 is exposed to the world outside this container
49+
- Set an environment variable within this container named `NAME` to be the string `World`
50+
- Finally, execute `python` and pass in `app.py` as the "entry point" command,
51+
the default command that is executed at runtime.
52+
53+
### The app itself
54+
55+
Grab these two files and place them in the same folder as `Dockerfile`.
56+
57+
{% gist johndmulhausen/074cc7f4c26a9a8f9164b20b22602ad7 %}
58+
{% gist johndmulhausen/8728902faede400c057f3205392bb9a8 %}
59+
60+
Now we see that the `Dockerfile` command `pip install requirements.txt` installs
61+
the Flask and Redis libraries for Python. We can also see that app itself
62+
prints the environment variable of `NAME`, which we set as `World`, as well as
63+
the output of a call to `socket.gethostname()`, which the Docker runtime is
64+
going to answer with the container ID, which is sort of like the process ID for
65+
an executable. Finally, because Redis isn't running
66+
(as we've only installed the Python library, and not Redis itself), we should
67+
expect that the attempt to use it here will fail and produce the error message.
68+
69+
## Build the App
70+
71+
That's it! You don't need to have installed Python or anything in
72+
`requirements.txt` on your system, nor will running this app install them in
73+
your system. It doesn't seem like you've really set up an environment with
74+
Python and Flask, but you have. Let's build and run your app and prove it.
75+
76+
7Here's what `ls` should show:
77+
78+
```shell
79+
$ ls
80+
Dockerfile app.py requirements.txt
81+
```
82+
83+
Now run the build command. This creates a Docker image, which we're going to
84+
tag using `-t` so it has a friendly name.
85+
86+
```shell
87+
docker build -t friendlyhello .
88+
```
89+
90+
In the output spew you can see everything defined in the `Dockerfile` happening.
91+
Where is your built image? It's in your machine's local Docker image registry.
92+
Check it out:
93+
94+
```shell
95+
$ docker images
96+
REPOSITORY TAG IMAGE ID CREATED SIZE
97+
friendlyhello latest 326387cea398 47 seconds ago 192.1 MB
98+
```
99+
100+
## Run the app
101+
102+
Run the app, mapping our machine's port 4000 to the container's exposed port 80
103+
using `-p`:
104+
105+
```shell
106+
docker run -p 4000:80 friendlyhello
107+
```
108+
109+
You should see a notice that Python is serving your app at `http://0.0.0.0:80`.
110+
But that message coming from inside the container, which doesn't know you
111+
actually want to access your app at: `http://localhost:4000`. Go there, and
112+
you'll see the "Hello World" text, the container ID, and the Redis error
113+
message, all printed out in beautiful Times New Roman.
114+
115+
Hit `CTRL+C` in your terminal to quit.
116+
117+
Now let's run the app in the background, in detached mode:
118+
119+
```shell
120+
docker run -d -p 4000:80 friendlyhello
121+
```
122+
123+
You get a hash ID of the container instance and then are kicked back to your
124+
terminal. Your app is running in the background. Let's see it with `docker ps`:
125+
126+
```shell
127+
$ docker ps
128+
CONTAINER ID IMAGE COMMAND CREATED STATUS
129+
1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago Up 25 seconds
130+
```
131+
132+
You'll see that `CONTAINER ID` matches what's on `http://localhost:4000`, if you
133+
refresh the browser page. Now use `docker stop` to end the process, using
134+
`CONTAINER ID`, like so:
135+
136+
```shell
137+
docker stop 1fa4ab2cf395
138+
```
139+
140+
## Share your image
141+
142+
Sign up a Docker account at [hub.docker.com](https://hub.docker.com/).
143+
Make note of your username. We're going to use it in a couple commands.
144+
145+
Docker Hub is a public registry. A registry is a collection of accounts and
146+
their various repositories. A repository is a collection of tagged images like a
147+
GitHub repository, except the code is already built.
148+
149+
Log in your local machine to Docker Hub.
150+
151+
```shell
152+
docker login
153+
```
154+
155+
Now, let's publish your image. First, specify the repository you'd like to use
156+
in a tag. The notation for associating a local image with a repository on a
157+
registry, is `username/repository:tag`. The `:tag` is optional, but recommended;
158+
it's the mechnism that registries use to give Docker images a version. So,
159+
putting all that together:
160+
161+
```shell
162+
docker tag friendlyhello YOURUSERNAME/YOURREPO:ARBITRARYTAG
163+
```
164+
165+
From now on, you can use `docker run` on this machine with the fully qualified
166+
tag. But that won't work on other machines until you upload this image, like so:
167+
168+
```shell
169+
docker push YOURUSERNAME/YOURREPO:ARBITRARYTAG
170+
```
171+
172+
Once complete, the results of this upload are [publicly available
173+
on Docker Hub](https://hub.docker.com/).
174+
175+
Now, remembering whatever you specified as your target repo, and whatever you
176+
used as a tag, go on another machine. Any machine where you can install Docker,
177+
and run this command:
178+
179+
```shell
180+
docker run YOURUSERNAME/YOURREPO:ARBITRARYTAG
181+
```
182+
183+
> Note: If you don't specify the `:ARBITRARYTAG` portion of these commands,
184+
the tag of `:latest` will be assumed, both when you build and when you run
185+
images.
186+
187+
You'll see this stranger of a machine pull your image, along with Python and all
188+
the dependencies from `requirements.txt`, and run your code. It all travels
189+
together in a neat little package, and the new machine didn't have to install
190+
anything but Docker to run it.
191+
192+
## Recap and cheat sheet for images and containers
193+
194+
To recap: After calling `docker run`, you created and ran a container, based on
195+
the image created when you called `docker build`. Images are defined in a
196+
`Dockerfile`. A container is an instance of an image, and it has any package
197+
installations, file writes, etc that happen after you call `docker run` and run
198+
the app. And lastly, images are shared via a registry.
199+
200+
```shell
201+
docker build -t friendlyname . #Create image using this directory's Dockerfile
202+
docker run -p 4000:80 friendlyname #Run image "friendlyname" mapping port 4000 to 80
203+
docker run -d -p 4000:80 friendlyname #Same thing, but in detached mode
204+
docker ps #See a list of all running containers
205+
docker stop <hash> #Gracefully stop the specified container
206+
docker ps -a #See a list of all containers on this machine, even the ones not running
207+
docker kill <hash> #Force shutdown of the specified container
208+
docker rm <hash> #Remove the specified container from this machine
209+
docker rm $(docker ps -a -q) #Remove all containers from this machine
210+
docker images -a #Show all images that have been built or downloaded onto this machine
211+
docker rmi <imagename> #Remove the specified image from this machine
212+
docker rmi $(docker images -q) #Remove all images from this machine
213+
docker login #Log in this CLI session using your Docker credentials (to Docker Hub by default)
214+
docker tag <image> username/repository:tag #Tag <image> on your local machine for upload
215+
docker push username/repository:tag #Upload tagged image to registry (Docker Hub by default)
216+
docker run username/repository:tag #Run image from a registry (Docker Hub by default)
217+
```
218+
219+
[On to "Getting Started, Part 3: Stateful, Multi-container Applications" >>](part3.md){: class="button darkblue-btn"}

0 commit comments

Comments
 (0)