Skip to main content

Managing Docker Performance

1. Monitoring Resource Usage

Resource Command Description
CPU Usage docker stats Displays real-time CPU usage for running containers
Memory Usage docker stats --format "table {{.Container}}\t{{.MemUsage}}" Shows memory consumption per container
Disk I/O docker stats --format "table {{.Container}}\t{{.BlockIO}}" Displays block I/O statistics
Network I/O docker stats --format "table {{.Container}}\t{{.NetIO}}" Shows network input/output statistics

Example: Monitoring CPU and Memory Usage

docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}" --no-stream
Note: The --no-stream flag prevents continuous output, useful for scripting or one-time checks.

Example: Filtering Containers by Name

docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" --filter name=web
Warning: docker stats can be resource-intensive when used with many containers. Use filters to limit output.

2. Optimizing Build Cache

Instruction Description Best Practice
COPY --from Copies files from another build stage or image Use multi-stage builds to reduce layer size and improve cache efficiency
COPY . . Copies all files from the host to the container Use .dockerignore to exclude unnecessary files and directories
RUN apt-get update && apt-get install Installs packages using the package manager Combine RUN commands to reduce layers and avoid caching issues

Example: Efficient Dockerfile with Cache Optimization

FROM node:18-alpine

# Copy package files first to leverage cache
COPY package*.json ./
RUN npm ci --only=production

# Copy application code after dependencies are installed
COPY . .

EXPOSE 3000
CMD ["npm", "start"]
Note: The order of instructions in a Dockerfile is crucial for effective caching. Changes to earlier instructions invalidate subsequent layers.
Warning: Avoid copying entire directories without .dockerignore, as it can cause unnecessary rebuilds.

3. Using Volume Performance Options

Option Description Notes
--volume-driver Specifies the volume driver to use for creating volumes. Defaults to local. Can be set to aws, gce, or custom drivers.
--mount Mounts a volume or bind mount into the container. More flexible than -v, supports additional options like bind-propagation.
--tmpfs Mounts a temporary filesystem in memory. Useful for ephemeral data, not persisted on disk. Ideal for cache or temporary files.

Example: Using --tmpfs

docker run --tmpfs /app/cache:rw,noexec,nosuid,size=100m myapp

Example: Mounting a volume with performance options

docker run --mount type=volume,source=myvol,target=/app/data,bind-propagation=rshared myapp
Note: Performance can be improved by using --tmpfs for temporary data and --mount with bind-propagation for shared volumes.
Warning: --tmpfs is not persisted across container restarts and uses memory.

4. Configuring Storage Driver Settings

Driver Description Default Notes
aufs Union filesystem, older driver Yes (on some systems) DEPRECATED in Docker 20.10+
overlay2 Union filesystem, modern and preferred Yes (on most systems) Recommended for production
btrfs Btrfs filesystem driver No Requires Btrfs filesystem
zfs ZFS filesystem driver No Requires ZFS pool
devicemapper Device mapper driver (legacy) No DEPRECATED in Docker 20.10+

Example: Configure overlay2 storage driver

{
  "storage-driver": "overlay2"
}
Note: The storage driver must be set at Docker daemon startup and cannot be changed without reconfiguring the daemon.

Storage Driver Configuration Tips

  • Use overlay2 for most modern Linux systems.
  • Ensure sufficient disk space and I/O performance for the storage backend.
  • For production, overlay2 is recommended over aufs or devicemapper.

5. Implementing Resource Constraints

Resource Type Configuration Option Description Default Value
CPU --cpus Limit the number of CPUs available to a container Unlimited
Memory --memory Set the maximum amount of memory a container can use Unlimited
Memory Swap --memory-swap Set the total memory plus swap a container can use Unlimited
Memory Reservation --memory-reservation Set the memory that is reserved for the container Unlimited
CPU Shares --cpu-shares Set relative CPU shares for a container 1024
CPU Period --cpu-period Set the CPU period for CPU quota enforcement (microseconds) 100,000
CPU Quota --cpu-quota Set the CPU time that a container can use in a period (microseconds) -1 (unlimited)

Example: Limiting CPU and Memory Usage

docker run --cpus=1.5 --memory=512m my-app

Example: Setting Memory Swap Limit

docker run --memory=1g --memory-swap=2g my-app
Note: Setting --memory-swap to the same value as --memory disables swap.
Warning: If --memory-swap is set to a value less than --memory, it will cause an error.

6. Optimizing Network Performance

Option Values Description
--network bridge, host, none Set container network mode. host offers best performance by sharing host network stack.
--network-alias alias-name Assigns an alias to a container for easier service discovery in custom networks.
--add-host hostname:ip Adds a custom entry to the container's /etc/hosts file for faster DNS resolution.

Example: Using host network mode for performance

docker run --network host nginx

Example: Adding custom host entry

docker run --add-host myapp.local:127.0.0.1 nginx
Note: Using --network host disables network isolation and should be used carefully in production environments.

