Docker First Image
Create your first image
Note: The code for this section is in this repository in the flask-app directory.
Now that you have a better understanding of images, it's time to create your own. Our goal here is to create an image that sandboxes a small Flask application.
The goal of this exercise is to create a Docker image which will run a Flask app.
We'll do this by first pulling together the components for a random cat picture generator built with Python Flask, then dockerizing it by writing a Dockerfile. Finally, we'll build the image, and then run it.
Create a Python Flask app that displays random cat pix
For the purposes of this workshop, we've created a fun little Python Flask app that displays a random cat .gif
every time it is loaded - because, you know, who doesn't like cats?
Start by creating a directory called flask-app
where we'll create the following files:
Make sure to cd flask-app
before you start creating the files, because you don't want to start adding a whole bunch of other random files to your image.
app.py
Create the app.py with the following content:
requirements.txt
In order to install the Python modules required for our app, we need to create a file called requirements.txt and add the following line to that file:
templates/index.html
Create a directory called templates
and create an index.html file in that directory with the following content in it:
Write a Dockerfile
We want to create a Docker image with this web app. As mentioned above, all user images are based on a base image. Since our application is written in Python, we will build our own Python image based on Alpine. We'll do that using a Dockerfile.
A Dockerfile is a text file that contains a list of commands that the Docker daemon calls while creating an image. The Dockerfile contains all the information that Docker needs to know to run the app — a base Docker image to run from, location of your project code, any dependencies it has, and what commands to run at start-up. It is a simple way to automate the image creation process. The best part is that the commands you write in a Dockerfile are almost identical to their equivalent Linux commands. This means you don't really have to learn new syntax to create your own Dockerfiles.
Create a file called Dockerfile, and add content to it as described below.
We'll start by specifying our base image, using the FROM
keyword:
The next step usually is to write the commands of copying the files and installing the dependencies. But first we will install the Python pip package to the alpine linux distribution. This will not just install the pip package but any other dependencies too, which includes the python interpreter. Add the following RUN command next:
Let's add the files that make up the Flask Application.
Install all Python requirements for our app to run. This will be accomplished by adding the lines:
Copy the files you have created earlier into our image by using COPY command.
Specify the port number which needs to be exposed. Since our flask app is running on
5000
that's what we'll expose.
The last step is the command for running the application which is simply -
python ./app.py
. Use the CMD command to do that:
The primary purpose of CMD
is to tell the container which command it should run by default when it is started.
Verify your Dockerfile.
Our Dockerfile
is now ready. This is how it looks:
Build the image
Now that you have your Dockerfile
, you can build your image. The docker build
command does the heavy-lifting of creating a docker image from a Dockerfile
.
When you run the docker build
command given below, make sure to replace <YOUR_USERNAME>
with your username. This username should be the same one you created when registering on Docker Cloud. If you haven't done that yet, please go ahead and create an account.
The docker build
command is quite simple - it takes an optional tag name with the -t
flag, and the location of the directory containing the Dockerfile
- the .
indicates the current directory:
If you don't have the alpine:3.5
image, the client will first pull the image and then create your image. Therefore, your output on running the command will look different from mine. If everything went well, your image should be ready! Run docker images
and see if your image (<YOUR_USERNAME>/myfirstapp
) shows.
Run your image
The next step in this section is to run the image and see if it actually works.
Head over to http://localhost:8888
and your app should be live. Note If you are using Docker Machine, you may need to open up another terminal and determine the container ip address using docker-machine ip default
.
Hit the Refresh button in the web browser to see a few more cat images.
Push your image
Now that you've created and tested your image, you can push it to Docker Cloud.
First you have to login to your Docker Cloud account, to do that:
Enter YOUR_USERNAME
and password
when prompted.
Now all you have to do is:
Now that you are done with this container, stop and remove it since you won't be using it again.
Open another terminal window and execute the following commands:
or
Dockerfile commands summary
Here's a quick summary of the few basic commands we used in our Dockerfile.
FROM
starts the Dockerfile. It is a requirement that the Dockerfile must start with theFROM
command. Images are created in layers, which means you can use another image as the base image for your own. TheFROM
command defines your base layer. As arguments, it takes the name of the image. Optionally, you can add the Docker Cloud username of the maintainer and image version, in the formatusername/imagename:version
.RUN
is used to build up the Image you're creating. For eachRUN
command, Docker will run the command then create a new layer of the image. This way you can roll back your image to previous states easily. The syntax for aRUN
instruction is to place the full text of the shell command after theRUN
(e.g.,RUN mkdir /user/local/foo
). This will automatically run in a/bin/sh
shell. You can define a different shell like this:RUN /bin/bash -c 'mkdir /user/local/foo'
COPY
copies local files into the container.CMD
defines the commands that will run on the Image at start-up. Unlike aRUN
, this does not create a new layer for the Image, but simply runs the command. There can only be oneCMD
per a Dockerfile/Image. If you need to run multiple commands, the best way to do that is to have theCMD
run a script.CMD
requires that you tell it where to run the command, unlikeRUN
. So exampleCMD
commands would be:
EXPOSE
creates a hint for users of an image which ports provide services. It is included in the information which can be retrieved via$ docker inspect <container-id>
.
Note: The
EXPOSE
command does not actually make any ports accessible to the host! Instead, this requires publishing ports by means of the-p
flag when using$ docker run
.
PUSH
pushes your image to Docker Cloud, or alternately to a private registry
Note: If you want to learn more about Dockerfiles, check out Best practices for writing Dockerfiles.
Next Steps
For the next step in the tutorial head over to 3.0 Deploying an app to a Swarm
Last updated