keepcalculator

06 Numbers and Powers

Docker Best Practices for Secure, Reliable Containers

Card No. 06·61740 · Updated · Standard formula, shown below

Docker best practices help you build images that are smaller, safer, easier to update, and more predictable across development and production. Use trusted base images, keep build instructions reproducible, run containers with only the permissions they need, and manage configuration and data outside the image.

Build Images That Are Small and Reproducible

A Docker image is assembled from instructions in a Dockerfile, usually as a series of layers. Thoughtful layer ordering and a minimal build context reduce unnecessary work and make images easier to transfer and maintain.

  • Choose an appropriate base image. Prefer a maintained image that includes only what the application needs. Minimal images can reduce size and the number of included components, but confirm they support your runtime, certificates, and troubleshooting needs.
  • Pin dependencies deliberately. Use lockfiles and version constraints for application packages. Pinning a base image by digest can make builds more repeatable; it also means updates will not arrive automatically, so schedule a process to review and refresh it.
  • Use a .dockerignore file. Exclude items such as local dependencies, version-control metadata, build output, and secret files from the build context. This speeds up transfers and helps prevent accidental inclusion of sensitive or irrelevant files.
  • Order Dockerfile instructions for useful caching. Copy dependency manifests and install dependencies before copying frequently changing source files. Docker can then reuse earlier layers when only application code changes.

For example, a Node.js project might copy package.json and its lockfile, run npm ci, and then copy the source. The exact commands depend on the project; the general principle is to put stable inputs before files that change often. Avoid combining unrelated steps just to reduce the number of lines: readable instructions make builds easier to review.

Use Multi-Stage Builds and Clear Dockerfiles

Multi-stage builds separate the environment used to compile or package an application from the image used to run it. This can keep compilers, development tools, and intermediate files out of the final image.

FROM node:22 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-slim
WORKDIR /app
COPY --from=build /app/dist ./dist
CMD ["node", "dist/server.js"]

This example illustrates the pattern, not a universal production configuration: the runtime may need additional files, and the appropriate Node.js version depends on the application. Use explicit working directories, group related instructions, and choose the exec form of CMD or ENTRYPOINT when the application should receive operating-system signals directly.

Do not assume a successful build proves the image is reproducible. External downloads, mutable tags, and unpinned packages can change what a later build produces. Where repeatability matters, control those inputs and record the image version or digest used for deployment.

Run Containers With Least Privilege

Containers share the host operating-system kernel. They provide useful isolation, but they are not a substitute for securing the host or treating application code as trusted. Reduce the impact of a compromised process by limiting its privileges and access.

  • Run the application as a non-root user when the image and application support it. Create or select that user explicitly rather than assuming a base image does so.
  • Do not use privileged mode unless a specific, understood requirement calls for it. Avoid adding capabilities or mounting host paths unnecessarily.
  • Keep the container filesystem read-only where practical, and provide writable locations only where the application needs them.
  • Set CPU and memory limits where appropriate for the deployment environment, and monitor whether the limits fit real workload needs.
  • Keep Docker Engine, base images, and application dependencies updated. Scan images with suitable tooling and investigate findings rather than treating a scan result as a guarantee of safety.

Security settings can affect functionality. Test them with the actual application: a process that needs to write temporary files, bind to a port, or access a device may require a carefully scoped adjustment.

Keep Secrets, Configuration, and Data Outside Images

Do not bake passwords, API tokens, private keys, or environment-specific settings into an image. Image layers can remain available even if a later Dockerfile instruction removes a file, and images may be copied to registries or other systems. Use an appropriate secrets-management mechanism for the runtime, and ensure secret files are excluded from the build context.

Use environment variables or mounted configuration for values that vary between environments, while remembering that environment variables are not automatically a secure secrets store. Restrict who can inspect container configuration and choose a more suitable secret-delivery mechanism for sensitive values.

Container writable layers are generally tied to the container lifecycle. For data that must persist, use a volume or an external storage service, and plan backups and recovery separately. A volume provides persistence beyond a container’s writable layer; it does not by itself provide backups, encryption, or protection from deletion.

Make Services Observable and Predictable

A container should run its main process in the foreground and exit meaningfully when that process ends. Avoid relying on a shell wrapper that fails to forward termination signals; use exec-form commands or ensure a wrapper replaces itself with the application process.

Write logs to standard output and standard error so the container platform can collect them. Add health checks when they can report a meaningful condition, but distinguish “the process is running” from “the service can handle requests.” A health check should be lightweight and should not create excessive load or depend on an unrelated service unless that dependency is intentionally part of the health definition.

Use explicit port declarations and document which ports the application listens on. In Docker, declaring a port in an image does not by itself publish it to the host; publishing is configured when the container is run or by the orchestration setup. Keep service discovery, restart behavior, and resource allocation in the deployment configuration appropriate to your environment.

Common Docker Mistakes to Avoid

  • Using latest as a deployment strategy. A mutable tag can point to different image contents over time. Use a deliberate versioning and update process so deployments can be understood and rolled back.
  • Putting everything in one container. A container should generally have a clear main responsibility. Separate services when their lifecycles, scaling needs, or operational responsibilities differ, rather than splitting every process automatically.
  • Assuming containers are lightweight virtual machines. Containers share the host kernel and often start quickly, but they still need resource limits, monitoring, and host-level maintenance.
  • Using a container as a backup. Recreating a container is different from restoring its persistent data. Test backup and recovery procedures for volumes and external stores.
  • Ignoring build and runtime differences. A build that works on one machine can fail elsewhere because of architecture, missing files, or unpinned dependencies. Test the built image in an environment close to the intended deployment.

Frequently Asked Questions

Should I use Alpine Linux for every Docker image?
No. Alpine can produce small images, but compatibility and debugging needs vary. Choose a base image that supports your application and dependencies, then compare size, maintenance, and operational trade-offs.

Is Docker safe to run as root?
The Docker daemon and some container configurations can have substantial host access. Run application processes as non-root where practical, avoid unnecessary privileges, and secure access to the Docker daemon.

Do Docker containers keep data after they are removed?
Data in a container’s writable layer is not a dependable persistence strategy. Use volumes or external storage for data that must outlive a container, and arrange backups independently.

Does exposing a port in a Dockerfile make it public?
No. An EXPOSE instruction documents a port the application uses; it does not publish that port to the host. Publishing depends on the run command or deployment configuration.

How often should Docker images be updated?
Review and rebuild images regularly, including updates to base images and dependencies. The right cadence depends on the application and its risk, but updates should be tested and deployed through a repeatable process rather than left indefinitely.

Are Docker best practices the same in production and development?
The core principles—reproducible builds, least privilege, and clear data handling—apply to both. Production usually needs stricter controls for secrets, access, monitoring, updates, backups, and resource limits.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →