Skip to content
IRC-CodingIRC-Coding
DockerContainersImagesDockerfileDocker ComposeKubernetesDevOpsContainerization

Docker Containers: Images, Dockerfile & Compose

Learn Docker containers, images, Dockerfile, and Docker Compose. Practical containerization examples and best practices.

S

schutzgeist

10 min read
Docker Containers: Images, Dockerfile & Compose

Docker Containers: Fundamentals, Images, Dockerfile & Docker Compose

Docker transformed software development through containerization. It delivers consistent environments from development through production and solves the “works on my machine” problem.

Docker Fundamentals

What is Containerization?

Containerization is an operating system-level virtualization technology that runs applications with all their dependencies in isolated environments.

Docker vs Virtual Machines

# Virtual Machine (VM)
# - Full operating system
# - Hypervisor required
# - High resource consumption
# - Slower startup

# Docker Container
# - Shared OS kernel
# - No hypervisor required
# - Low resource consumption
# - Fast startup

Docker Architecture

# Docker Components
# 1. Docker Daemon (dockerd)
#    - Manages containers, images, networks, volumes
#    - Runs in the background
#    - API endpoint for clients

# 2. Docker Client (docker)
#    - Command-line interface
#    - Communicates with Docker Daemon
#    - User interaction

# 3. Docker Registry
#    - Storage for images (Docker Hub)
#    - Public and private registries

# 4. Docker Objects
#    - Images: Templates for containers
#    - Containers: Running instances
#    - Networks: Container communication
#    - Volumes: Data storage

Docker Installation and Setup

Installation

# Ubuntu/Debian
sudo apt update
sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker

# CentOS/RHEL
sudo yum install docker
sudo systemctl start docker
sudo systemctl enable docker

# Docker Desktop (Windows/Mac)
# Download from https://www.docker.com/products/docker-desktop

# Add user to docker group
sudo usermod -aG docker $USER
newgrp docker

# Verify installation
docker --version
docker info

Core Commands

# Docker version and system information
docker version
docker info
docker system df

# Manage images
docker images
docker pull ubuntu:latest
docker search nginx
docker rmi nginx:latest

# Manage containers
docker ps                    # Running containers
docker ps -a               # All containers
docker run nginx           # Start container
docker stop container_id   # Stop container
docker rm container_id     # Remove container

# Logs and inspection
docker logs container_id
docker inspect container_id
docker exec -it container_id bash

Docker Images

What Are Docker Images?

Docker images are read-only templates used to create containers. They consist of multiple layers.

Image Structure

# Docker Image layer structure
# 1. Base Layer (e.g., Ubuntu)
# 2. Dependencies Layer (e.g., Python)
# 3. Application Layer (e.g., web app)
# 4. Configuration Layer (e.g., environment variables)

# View layers
docker history nginx:latest

# Image information
docker inspect nginx:latest

Dockerfile

A Dockerfile is a text file containing instructions for building a Docker image.

# Dockerfile example for Node.js application

# Base Image
FROM node:16-alpine

# Metadata
LABEL maintainer="max@example.com"
LABEL version="1.0"
LABEL description="Node.js web application"

# Working directory
WORKDIR /app

# Environment variables
ENV NODE_ENV=production
ENV PORT=3000

# Copy files
COPY package*.json ./
RUN npm install --production

# Copy application code
COPY . .

# Create user (security best practice)
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs

# Expose port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

# Startup command
CMD ["node", "server.js"]

Dockerfile Best Practices

# Best practices for Dockerfile

# 1. Minimal base image
FROM alpine:latest

# 2. Use specific tags (not latest)
FROM node:16.14.2-alpine

# 3. Use .dockerignore
# .dockerignore
node_modules
npm-debug.log
.git
.gitignore
README.md
.env

# 4. Optimize layer caching
COPY package*.json ./
RUN npm install
COPY . .

# 5. Multi-stage builds
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM node:16-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]

