Base vs Parent vs Custom Image
Understanding the difference between base image, parent image, and custom image is essential before diving into best practices.
scratch (the empty Docker image):
Best Practices
One application per image
One application per image
Each image should be focused on a single application or service. For example, create separate images for a web server and a database.This enables better scalability, maintainability, and reusability, while also reducing image size by including only the necessary dependencies.
Do not store data or state in containers
Do not store data or state in containers
Containers are ephemeral — they can be created and destroyed at any time. Data stored inside a container is lost when the container is removed.Use Docker volumes or external storage solutions (e.g., Redis, PostgreSQL) to persist data outside of the container.
Keep images updated
Keep images updated
Regularly update your images and dependencies to include the latest security patches. Stale base images are a common source of vulnerabilities.
Scan images for vulnerabilities
Scan images for vulnerabilities
Regularly scan images using
docker scan or third-party tools like Trivy to detect known vulnerabilities before deployment.Avoid installing unnecessary packages
Avoid installing unnecessary packages
Only install the dependencies required for your application. Remove build tools and temporary files after installation to keep the image lean.
Use a .dockerignore file
Use a .dockerignore file
Exclude unnecessary files and directories from the build context to reduce image size and speed up builds.
Leverage multi-stage builds
Leverage multi-stage builds
Use multi-stage builds to separate the build environment from the runtime environment. This ensures only necessary files end up in the final image, improving both size and security.
Optimize layers
Optimize layers
Combine
RUN, COPY, and ADD commands where possible to minimize the number of layers and reduce image size — but keep readability in mind.Use explicit tags for base images
Use explicit tags for base images
Use a non-root user
Use a non-root user
Avoid running your application as the root user. Create a dedicated non-root user to reduce the attack surface.
Document the image with labels
Document the image with labels
Use
LABEL to record metadata such as maintainer, version, and description. This helps CI/CD pipelines, compliance tracking, and discoverability in registries.Verify image authenticity
Verify image authenticity
Use official images or verified publisher tags from Docker Hub or trusted registries.Enable Docker Content Trust (DCT) to ensure images are signed and verified:
Use minimal or slim base images
Use minimal or slim base images
Start with a minimal base image like
alpine or debian-slim to reduce the image size and attack surface. Only install what is strictly necessary.Use distroless images for production
Use distroless images for production
Distroless images contain only the application and its runtime dependencies — no package manager, shell, network tools, or text editors. This minimizes the attack surface significantly.Examples:
gcr.io/distroless/python3-debian12gcr.io/distroless/base-debian12