Network Optimization Tips

  • Use --network host for high-performance, low-latency communication.
  • Use custom networks with --network-alias for better service discovery.
  • Use --add-host to reduce DNS lookups in containers.

7. Using BuildKit for Faster Builds

Example: Enabling BuildKit

export DOCKER_BUILDKIT=1
Feature Description Notes
DOCKER_BUILDKIT=1 Enables BuildKit for docker build commands Set as environment variable or in ~/.docker/config.json
buildkit BuildKit driver option in docker config Can be set to "enabled" or "disabled"
Note: BuildKit is enabled by default in Docker 18.09 and later.

Key Benefits of BuildKit

  • Parallel builds with better caching
  • Improved layer caching
  • Reduced image sizes through pruning
  • Support for multi-platform builds

BuildKit Optimization Steps

  1. Enable BuildKit via environment variable or config
  2. Use --no-cache for clean builds
  3. Optimize Dockerfile instructions for caching
  4. Utilize --target for multi-stage builds

8. Parallel Container Execution

Example: Running Multiple Containers Concurrently

docker run -d --name app1 myapp:latest
docker run -d --name app2 myapp:latest
docker run -d --name app3 myapp:latest
Option Values Description
--detach, -d true Run containers in background
--name container-name Assign a name to the container
Note: Parallel execution is managed by the Docker daemon and OS-level resource allocation.
Warning: Ensure sufficient system resources (CPU, memory) to avoid performance degradation.

Best Practices for Parallel Execution

  • Monitor resource usage with docker stats
  • Use resource limits (--memory, --cpus) to prevent overconsumption
  • Consider using Docker Compose for managing multi-container setups

9. Minimizing Image Pulls

Option Values Notes
docker pull image:tag Explicitly pull image to local registry
docker build -t image:tag . Build and tag image locally without pulling
--no-cache true Force rebuild without using cached layers

Example: Pulling image with specific tag

docker pull nginx:1.21

Example: Building image without cache

docker build --no-cache -t myapp:latest .
Note: Using --no-cache ensures that all layers are rebuilt, which can help avoid outdated dependencies but increases build time.

10. Using Local Registry for Caching

Example: Setting up a local registry with caching

docker run -d \
  --name local-registry \
  --restart=always \
  -p 5000:5000 \
  registry:2
Configuration Description Default
registry.port Port to run the local registry on 5000
registry.storage.path Storage path for registry data /var/lib/registry
Note: The local registry must be configured to use a volume or bind mount for persistent storage.

Workflow: Pushing to local registry

  1. Tag image with local registry address: docker tag myapp localhost:5000/myapp
  2. Push image to local registry: docker push localhost:5000/myapp
  3. Use image from local registry in deployments: docker run localhost:5000/myapp

11. Optimizing Layer Caching Strategy

Instruction Description Best Practice
FROM Base image for the Dockerfile Use a specific tag (e.g., node:18-alpine) to ensure consistency and avoid pulling latest
COPY / ADD Copy files from host to container Order instructions to minimize cache invalidation; place less frequently changed files first
RUN Execute commands in the container Combine multiple RUN instructions with && to reduce layers and avoid unnecessary cleanup
WORKDIR Set working directory Use WORKDIR to avoid repeating paths in subsequent commands
ENV Set environment variables Use ENV for values that change infrequently to avoid rebuilding layers unnecessarily

Example: Layer Caching Optimization

FROM node:18-alpine

# Copy package files first to leverage layer caching
COPY package*.json ./

# Install dependencies before copying app code
RUN npm ci --only=production

# Copy application code after installing dependencies
COPY . .

EXPOSE 3000
CMD ["npm", "start"]
Note: Docker uses a content-based hash to determine if a layer has changed. Any change in the instruction order or content will invalidate the cache and force re-building of subsequent layers.

Key Tips for Layer Caching

  • Minimize file changes to keep layers cached
  • Place stable instructions first (e.g., dependencies, base image)
  • Use .dockerignore to exclude unnecessary files from being copied into the image
  • Avoid RUN commands with frequent changes (e.g., apt-get update)

12. Profiling Container Performance

Metric Description Tools Notes
CPU Usage Percentage of CPU time consumed by the container docker stats, top Can be normalized per core for comparison
Memory Usage Amount of RAM used by the container docker stats, ps Includes cache and buffers
Network I/O Data sent and received by the container docker stats, iftop Can be monitored per container or globally
Disk I/O Read and write operations on storage devices iostat, iotop Useful for identifying bottlenecks in storage-heavy apps

Example: Using docker stats to monitor container performance

docker stats {container_id}

Example: Collecting detailed stats using docker inspect

docker inspect {container_id} | grep -A 5 "Stats"
Note: docker stats provides real-time metrics, while docker inspect offers more static details about container configuration and runtime state.

Key Metrics to Monitor

  • CPU usage percentage
  • Memory consumption (RSS, cache)
  • Network throughput (bytes in/out)
  • Disk I/O operations (read/write)

Was this article helpful?