DevOps

Docker Advanced

Advanced Docker concepts: multi-stage builds, Docker networks, volumes, security, and Docker Compose for multi-container applications.

By TechCoder TeamLast updated: 2026-06-02
In a Nutshell

Advanced Docker concepts: multi-stage builds, Docker networks, volumes, security, and Docker Compose for multi-container applications. This hands-on tutorial focuses on practical implementation of docker advanced concepts.

Docker Advanced

Building on Docker fundamentals, let's explore advanced concepts for production-grade containerization.

Advanced Dockerfile Techniques

Build Arguments and Variables

# Build arguments (passed at build time)
ARG NODE_VERSION=18
ARG APP_VERSION=1.0.0

FROM node:${NODE_VERSION}-alpine

# Labels with build info
LABEL maintainer="devops@example.com"
LABEL version="${APP_VERSION}"
LABEL build_date="${BUILD_DATE}"

# Environment variables (available at runtime)
ENV NODE_ENV=production
ENV APP_VERSION=${APP_VERSION}
ENV PORT=3000

WORKDIR /app

# Use ARG for conditional logic
ARG INSTALL_DEV=false
RUN if [ "$INSTALL_DEV" = "true" ]; then npm ci; else npm ci --only=production; fi
# Build with arguments
docker build --build-arg NODE_VERSION=20 --build-arg APP_VERSION=2.0.0 -t myapp:2.0 .

Advanced Multi-stage Patterns

# Dependencies stage - cache npm install
FROM node:18-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Development stage
FROM node:18-alpine AS development
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
CMD ["npm", "run", "dev"]

# Production stage
FROM node:18-alpine AS production
WORKDIR /app
ENV NODE_ENV=production

# Copy only necessary artifacts
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./

# Security: Run as non-root
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001 && \
    chown -R nodejs:nodejs /app
USER nodejs

EXPOSE 3000
CMD ["node", "dist/main.js"]

ONBUILD Triggers

# Base image with ONBUILD
FROM node:18-alpine AS base
WORKDIR /app
ONBUILD COPY package*.json ./
ONBUILD RUN npm ci --only=production
ONBUILD COPY . .

# Usage: FROM mybase
# Triggers execute when building the child image

Docker Security

Running as Non-Root

# Create non-root user
FROM node:18-alpine
RUN addgroup -g 1001 -S appgroup && \
    adduser -u 1001 -S appuser -G appgroup
WORKDIR /app
COPY --chown=appuser:appgroup . .
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]
# Run with security options
docker run --user 1000:1000 nginx
docker run --read-only --tmpfs /tmp --tmpfs /var/cache/nginx nginx
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx
docker run --security-opt=no-new-privileges:true nginx

Content Trust and Signing

# Enable Docker Content Trust
export DOCKER_CONTENT_TRUST=1

# Sign images when pushing
docker trust sign registry.example.com/myapp:1.0

# View signatures
docker trust inspect registry.example.com/myapp:1.0

# Add signers
docker trust signer add --key signer.pub alice registry.example.com/myapp

Scanning for Vulnerabilities

# Docker Scout (Docker Desktop)
docker scout quickstart
docker scout cves myapp:latest

# Trivy
 trivy image myapp:latest

# Snyk
docker scan myapp:latest

# Grype
grype myapp:latest

Docker Networks Deep Dive

Custom Network Drivers

# Bridge network (default)
docker network create --driver bridge my-bridge

# Overlay network (multi-host)
docker network create --driver overlay my-overlay

# Macvlan (direct MAC)
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 my-macvlan

# IPvlan (L2/L3)
docker network create -d ipvlan \
  --subnet=192.168.1.0/24 \
  -o parent=eth0 my-ipvlan

Container DNS and Service Discovery

# Custom DNS
docker run --dns 8.8.8.8 --dns 8.8.4.4 nginx

# DNS search domain
docker run --dns-search example.com nginx

# Hosts file entries
docker run --add-host myhost:192.168.1.100 nginx

# Use container name as DNS
docker run --name web --network mynet nginx
docker run --name api --network mynet node  # can ping 'web'

Network Troubleshooting

# Inspect network
docker network inspect bridge

# Container network info
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container

# Execute network commands
docker exec container ping google.com
docker exec container nslookup api
docker exec container netstat -tlnp

