Read in 6 minutes

last updated 

How to Build Docker Images with Dockerfile

A Docker image is the blueprint of Docker containers that contains the application and everything you need to run the application. A container is a runtime instance of an image.

In this tutorial, we will explain what Dockerfile is, how to create one and how to build a Docker image with Dockerfile.

What is Dockerfile

A Dockerfile is a text file that contains all the commands a user could run on the command line to create an image. It includes all the instructions needed by Docker to build the image.

A Docker image is made up of a series of filesystem layers representing instructions in the image’s Dockerfile that makes up an executable software application.

The Docker file takes the following form:

# Comment
INSTRUCTION arguments

Although the instructions are not case-sensitive the convention is to use UPPERCASE for their names.

Below is the list with a short description of some of the most used Dockerfile instructions:

  • ARG - This instruction allows you to define variables that can be passed at build-time. You can also define a default value.
  • FROM - The base image for building a new image. This instruction must be the first non-comment instruction in the Dockerfile. The only exception from this rule is when you want to use a variable in the FROM argument. In this case FROM can be preceded by one or more ARG instructions.
  • LABEL - Used to add metadata to an image, such as description, version, author ..etc. You can specify more than one LABEL and each LABEL instruction is a key-value pair.
  • RUN - The commands specified in this instruction will be executed during the build process. Each RUN instruction creates a new layer on top of the current image.
  • ADD - Used to copy files and directories from the specified source to the specified destination on the docker image. The source can be local files or directories or an URL. If the source is a local tar archive, then it is automatically unpacked into the Docker image.
  • COPY - Similar to ADD but the source can be only a local file or directory.
  • ENV - This instruction allows you to define an environment variable.
  • CMD - Used to specify a command that will be executed when you run a container. You can use only one CMD instruction in your Dockerfile.
  • ENTRYPOINT - Similar to CMD, this instruction defines what command will be executed when running a container.
  • WORKDIR - This directive sets the current working directory for the RUN, CMD, ENTRYPOINT, COPY and ADD instructions.
  • USER - Set the username or UID to use when running any following RUN, CMD, ENTRYPOINT, COPY and ADD instructions.
  • VOLUME - Enables you to mount a host machine directory to the container.
  • EXPOSE - Used to specify the port on which the container listens at runtime.

To, exclude files and directories from being added to the image, create a .dockerignore file in the context directory. The syntax of the .dockerignore is similar to the one of the Git’s .gitignore file.

For a complete reference and detailed explanation of Dockerfile instructions see the official Dockerfile reference page.

Create a Dockerfile

The most common scenario for creating Docker images is to pull an existing image from a registry such (usually from Docker Hub) and specify the changes you want to make on the base image. The most commonly used base image when creating Docker images is Alpine because it is small and optimized to be run in RAM.

The Docker Hub is cloud-based registry service which among other functionalities is used for keeping the Docker images either in a public or private repository.

In this example, we will create a Docker image for the Redis server. We’ll use the latest ubuntu 18.04 as a base image.

First, create a directory that will contain the Dockerfile and all the necessary files:

mkdir ~/redis_docker

Navigate to the directory and create the following Dockerfile:

cd ~/redis_docker
nano Dockerfile
Dockerfile
1
2
3
4
5
6
7
8
9
FROM ubuntu:18.04

RUN apt-get update && \
    apt-get install -y redis-server && \
    apt-get clean

EXPOSE 6379

CMD ["redis-server", "--protected-mode no"]

Let’s explain the meaning of each of the lines in the Dockerfile:

  • In line 1 we are defining the base image.
  • The RUN instruction that starts in line 3 will update the apt index, install the “redis-server” package and clean the apt cache. The commands used in instructions are the same as the commands you would use to install redis on Ubuntu server.
  • The EXPOSE instruction defines the port on which the redis server listens.
  • In the last line, we are using the CMD instruction to set the default command that will be executed when the container runs.

Save the file and close the editor.

Building the Image

The next step is to build the image. To do so run the following command from the directory where the Dockerfile is located:

docker build -t linuxize/redis .

The option -t specifies the image name and optionally a username and tag in the ‘username/imagename:tag’ format.

The output of the build process will look something like this:

Sending build context to Docker daemon  3.584kB
Step 1/4 : FROM ubuntu:18.04
 ---> 7698f282e524
Step 2/4 : RUN apt-get update &&     apt-get install -y gosu redis-server &&     apt-get clean
 ---> Running in e80d4dd69263
...
Removing intermediate container e80d4dd69263
 ---> e19fb7653fca
Step 3/4 : EXPOSE 6379
 ---> Running in 8b2a45f457cc
Removing intermediate container 8b2a45f457cc
 ---> 13b92565c201
Step 4/4 : CMD ["redis-server", "--protected-mode no"]
 ---> Running in a67ec50c7048
Removing intermediate container a67ec50c7048
 ---> d8acc14d9b6b
Successfully built d8acc14d9b6b
Successfully tagged linuxize/redis:latest

WHen the build process is completed the new image will be listed in the image list:

docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
linuxize/redis      latest              d8acc14d9b6b        4 minutes ago       100MB
ubuntu              18.04               7698f282e524        5 days ago          69.9MB

If you want to push the image to Docker Hub see Pushing a Docker container image to Docker Hub.

Running a Container

Now that the image is created you run a container from it by running:

docker run -d -p 6379:6379 --name redis linuxize/redis

The -d options tell Docker to run the container in detached mode, the -p 6379:6379 option will publish the port 6379 to the host machine and the --name redis option specifies the container name. The last argument linuxize/redis is the name of the image which is used to run the container.

When the container starts, use the following command to list all running containers:

docker container ls
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                    NAMES
6b7d424cd915        linuxize/redis:v0.0.1   "redis-server '--pro…"   5 minutes ago       Up 5 minutes        0.0.0.0:6379->6379/tcp   redis

To verify that everything works as it should use the redis-cli to connect to the docker container:

redis-cli ping

The redis server should respond with PONG.

Conclusion

This tutorial covered only the basics of using Dockerfiles to build images. To learn more about how to write Dockerfiles and the recommended best practices see Best practices for writing Dockerfiles.

If you have any question, please leave a comment below.