Skip to content

Creating container images

One of the first steps to move to Kubernetes is making sure that the application can run in containers. For this, all sub-systems of the application, need to be packaged in container images. This means creating a Dockerfile for each application.

Creating Dockerfiles is considered common knowledge, and not covered on this page.

  • Images should be as small as possible, reducing vulnerabilities, disk usage, number of dependencies.
    • alpine images are a good starting point.
    • Distroless images are also a good choice.
    • Ultimately, consider scratch images for compiled applications.
  • Base images should be pinned using a digest, making sure every build uses exactly the same base image.
  • Regularly update base images. Use Renovate to automate this process.
  • Use official images.
  • Use multi-stage builds, so the only files required by the application are left in the service image. This way, a full blown SDK image can be used during the build process, while the end result can be a minimal runtime (service) image. See example for details.
  • By default, pull base images from Harbor.
    • Make sure the container registry is configurable using an ARG-variable so you can easily build locally.
  • Include proper LABEL metadata
  • Prefer ENV variables for runtime configuration
  • Layer Management:
    • Combine related commands in single RUN instructions
    • Order layers by change frequency (less frequent changes first)
    • Use .dockerignore to exclude unnecessary files
  • Run containers as non-root users
  • Remove unnecessary permissions
  • Implement read-only root filesystem when possible
  • Remove unnecessary packages and tools
  • Clear package manager caches
  • Delete sensitive data and credentials
  • Use multi-stage builds to minimize attack surface
  • DO NOT put secrets in your image!
  • For static HTML content, nginx is proven to be a good choice.