Docker Part-5

Docker Best Practices

Docker Best Practices

Use Official Docker Image as Base Image

Instead of using Ubuntu as a base image and installing dependencies on it, take a base image (e.g., Node). This will have all dependencies installed and would have been made with best practices.

Use Specific Image Versions

If a version is not specified, the latest version will be installed, which may not be suitable for all cases.

Use Small-Sized Official Images

Images based on full-blown OS distributions include all dependencies, many of which may not be needed.

Using smaller images results in:

  • Less attack surface
  • More security
  • Lower storage usage
  • Easier transfer

Optimize Caching Image Layers

If a layer is reinstalled, all the following layers will be reinstalled as well.

Order Dockerfile commands from least to most frequently changing to maximize cache usage.

Example:


FROM node:20.0.2-alpine
WORKDIR /app

# Copy package.json and package-lock.json before project files
COPY package.json package-lock.json .  

# Install dependencies only when package.json changes (cache-efficient)
RUN npm install --production  

# Now copy the project files (won’t invalidate npm install cache)
COPY myapp /app  

# Start the application
CMD ["node", "src/index.js"]
    

Key Takeaways:

  • DO NOT re-run npm install if only project files change.
  • Re-run npm install when package.json or package-lock.json changes.
  • Use .dockerignore to exclude unnecessary files.

Use Multi-Stage Builds

The Multi-Stage Build technique helps optimize Docker images by reducing their final size and improving efficiency.

Example:


# Build stage
FROM maven AS build
WORKDIR /app
COPY myapp /app
RUN mvn package

# Runtime stage
FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps/
    

Key Takeaways:

  • Multi-stage builds separate the build process from the final image.
  • The first stage (build stage) compiles the application.
  • The second stage (runtime stage) includes only the necessary artifacts.
  • Only the last stage defines the final image.

Benefits of Multi-Stage Builds:

  • Reduces image size by excluding build tools.
  • Improves security by keeping only necessary files in the final image.
  • Enhances efficiency by preventing build environment bloat.

Use the Least Privileged User

Create a dedicated user and group in the Dockerfile:

RUN groupadd -r tom && useradd -g tom tom

Some images already include a generic user (e.g., Node includes the node user). Use it with:

USER node

Scan Images for Vulnerabilities

Login to Docker and scan for vulnerabilities using:

docker scout cves <ImageName>