Docker image is an essential part of container infrastructure. It is an image that contains an application and all its required parts (libraries and other files).
Docker image is usually created using a
Dockerfile contains commands to build the image, environment variables, command to run when the container starts, entry point, and many other items.
Docker images are named using the following scheme
registry is omitted, the docker hub registry is used. An example of a docker image name is:
Before building your own docker image, it is strongly recommended to search the public registry for an existing image that contains the desired application, but also to check what is the timestamp of the last image, i.e. if someone is making new releases and bug fixes. For example, we can recommend
bitnami images. There are some limitations to using external docker images on our infrastructure, see limitations.
Creating your own Docker Image
If you find it necessary to create your own image, you will find a short guide below. For a complete guide, see official docker documentation. Knowledge of installing Linux applications and basics of Linux packaging systems is required.
Here are the most common Dockerfile commands:
FROM image– defines the image name to start your docker image from, e.g.
RUN cmd– run command that changes the starting image, more than one
RUNcommand can be used.
COPY localfile containerfile– copy local files to the docker image, you can use optional
--chown=user:groupto change ownership during copying. Copying and changing ownership later using
RUN chownis discouraged, as the resulting image will be twice as large.
USER uid– change the user to
uid(or name), from this line all other commands will run as the specified user, if this command is not used, everything will be done as the
rootuser. The last
USER uiddirective also specifies which user the container will run as by default.
CMD command– run
commandas the default command when the container is started.
- WORKDIR dir` – specifies current working directory, last working directory will be used as initial directory in a running container.
Example for Dockerfile:
RUN apt update -y && apt upgrade -y && apt install build-essential libssh-dev git -y
RUN git clone https://gitlab.con/zvon/iobench && cd iobench && make && make install
CMD /bin/bash -c "tail -f /dev/null"
- Containers usually do not have a user created in
/etc/passwd. In this case you will see the
I have no nameprompt. Also in this case there is no
homedirectory which defaults to
/, many applications fail here as
/will not be writable. It is recommended to create a default user to run the container as. The name of the user is not important. The following command will create a group named
groupand a user named
userat the end of the command is not an error.
RUN addgroup --gid 1000 group && \ adduser --gid 1000 --uid 1000 --disable-password --gecos user user
- The container defaults to the UTC timezone. If this is not desired, it should be set to the correct default, e.g.
RUN echo 'Europe/Prague' > /etc/timezone
- Packaging tools must not be interactive. For example, for `deb’ systems:
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y curl
Do not forget to add
-yto most packaging tools.
- Debian family systems usually install recommended packages by default, which is not desired here, disable it:
RUN apt-get install -y --no-install-recommends curl
- Keep the resulting image as small as possible. It is needed to clean up temporary files. For example, for
RUN apt-get update && apt-get -y install curl && apt-get clean && rm -rf /var/lib/apt/lists/*
RUN conda install package && conda clean --all -f -y && rm -rf "~/.cache
**Cleaning must be done within a single `RUN’ command.
RUN' command creates a new Docker image layer. It is recommended to merge related commands into a singleRUN` command, for example, install all required packages at once, not one at a time.
For Kubernetes, there is no need to use the `EXPOSE’ command to publish network ports. See Exposing Applications.
chmodwill double the size of the change files in the docker file, i.e.
chownon all files in the docker file will double the size of the docker file.
- When chaining commands, always chain with
&&and never with just
;. If one of the commands fails, chaining with
&&will stop the build of the whole image, which is usually what you want. Chaining with
;can hide some failing commands and make it hard to debug why the image is not what it should be.
Building Docker Image
Once the `Dockerfile’ is created, the docker image can be built. The following describes how to build a docker image manually. Manual building can be useful for debugging the build process.
To build a docker image locally, you need a machine running Linux with docker installed. To install docker, follow the instructions for your Linux distribution, usually
docker-ce is the right package. You may need to become a member of the
docker group to be able to use docker.
Dockerfile in a directory, e.g.
mydocker, and run the following, replacing
repo/name:tag with the correct name and tag
docker build -t repo/name:tag mydocker
If the build was successful, the image is built locally and needs to be pushed to a registry. If you are not logged in to the registry, issue
docker login registry', replacing registry’ with the real registry name.
docker push repo/name:tag
The `repo/name:tag’ must be exactly the same as in the build case.
Automated build can be done using a CI/CD pipeline. The build is done using the runner component which is part of many github/gitlab installations. You can use gitlab.ics.muni.cz, see GitLab Containers how to do it. This gitlab also provides docker registry, so once built image can be stored here for use from Kubernetes. The registry is public or private depending on the project settings, see GitLab Containers.
The automated build can be slow, so it is not the best option for debugging the build process.
Running Docker Images
It can be useful to manually run the built image before running it on Kubernetes, for example to check that all files are in place, important directories are writable, and so on. Running it manually is fast and has no privilege restrictions. However, be careful about running unknown images on your machine. To run a docker image locally, you need a Linux machine with docker installed, see manual build above.
Running locally can also be useful for inspecting the image, for example, to get the
UID of the running user if it is not known, as the
UID may be needed for running in Kubernetes.
For testing purposes, you can run the Docker image using:
docker run -it --rm registry/name:tag command
This command will run the
registry/name:tag image and run the
commend inside it. You can add
-u uid to run the image as user
If the image used has
ENTRYPOINT set, the
command will not be executed, but will only be passed as an argument to the
ENTRYPOINT script. If you need to avoid execution, you can pass the
--entrypoint /bin/bash option to
docker run. However, not all images have
/bin/bash or even
/bin/sh available. In such a case, you will need to rebuild the image and add/install
ctrl-d will kill the running Docker image. All changes inside the container will be lost unless you use
docker commit', see the [official docker documentation](https://docs.docker.com/develop/), in this case do not use the –rm’ option which automatically removes terminated images.