Working as a Developer/DevOps who works with docker on daily basis or just getting started to learn using the container tech tools, I think there are some good practices that most people will agree on following.
So here are some tips I found while learning about creating Docker images.
1. Always chain RUN commands
Each RUN command will create a new extra layer because RUN command commits the changes you made in the top writable layer into a new image, You need to reduce images (to decrease complexity and increase speed).
So don’t do this
FROM ubuntu:xenial
RUN apt-get update
Run apt-get install -y git
RUN apt-get install -y vim
RUN apt-get install -y curl
Do this
FROM ubuntu:xenial
RUN apt-get update && apt-get install -y curl \
git \
vim
2. Use COPY instead of ADD unless you are sure you need ADD
COPY
: is a command used to copy files from the source directory to your container file system.
While ADD
also can copy files from source to container it also can download files and unpack zipped files.
Although ADD
and COPY
are functionally similar, generally speaking, COPY
is preferred. That’s because it’s more transparent than ADD
.
3. Avoid using [:latest] tag
From
command picks your base docker image you are building on, try to specify an official release tag and not latest
as latest
tag (tagging image latest release with latest
) is just a convention not all maintainers obligated to follow it, so specify a tag.
4. Sort your multi-line dependencies in alphanumeric order
When installing dependencies there is a best practice to order dependencies in alphanumeric order. this way you will avoid duplication.
RUN apt-get update && apt-get install -y curl \
git \
vim
5. Always use unprivileged normal user to run your app
By default, your container process runs as the root user, which introduces the risk of (given a scenario if a hacker breaks in the container using root user) they can also hack into your host machine.
So before running your app using CMD
create normal user and use him to run your app like:
RUN useradd -ms /bin/bash ahmed
USER ahmed
CMD [“python”, “app.py”]
6. Make sure to invalidate image cache when you update images.
Dockerfile: Chaining apt-get update
and apt-get install
helps to avoid running outdated images, the problem happens because for apt-get update
instruction, if run alone, will be cached with old updates, however, if you add new package like git to install it’s probably you won’t install the latest version of git if the apt-get update
is cached, being aware of that problem you can stop using the cache if needed docker build — no-cache=true
docker-compose: when using docker-compose you just need to make sure you build images, as docker-compose up -d
only builds images if they don’t exist, so if you change anything you need to build them again.
7. Avoid using the Host network unless you know what you are doing.
Creating a container with Host Network type can be risky, it’s the network with minimum security level because it shares same network interfaces as the host machine, although it’s fast (because requests don’t have to go through hosts IP mapping tables) it’s risky and not advisable to do it in production.
There are four networks types between docker containers : [Closed-Bridge-Host-Overlay]
Bridge: is the default where containers in the same bridge network can communicate with each other and outside world.
Closed: is isolated can’t even connect to the internet.
Overlay: is used with multi-host networking across many hosts (like in docker-swarm or Kubernetes)
Hope you liked the tips, you can check more best practices here https://docs.docker.com/develop/develop-images/dockerfile_best-practices
Please contact me if you have any thoughts about the topic
Thanks for reading ❤️