I am building a docker container for a couple of services and it occured to me that I don’t really understand how to properly decide where to place certain commands.
It seems to me there are 2 alternatives when it comes to running commands on a Docker container.
- Using the RUN instruction (e.g
RUN composer -n install
) - Running the same command above inside a script that is used as entrypoint for the container (i.e inside
docker-entrypoint.sh
)
With regards to best practices, how should one decide when to use one approach vs the other? Specially with regards to containers that are not meant to be the base for any others, should commands be entirely contained in the Dockerfile, with only the application startup be done with the entrypoint, or should some commands be moved to the entrypoint script?
Thanks.
2
Answers
Everything that has to do with the building and configuration of software should take place in the build stage. The entrypoint should only perform the minimum set of tasks required to get the container up and running properly.
If you are concerned about image size, then you should most certainly adopt the best practice of combining statements in a single
RUN
command, as this will result in a single layer (so less overall size), e.g.:You may also look into multi-stage builds, which can help in reducing the final size of the image.
For reference: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers
You can run multiple copies of a container off of a single image. A Dockerfile
RUN
command only runs once when the image is built; the entrypoint script runs every time you start the container.As a general rule, I might suggest doing as much as you can in the Dockerfile. There are some parts of the system that aren’t available until runtime, like environment-variable settings and other containers; you can’t access these until the container starts, which means the entrypoint script.
So, for example:
RUN composer ...
and other commands that install software or libraries in the Dockerfile; these don’t depend on the runtime environment and you don’t want to repeat them every time the container runs.COPY
the migration files into the image, but the database isn’t available at image-build time, so the actual migrations need to be run in the entrypoint script.I’m a little less familiar with PHP, but a typical Python example might look like: