Building your first Dockerfile and image

Docker build from Dockerfile
Docker build from Dockerfile

What is a Dockerfile?

A Dockerfile in it’s simplest form is a file that contains instructions on how to build an Docker image. Although there aren’t any set rules about how Dockerfiles can be built I generally like to imagine them containing 4 primary sections:

  1. The first portion of the Dockerfile is the base section. This small 1 line section identifies a base image to start from. For example if your first line was FROM ubuntu:20.04 it would tell docker that when it builds the image it should start with the image that contains the Ubuntu 20.04 operating system.
  2. The second section is the environment section. This is where you get to setup the environment that the rest of the file runs in. You might want to set the working directory (WORKDIR /opt/app) or other variables (ENV PORT=”3000″) to use later on.
  3. The third section is the work section. This is where all of the work happens. Packages get installed (RUN apt install -y python3), code gets copied over (COPY src/ /opt/app), dependencies get install, code gets compiled, etc.
  4. The final portion of the Dockerfile is the run section. This is where you get to define what ports your app runs on (EXPOSE 3000), who the app runs as (USER node), and what command to run once the app starts up (CMD [“yarn”, “start”]).

Combining all of these sections creates an Dockerfile with the instructions on what image/os to start with, the environment to run in, what commands it should run, and what to do when the docker image starts up. The next section contains a hands on – step by step guide to creating a Dockerfile.

Creating the Dockerfile

To keep it simple our hands on example will be to create a python dockerized application that says hello world. So let’s jump into it! Create a new file called ‘Dockerfile’ and follow the upcoming steps.

  1. The first line will include the base image that we’d like to use. Jumping over to Dockerhub there’s an official docker image that already has python setup and ready to go. So instead of using an Ubuntu or Alpine Linux image and running a bunch of install commands I’ll just use the ‘python‘ image. Looking through the tags on that same page I’m going to use ‘3.9-alpine‘ indicating I want python version 3.9 based on the Alpine Linux image. So my first line will be: ‘FROM python:3.9-alpine
  2. The next step will be to set any environment variables we’ll need. The one I always set is the working directory so the next line we’ll add will be ‘WORKDIR /opt‘. We don’t have any other variables to set at this time so we’ll move onto the next step.
  3. The third section will include all of the work to be done. Since the base image is already setup with python we can jump right into copying our code onto the image. So the next line will be to add our hello.py script ‘COPY hello.py /opt/‘. Note, you’ll need to create a hello.py file in your current directory with the contents ‘print(“Hello World”)’
  4. The final step is to specify how the image will run. Since we want our hello.py script to run on startup let’s add a ‘CMD’ line to start it up: ‘CMD [“python”,”/opt/hello.py”]‘. With this complete we now have:
FROM python:3.9-alpine
WORKDIR /opt
COPY hello.py /opt/
CMD ["python","/opt/hello.py"]

Building an image from the Dockerfile

With the Dockerfile in place it’s time to execute those instructions and convert them into an image. The basic syntax to do this is:

docker build <working_dir> -t <image_name>:<image_tag> -f <path_to_dockerfile>

We have 1 relative path in our Dockerfile – the hello.py copy. So we need to make sure we’re in the right local directory when running docker build for it to not error out. We’ll build our image by running:

docker build ./ -t hello:latest -f ./Dockerfile

The output should show each of the steps being processed:

Step 1/4 : FROM python:3.9-alpine
 ---> 7254f7459375
Step 2/4 : WORKDIR /opt
 ---> Using cache
 ---> 98e8d7b2e27c
Step 3/4 : COPY hello.py /opt/
 ---> 866e30a28d31
Step 4/4 : CMD ["python","/opt/hello.py"]
 ---> Running in 8020a1558e87
Removing intermediate container 8020a1558e87
 ---> 325e042dbe42
Successfully built 325e042dbe42
Successfully tagged hello:latest

We now have a new image ‘hello:latest’ that we can run!

Running your image

To run our new image is pretty simple:

docker run <image>:<tag>

So in our case we’ll run:

docker run hello:latest

And the output should be:

Hello World

Conclusion

We did it! We built a Dockerfile, turned it into an image, and then ran it! To get more comfortable creating Dockerfiles try installing some pip packages, building a new Dockerfile based on nodejs instead of python, or build an Dockerfile that starts an application and runs it on a certain port.

2 thoughts on “Building your first Dockerfile and image”

  1. Pingback: Docker Image vs Container | The Difference - Swiss Army DevOps

  2. Pingback: Installing Docker on Ubuntu - Swiss Army DevOps

Leave a Reply

Your email address will not be published. Required fields are marked *