Best Docker Practices
1. Optimize Image Size
- Use Official Images: Start with trusted and official Docker images as a base.
-
Use Minimal Base Images: Lightweight images like
alpine
are smaller, faster to download, and reduce the attack surface. -
Minimize Layers: Combine commands to minimize the number of layers in your Dockerfile (e.g., use
&&
to chain commands in a singleRUN
statement). -
Clear Cache: Remove package managers and caches after installation (e.g.,
apt-get clean
for Ubuntu).
2. Secure Images and Containers
- Use Multi-Stage Builds: Separate build dependencies from the runtime environment, making production images leaner.
-
Run as Non-Root: Avoid using the root user inside your containers. Use
USER
in Dockerfile to specify a non-root user. - Keep Docker Updated: Regularly update Docker itself and any images used.
-
Use
COPY
Instead ofADD
:COPY
is more straightforward and doesn’t perform automatic decompression likeADD
, reducing ambiguity. -
Leverage
.dockerignore
: To avoid copying unnecessary files to the image, create a.dockerignore
file similar to.gitignore
.
3. Optimize Dockerfile Instructions
- Order Instructions to Leverage Caching: Place less-frequently changing instructions at the top of your Dockerfile to leverage Docker’s caching mechanism.
-
Use Specific Versions: Avoid using
latest
tags in production environments; pin images to specific versions to ensure stability and reproducibility.
4. Use Docker Compose for Multi-Container Applications
- Separate Concerns by Using Multiple Containers: For complex applications, break down services (e.g., separate databases, web servers, and application layers) into different containers.
- Use Docker Compose for Local Development: It makes handling complex multi-container applications easier and creates a consistent environment.
5. Limit Resource Usage
-
Set Memory and CPU Limits: Use Docker’s resource constraints to avoid a single container using excessive resources (
--memory
,--cpus
). -
Use Read-Only Filesystems: Limit filesystem access to read-only whenever possible (
--read-only
).
6. Logging and Monitoring
- Centralize Logging: Configure Docker to send logs to a centralized logging service (like ELK Stack, Splunk, or AWS CloudWatch).
- Monitor Containers: Use tools like Prometheus or Grafana to monitor performance, memory, and CPU usage.
7. Secure Communication Between Containers
- Use Private Networks: Avoid exposing unnecessary ports and use Docker networks to isolate services.
- Use Secrets Management: For sensitive information like passwords and keys, use Docker Secrets, especially in swarm mode.
8. Optimize Container Health and Lifecycle
-
Set Health Checks: Add health checks in your Dockerfile to ensure the container is healthy (
HEALTHCHECK
directive). -
Clean Up Unused Containers and Images: Regularly clean up unused images, containers, volumes, and networks (
docker system prune
) to save disk space.
9. Use Multi-Stage Builds
Multi-stage builds allow you to create leaner production images by separating build dependencies from runtime requirements.
- Build Stage: Create a first stage for compiling or building the application. This stage can include all necessary dependencies and tools.
- Final Stage: Copy only the required files from the build stage to a smaller base image. This results in a cleaner, smaller final image.
- Example: We are using Alpine image for laravel
FROM serversideup/php:8.2-cli-v2.2.1 as builder
ARG LARAVEL_ENV_ENCRYPTION_KEY
COPY ./ /var/www
WORKDIR /var/www
RUN <<EOF
composer install --ignore-platform-reqs --no-interaction --no-dev --prefer-dist --optimize-autoloader
php artisan env:decrypt --force
EOF
# ================================================ #
FROM serversideup/php:8.2-fpm-nginx-v2.2.1
ENV AUTORUN_LARAVEL_MIGRATION=true
ENV SSL_MODE=off
ENV PHP_MEMORY_LIMIT=128M
ENV PHP_MAX_EXECUTION_TIME=30
WORKDIR /var/www/html
COPY --chown=$PUID:$PGID --from=builder /var/www/ /var/www/html
RUN php artisan optimize
HEALTHCHECK CMD curl -s --fail http://localhost/health || exit 1
CMD ["su", "webuser", "-c", "php artisan schedule:work"]
EXPOSE 80
10. Use Build Kit to speed up Docker builds
Docker BuildKit is an opt-in image building engine which offers substantial improvements over the traditional process. BuildKit creates images layers in parallel, accelerating the overall build process.
Although BuildKit is now stable, Docker still doesn't ship with it on by default. Make sure to enable it in your Docker client if you want to use its features. There's an active proposal to make BuildKit the standard build engine but there are still unresolved issues preventing the switch.
===================================
Adhering to these best practices can streamline development, improve security, and make it easier to scale and maintain Docker environments.
Support if you found this helpful😉
No Money 🙅🏻♀️ just Subscribe to me YouTube channel.
Linktree Profile: https://linktr.ee/DevOps_Descent
GitHub: https://github.com/devopsdescent
Top comments (12)
There is no need to have multiple RUN statements joined together using
&&
. Docker support heredocs which makes for easier reading.docker.com/blog/introduction-to-he...
Thanks for the Tip. :)
I have updated the article.
Insightful
Thanks🤗
thank you for sharing this
Happy to help 🤗,keep learning 🤭
Good Article.
Thanks for appreciation 🤗
Thanks guys for all these materials. I'm a Devops fresher
Happy to help. Keep learning and growing in this field.😉
Some comments may only be visible to logged-in visitors. Sign in to view all comments.