Docker Full Tutorial — Part 9: Docker Security Best Practices

By Suraj Ahir December 03, 2025 6 min read

Docker — Multi-stage Builds
Docker — Multi-stage Builds
← Part 8 Docker Tutorial · Part 9 of 12 Part 10 →

Docker makes it easy to ship applications fast, but speed without security creates problems. Many Docker deployments in production have serious security vulnerabilities that are avoidable with basic knowledge. This part covers the most important security practices every Docker user should follow — not theoretical concepts, but practical steps you can apply today.

Never Run Containers as Root

By default, Docker containers run as the root user. This is dangerous. If an attacker exploits a vulnerability in your application and gains code execution inside the container, they have root access. Even though they are inside a container, there are documented container escape vulnerabilities. Running as a non-root user significantly reduces the blast radius of a compromise.

Non-Root User in Dockerfile
FROM python:3.11-slim

# Create a non-root user
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

# Change ownership of app files
RUN chown -R appuser:appgroup /app

# Switch to non-root user
USER appuser

EXPOSE 5000
CMD ["python", "app.py"]

Use Official and Minimal Base Images

Every package in your base image is a potential vulnerability. The less software you include, the smaller your attack surface. Always start from official images from Docker Hub verified publishers, and prefer slim or minimal variants.

Image Choices
# Bad: generic large image
FROM ubuntu:22.04

# Better: official language image slim variant
FROM python:3.11-slim

# Best for production: Alpine or distroless
FROM python:3.11-alpine
FROM gcr.io/distroless/python3  # Google's distroless — no shell at all

Scan Images for Vulnerabilities

Docker has a built-in vulnerability scanner powered by Snyk. Use it regularly on your images:

Vulnerability Scanning
# Scan an image
docker scout cves my-app:latest

# Scan local image
docker scout cves --type image my-app:latest

# Get recommendations to fix vulnerabilities
docker scout recommendations my-app:latest

# Alternative: Trivy (popular open-source scanner)
trivy image my-app:latest

Read-Only Containers

If your application does not need to write to the filesystem at runtime, run the container with a read-only root filesystem. This prevents any malware or exploit from writing files or installing tools inside the container.

Read-Only Container
# Run with read-only filesystem
docker run --read-only -p 5000:5000 my-app:latest

# If the app needs some writable directories, use tmpfs
docker run --read-only   --tmpfs /tmp   --tmpfs /var/run   -p 5000:5000 my-app:latest

Managing Secrets Safely

Never put secrets — passwords, API keys, tokens — in environment variables passed directly in docker run commands or hardcoded in Dockerfiles. These show up in docker inspect output and in logs. Use Docker secrets (in Swarm mode) or mount secret files:

Secrets Best Practices
# BAD: secret visible in docker inspect
docker run -e DB_PASSWORD=mysecret my-app

# BETTER: use a .env file (never commit to git)
docker run --env-file .env my-app

# IN COMPOSE: use secrets
services:
  app:
    image: my-app
    secrets:
      - db_password
secrets:
  db_password:
    file: ./secrets/db_password.txt

Limit Container Resources

Without resource limits, a single misbehaving container can consume all CPU and memory on the host, taking down every other container. Always set limits in production:

Resource Limits
# Limit CPU and memory
docker run -d   --memory="512m"   --cpus="1.5"   --memory-swap="1g"   my-app:latest

# In docker-compose.yml
services:
  app:
    image: my-app
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '1.5'

Docker Daemon Security

In Part 10, we will cover Docker with CI/CD pipelines — automating image builds, tests, and deployments using GitHub Actions and other tools.

Container Security Scanning

Even carefully built images can contain vulnerabilities in their base layers or dependencies. Vulnerability scanning tools analyze images against databases of known CVEs (Common Vulnerabilities and Exposures). Docker Scout is built into Docker Desktop and the Docker CLI: docker scout cves myimage:latest shows vulnerabilities in an image. Trivy is a popular open-source scanner: trivy image myimage:latest. Integrating scanning into CI/CD pipelines — failing builds when critical vulnerabilities are detected — is a security best practice. Most cloud container registries (ECR, GCR, ACR) also offer built-in image scanning.

Resource Limits and Security Options

Docker containers share the host kernel, which means a container that consumes all available memory or CPU can impact other containers and the host system. Set resource limits to prevent this:

Resource Limits
# Limit memory to 512MB and CPU to 0.5 cores
docker run -d   --memory="512m"   --cpus="0.5"   --memory-swap="512m"   myapp:latest

# Additional security hardening options
docker run -d   --read-only \                    # Read-only filesystem
  --no-new-privileges \            # Prevent privilege escalation
  --cap-drop ALL \                 # Drop all Linux capabilities
  --cap-add NET_BIND_SERVICE \     # Add only what's needed
  myapp:latest

Practice Exercise

Run a container with explicit resource limits: docker run -d --memory="256m" --cpus="0.5" nginx. Use docker stats to monitor its resource usage. Then run the container with --read-only flag and observe which operations fail because they need to write to the filesystem. Add --tmpfs /tmp to provide a writable temporary directory and verify that resolves the issue. This exercise builds practical understanding of container resource management and filesystem security.

Building Cloud Intuition Over Time

Cloud computing is a domain where deep intuition — the ability to make good architectural decisions quickly, to diagnose problems efficiently, and to anticipate how systems will behave under load — develops through accumulated hands-on experience. Every project you build on cloud infrastructure teaches you something that cannot be learned from documentation alone. The cost surprises, the permission errors, the networking debugging sessions, the performance investigations — these are not obstacles to learning, they are the learning. The engineers who have built genuinely deep cloud intuition have usually accumulated it through many projects over several years, not from any single course or certification. Start building things, make mistakes safely in learning environments, and accumulate that experience deliberately.

Disclaimer: This content is for educational purposes only. SRJahir Tech does not guarantee any specific outcome or job placement.