Dockerfile
==========
A Dockerfile is a recipe file that can be used to create a docker image out
of it as::
docker build
-t
A Dockerfile contains a set of instructions, each of which constitutes
a new layer on top of the previous one.
Useful instructions in a dockerfile are:
.. code-block:: dockerfile
FROM # base image
ADD [] # copy files or directories to the image
RUN # execute command in the image
ENV # define environment variable
CMD # command to be executed when the container starts
Other useful instructions are:
.. code-block:: dockerfile
WORKDIR # set a working directory
VOLUME # create a mount point for external volumes
EXPOSE # expose a particular port in the container
USER # change container user
The **user** in the container is ``root`` by default. You can use any other
user, but it must exits in the host OS.
Many services use user ``999`` as default.
Example
-------
Example of a Dockerfile:
.. code-block:: dockerfile
FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py
Multi-stage
-----------
Multi-Stage Dockerfiles allow to create images on every stage,
and copy files from earlier stages to keep final images small.
E.g.::
# stage - 1
FROM ubuntu AS buildstep
RUN apt-get update && apt-get install -y build-essential gcc
COPY hello.c /app/hello.c
WORKDIR /app
RUN gcc -o hello hello.c && chmod +x hello
# stage - 2
FROM ubuntu
RUN mkdir -p /usr/src/app/
WORKDIR /usr/src/app
COPY --from=buildstep /app/hello ./hello
COPY ./start.sh ./start.sh
ENV INITSYSTEM=on
CMD ["bash", "/usr/src/app/start.sh"]
Tips
----
Limit the number of instructions
********************************
Each instruction in a Dockerfile constitutes a new layer. For this reason, it
is often recommended to combine items that have the same instruction (if that
makes sense).
E.g. instead of
.. code-block::
RUN apt-get update
RUN apt-get install -y git
in two lines, they can be combined into a single line as:
.. code-block::
RUN apt-get update && apt-get install -y git
In the :dk:`RUN` case, it also has other benefits, because the first
instruction is cached, it might be that the second gets and out of date
version of the packages.
Keep your image small
*********************
Try to use small base images (e.g. `alpine `_)
or slim versions (e.g. `Debian bullseye-slim `_).
Moreover, try to remove any extra stuff you added and it is not required.
E.g.:
.. code-block:: dockerfile
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y \
build-essential \
git \
&& rm -rf /var/lib/apt/lists/*