# Packet capture
docker run --rm --net=container:target nicolaka/netshoot tcpdump -i eth0

Advanced Docker Compose

Profiles and Environment Overrides

# docker-compose.yml
version: '3.8'
services:
  web:
    build: ./web
    ports:
      - "80:80"
    profiles:
      - frontend
      - full
    
  api:
    build: ./api
    profiles:
      - backend
      - full
    
  db:
    image: postgres:15
    profiles:
      - backend
      - full
      
  test:
    build:
      context: ./api
      target: test
    profiles:
      - test
    command: npm test
# Start with profile
docker-compose --profile full up -d
docker-compose --profile test run --rm test
# docker-compose.override.yml (automatically merged)
version: '3.8'
services:
  web:
    volumes:
      - ./web/src:/app/src  # Hot reload in dev
    environment:
      - DEBUG=true
      
  db:
    ports:
      - "5432:5432"  # Expose for local access
# docker-compose.prod.yml
version: '3.8'
services:
  web:
    restart: always
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
        
  db:
    volumes:
      - db-data-prod:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
# Production deployment
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Health Checks and Restart Policies

services:
  app:
    image: myapp:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
      start_interval: 5s
    restart: unless-stopped
    # Options: "no", "always", "on-failure", "unless-stopped"

Secrets and Configs

services:
  api:
    image: myapi:latest
    secrets:
      - source: api_key
        target: /run/secrets/api_key
        mode: 0400
      - db_password
    configs:
      - source: app_config
        target: /app/config.json

secrets:
  api_key:
    external: true  # Created with docker secret create
  db_password:
    file: ./secrets/db_password.txt

configs:
  app_config:
    file: ./config/app.json

Docker Swarm (Orchestration)

Initialization and Services

# Initialize swarm
docker swarm init --advertise-addr 192.168.1.10

# Join as worker
docker swarm join --token SWMTKN-1-xxx 192.168.1.10:2377

# Create service
docker service create \
  --name web \
  --replicas 3 \
  --publish 80:80 \
  --mount type=volume,source=web-data,target=/data \
  nginx

# Scale service
docker service scale web=5

# Update service (rolling update)
docker service update --image nginx:alpine web

# Rolling update with delay
docker service update \
  --image myapp:2.0 \
  --update-delay 10s \
  --update-parallelism 1 \
  --update-failure-action rollback \
  myapp

Stack Deployment

# docker-stack.yml
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
        order: start-first
      rollback_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      placement:
        constraints:
          - node.role == worker
        preferences:
          - spread: node.availability.zone
    networks:
      - frontend
      - backend
      
  api:
    image: myapi:latest
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
    environment:
      - DB_HOST=db
    networks:
      - backend
      
  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
    volumes:
      - type: volume
        source: db-data
        target: /var/lib/postgresql/data
    networks:
      - backend
    deploy:
      placement:
        constraints:
          - node.labels.storage == ssd

networks:
  frontend:
    driver: overlay
  backend:
    driver: overlay
    internal: true
    
volumes:
  db-data:
    driver: rexray/ebs  # AWS EBS
    
secrets:
  db_password:
    external: true
# Deploy stack
docker stack deploy -c docker-stack.yml myapp

# List services
docker stack ps myapp
docker service ls

# View logs
docker service logs myapp_web -f

# Remove stack
docker stack rm myapp

Production Deployment Patterns

Blue-Green with Docker

# Green deployment
docker-compose -f docker-compose.yml -f docker-compose.green.yml up -d

# Health check
curl -f http://green.example.com/health || exit 1

# Switch traffic (update load balancer or DNS)
# Rollback if needed:
docker-compose -f docker-compose.yml -f docker-compose.blue.yml up -d

Database Migrations

# docker-compose.yml
services:
  migrate:
    build:
      context: ./api
      target: migration
    command: npx prisma migrate deploy
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
    depends_on:
      db:
        condition: service_healthy
    restart: on-failure
    deploy:
      restart_policy:
        max_attempts: 3
        
  api:
    build: ./api
    depends_on:
      migrate:
        condition: service_completed_successfully

Quiz

Quiz

Question 1 of 5

What is the purpose of Docker secrets?

To encrypt Docker images
To securely manage sensitive data like passwords and API keys
To lock Docker containers
To hide Dockerfiles from view

Next Steps

Now let's explore Kubernetes—the industry-standard container orchestration platform.