# 6. Security best practices
USER nonrootuser
RUN rm -rf /var/cache/apk/*

Build and Manage Images

# Build image
docker build -t myapp:1.0 .
docker build -t myapp:latest -f Dockerfile.prod .

# Build with args
docker build --build-arg NODE_ENV=production -t myapp:prod .

# Multi-platform build
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:multi .

# Tag images
docker tag myapp:1.0 myregistry/myapp:1.0
docker tag myapp:latest myregistry/myapp:latest

# Push images
docker login myregistry.com
docker push myregistry/myapp:1.0
docker push myregistry/myapp:latest

# Cleanup images
docker image prune -f
docker image prune -a -f

Docker Containers

Container Lifecycle

# Create and start container
docker run --name mywebserver -d -p 8080:80 nginx

# Container with volumes
docker run --name mydb -v /data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password mysql:8.0

# Container with network
docker network create mynetwork
docker run --name myapp --network mynetwork -d myapp:latest

# Manage containers
docker start mywebserver
docker stop mywebserver
docker restart mywebserver
docker pause mywebserver
docker unpause mywebserver

# Inspect containers
docker logs mywebserver
docker logs -f mywebserver  # Follow logs
docker stats mywebserver    # Resource usage
docker exec -it mywebserver bash

Container Configuration

# Resource limits
docker run --memory="512m" --cpus="1.0" myapp:latest

# Environment variables
docker run -e NODE_ENV=production -e PORT=3000 myapp:latest

# Volumes
docker run -v /host/path:/container/path myapp:latest
docker run -v myvolume:/container/path myapp:latest

# Ports
docker run -p 8080:80 -p 8443:443 myapp:latest

# Networks
docker run --network bridge myapp:latest
docker run --network host myapp:latest
docker run --network none myapp:latest

# Restart policies
docker run --restart=always myapp:latest
docker run --restart=on-failure:5 myapp:latest
docker run --restart=unless-stopped myapp:latest

Docker Volumes

# Volume types
# 1. Bind mounts: Host filesystem
docker run -v /host/data:/container/data myapp:latest

# 2. Named volumes: Docker-managed
docker volume create mydata
docker run -v mydata:/container/data myapp:latest

# 3. Anonymous volumes: Auto-created
docker run -v /container/data myapp:latest

# Volume management
docker volume ls
docker volume inspect mydata
docker volume rm mydata
docker volume prune

# Backup and restore
docker run --rm -v mydata:/data -v $(pwd):/backup alpine tar czf /backup/mydata-backup.tar.gz /data
docker run --rm -v mydata:/data -v $(pwd):/backup alpine tar xzf /backup/mydata-backup.tar.gz -C /

Docker Networks

Network Types

# Bridge Network (Standard)
docker network create mybridge
docker run --network mybridge myapp:latest

# Host Network
docker run --network host myapp:latest

# None Network
docker run --network none myapp:latest

# Overlay Network (Multi-Host)
docker network create --driver overlay myoverlay

Network Configuration

# Create a network
docker network create --driver bridge --subnet 192.168.1.0/24 mynetwork

# Run a container on the network
docker run --network mynetwork --ip 192.168.1.10 myapp:latest

# Manage network connections
docker network connect mynetwork mycontainer
docker network disconnect mynetwork mycontainer

# Inspect networks
docker network inspect mynetwork
docker network ls
docker network prune

Docker Compose

Getting Started with Docker Compose

Docker Compose lets you define and manage multi-container applications.

# docker-compose.yml
version: '3.8'

services:
  # Web service
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:password@db:5432/myapp
    depends_on:
      - db
      - redis
    volumes:
      - ./logs:/app/logs
    restart: unless-stopped
    networks:
      - app-network

  # Database service
  db:
    image: postgres:13
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    restart: unless-stopped
    networks:
      - app-network

  # Redis cache
  redis:
    image: redis:6-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    restart: unless-stopped
    networks:
      - app-network

  # Nginx reverse proxy
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl
    depends_on:
      - web
    restart: unless-stopped
    networks:
      - app-network

# Volumes
volumes:
  postgres_data:
  redis_data:

# Networks
networks:
  app-network:
    driver: bridge

Docker Compose Commands

# Start services
docker-compose up
docker-compose up -d  # Detached mode
docker-compose up --build  # With rebuild

# Stop services
docker-compose down
docker-compose down -v  # Including volumes

# View logs
docker-compose logs
docker-compose logs -f web
docker-compose logs --tail=100 web

# Manage services
docker-compose ps
docker-compose restart web
docker-compose stop web
docker-compose start web

# Scale services
docker-compose up -d --scale web=3

# Build images
docker-compose build
docker-compose build --no-cache
docker-compose build web

# Multiple configuration files
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up

Environment-Specific Configuration

# docker-compose.override.yml (Development)
version: '3.8'

services:
  web:
    environment:
      - NODE_ENV=development
    volumes:
      - .:/app
      - /app/node_modules
    command: npm run dev

  db:
    ports:
      - "5432:5432"

# docker-compose.prod.yml (Production)
version: '3.8'

services:
  web:
    environment:
      - NODE_ENV=production
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  nginx:
    ports:
      - "80:80"
      - "443:443"

Docker Security

Security Best Practices

# 1. Use minimal base images
FROM alpine:latest

# 2. Run as non-root user
RUN addgroup -g 1001 -S appgroup && \
    adduser -S appuser -u 1001 -G appgroup
USER appuser

# 3. Use secrets (keep them out of the image)
# docker run --secret=mysecret myapp:latest

# 4. Set the filesystem to read-only
docker run --read-only --tmpfs /tmp myapp:latest

# 5. Apply resource limits
docker run --memory=512m --cpus=1.0 myapp:latest

Docker Security Scanning

# Scan images with Trivy
trivy image myapp:latest

# Docker Scout (official tool)
docker scout cves myapp:latest

# Check your Dockerfile
hadolint Dockerfile

Docker Monitoring and Logging

Logging Strategies

# docker-compose.yml with logging configuration
version: '3.8'

services:
  web:
    image: myapp:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    labels:
      - "logging=promtail"

  # ELK Stack for logging
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0
    environment:
      - discovery.type=single-node
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data

  logstash:
    image: docker.elastic.co/logstash/logstash:7.14.0
    volumes:
      - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf

  kibana:
    image: docker.elastic.co/kibana/kibana:7.14.0
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch

Monitoring with Prometheus

# docker-compose.monitoring.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards

  node-exporter:
    image: prom/node-exporter:latest
    ports:
      - "9100:9100"
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro

volumes:
  prometheus_data:
  grafana_data:

Docker and Kubernetes

Kubernetes Basics

# kubernetes/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myregistry/myapp:1.0
        ports:
        - containerPort: 3000
        env:
        - name: NODE_ENV
          value: "production"
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5

Migrating from Docker to Kubernetes

# Use Kompose to convert files
kompose convert -f docker-compose.yml

# Apply Kubernetes manifests
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml

# Manage deployments
kubectl get deployments
kubectl get pods
kubectl logs -f deployment/myapp-deployment
kubectl scale deployment myapp-deployment --replicas=5

Docker Best Practices

Performance Optimization

# Multi-stage builds for smaller images
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
COPY . .
RUN npm run build

FROM node:16-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]

Production Deployment

# docker-compose.prod.yml
version: '3.8'

services:
  web:
    image: myregistry/myapp:${VERSION}
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

Troubleshooting

Common Issues

# 1. Container won't start
docker logs container_id
docker inspect container_id

# 2. Disk space full
docker system df
docker system prune -a -f
docker volume prune -f

# 3. Network issues
docker network inspect network_name
docker exec -it container_id ping other_container

# 4. Permission errors
sudo chown -R $USER:$USER /var/run/docker.sock

# 5. Image pull failures
docker system prune -f
docker pull --no-cache image_name

Debugging Techniques

# Inspect container
docker exec -it container_id /bin/sh
docker exec -it container_id /bin/bash

# Copy files
docker cp container_id:/path/file.txt .
docker cp file.txt container_id:/path/

# Analyze image layers
docker history image_name
dive image_name

# Performance analysis
docker stats
docker top container_id

Exam-Relevant Concepts

Essential Docker Commands

CommandDescriptionUse Case
docker buildBuild an imageFrom a Dockerfile
docker runStart a containerRun an application
docker-compose upStart multi-container setupDevelopment environment
docker pushUpload an imageRegistry upload
docker pullDownload an imageRegistry download

Typical Exam Tasks

  1. Create Dockerfiles for various applications
  2. Configure Docker Compose for multi-container apps
  3. Implement security best practices
  4. Optimize Docker images for production
  5. Migrate applications to Kubernetes

Summary

Docker is fundamental to modern software development:

  • Containerization: Consistent environments everywhere
  • Images: Reusable templates for applications
  • Dockerfile: Automated build processes
  • Docker Compose: Define multi-container applications
  • Kubernetes: Orchestration for large-scale deployments

Effective Docker management requires understanding container concepts, security practices, and orchestration techniques.

Book Recommendations

Docker is quick to learn and useful for simple deployments, but the platform offers far more capabilities for boosting productivity and security. Invest time in quality resources to unlock the full potential of containers. The recommended books guide you from fundamentals through advanced enterprise solutions, helping you design and operate professional Docker architectures.

Das Komplette Docker Handbuch: Containerisierte Anwendungen Erstellen, Verteilen, Ausführen

Das Komplette Docker Handbuch: Containerisierte Anwendungen Erstellen, Verteilen, Ausführen

39,99 €

Bei Amazon ansehen

Affiliate-Link: Bei einem Kauf erhalten wir möglicherweise eine Provision.

Back to Blog
Share:

Related Posts