November 16, 2021 - Reading time: 6 minutes

Basic example

List of instructions to run when creating a container.

FROM debian:latest
LABEL location="DC1"
LABEL maintainer="Alan <>"
RUN apt update && apt install -y git

The name of the file is Dockerfile and we can generate a new container from it with:

test@localhost: sudo docker build --tag debian:with-git .
test@localhost: sudo docker image history debian:with-git
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
3ecca0c1966a   2 minutes ago   /bin/sh -c #(nop)  ENTRYPOINT ["git"]           0B        
2d12420a2edb   2 minutes ago   /bin/sh -c apt update && apt install -y git     119MB     
05954652b3a9   3 minutes ago   /bin/sh -c #(nop)  LABEL maintainer=Alan <a@…   0B        
e85ee52ff06f   3 minutes ago   /bin/sh -c #(nop)  LABEL location=DC1           0B        
f776cfb21b5e   5 weeks ago     /bin/sh -c #(nop)  CMD ["bash"]                 0B        
<missing>      5 weeks ago     /bin/sh -c #(nop) ADD file:aea313ae50ce6474a…   124MB 

The build process will add intermediate layers to the cache, and rely on the cache for future builds, unless instructed otherwise.

Ignore file

docker build reads the contents of .dockerignore do find out which files it should never add to the new image.

test@localhost: cat .dockerignore 

In this example, we ignore the loop.df (dockerfile) and other files. The content of loop.df is:

FROM debian:latest

ENV APPROOT="/app" \
    APP=""  \

LABEL com.test.auth="pepe <>" \ 
      com.test.loc="east" \

ENTRYPOINT [ "/app/" ]

Mixing multiple LABEL and ENV in one command reduces the number of layers.
The directory only contains the bash script, the docker file and the .dockerignore file:

test@localhost: ls -a
.  ..  .dockerignore  loop.df

Then we can build the image with:

test@localhost: sudo docker build --file loop.df --tag debian:loop .
Sending build context to Docker daemon  4.096kB
 ---> Running in 1f348ea58afd
Removing intermediate container 1f348ea58afd
 ---> f1188008d0a0
Step 5/7 : ADD . ${APPROOT}
 ---> 3b8d4f431e58
Step 6/7 : ENTRYPOINT [ "/app/" ]
 ---> Running in 8670ec90d355
Removing intermediate container 8670ec90d355
 ---> d6c0afd193dc
Step 7/7 : EXPOSE 3333
 ---> Running in e84f35d0dae4
Removing intermediate container e84f35d0dae4
 ---> b3925800617d

All the intermediate images using in the build process are left behind un-tagged:

test@localhost: sudo docker image ls --all
<none>       <none>    d6c0afd193dc   2 minutes ago   124MB
debian       loop      b3925800617d   2 minutes ago   124MB
<none>       <none>    26a9cad0f0c7   2 minutes ago   124MB
<none>       <none>    f1188008d0a0   2 minutes ago   124MB
<none>       <none>    3b8d4f431e58   2 minutes ago   124MB
<none>       <none>    b2cb3d542a4c   2 minutes ago   124MB
debian       latest    f776cfb21b5e   5 weeks ago     124MB

The ENTRYPOINT parameter accepts two different formats (array or string). When adding it as an array, anything passed as CMD or as parameter when docker container run will be ignored. The preferred way is exec command (array).

File system specific commands

  • COPY: for one specific file or folder
  • ADD: for the current folder
  • VOLUME: attach one or more volumes

Build related commands

  • ONBUILD [RUN] ... : commands that will only be run when the image is used with "FROM"


  • ARG VERSION=none: The value of version can be set with --build-arg VERSION=1.0 during docker image build

Multistage docker file

A file that has more than one FROM stanza. Each FROM marks a new stage, and the output layer can be used by the next stage. FROM <image> AS <identifier>. The identifier can be use by other stages in FROM or COPY. At the end we endup with only one single image.