Let's take an in-depth look at best practices for Docker containers:
Container Images
- Make sure you use an official and verified base image for your particular programming environment.
For example, if you are using a reactJS-based application, then instead of taking a base OS image and then installing reactJS, NPM etc., by yourself, you should use an official reactJS image for your application. An official and verified image is built with best practices, resulting in a cleaner Docker file. - Use the specific version of the Docker image.
Instead of always using the image with the latest tag, you should use the specific version suitable for your application. Default is the latest one, so you must specify the exact version to use a previous version. - Use smaller images.
When selecting a base image, you will see many base image variations. Each image will have its own set of operating system distributions and tools packaged in that image. Try to use a smaller image instead of full-blown operating system distribution. That will reduce the time to transfer this image and improve security as well, i.e. reduced surface area, more secure images, etc. - Use caching intelligently for Docker image layers when building images.
Try to use a cached image when building the Docker image; that will be much faster and easier. By default, Docker tries to use cached image layers as much as possible. As the caching works on the Docker file command from top to bottom, it is better to write those commands on top which are least likely to change. Similarly, any commands which are likely to change frequently should be written at the bottom. - Use .dockerignore for sensitive files and configuration.
You do not want any API keys, secrets, etc., to be part of the built Docker container image. You also do not want to include unnecessary folders to be part of the image e.g. Build folder, readme, etc. The best way to achieve this is by using the dockerignore file. Just mention the files and folders in this file, and Docker will do the rest. - Make use of multi-stage builds.
Multi-stage builds are helpful when some libraries are only needed when building the image but do not need to be part of the final image. Multi-stage build allows you to use temporary build images for build purposes but lets you create a final lean image without these build dependencies included. It also improves security, as the final image exposes less surface area. - Tag your container images.
Use the “stable” and “unique” tags to manage your images. You should use the “Stable” tag with base images of your container and use the “Unique” tag with your deployment containers. - Build one image for all environments.
Suppose you have multiple development environments like staging, QA, UAT, production, etc. Instead of creating a separate image for each environment. In that case, you should create one image for all the environments. The configuration or environment-specific configuration will be picked from the .env files and will not be part of the image itself. That will result in consistency and improved testing of your application. - Use Fixed Labels for Immutability.
Do not push newer versions to the same image tag, it will result in inconsistent images during the build, and it will be tough to track bugs and fixes. Try to use an immutable (static) tag or label in production environment to ensure your deployment does not change automatically if someone updates the same tag with a different image.

