Real-World Docker Projects
Apply Docker to real-world scenarios: build microservices architectures, integrate with CI/CD pipelines, create local development environments, and deploy production-ready applications.
Design and implement a complete microservices application with API Gateway, user service, product service, order service, and message queue using Docker Compose.
# docker-compose.yml for microservices
version: '3.8'
services:
# API Gateway (Nginx)
gateway:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- user-service
- product-service
networks:
- frontend
# User Service (Node.js)
user-service:
build: ./services/user
environment:
- DB_HOST=postgres
- REDIS_HOST=redis
depends_on:
- postgres
- redis
networks:
- backend
- frontend
# Product Service (Python)
product-service:
build: ./services/product
environment:
- DB_HOST=mongodb
depends_on:
- mongodb
networks:
- backend
- frontend
# Order Service (Go)
order-service:
build: ./services/order
environment:
- DB_HOST=postgres
- RABBITMQ_HOST=rabbitmq
depends_on:
- postgres
- rabbitmq
networks:
- backend
# Databases
postgres:
image: postgres:15-alpine
environment:
POSTGRES_PASSWORD: secret
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
mongodb:
image: mongo:6
volumes:
- mongo_data:/data/db
networks:
- backend
redis:
image: redis:alpine
networks:
- backend
rabbitmq:
image: rabbitmq:3-management-alpine
networks:
- backend
networks:
frontend:
backend:
internal: true
volumes:
postgres_data:
mongo_data:
# nginx.conf for API Gateway
# Routes /api/users -> user-service:3000
# Routes /api/products -> product-service:5000
# Routes /api/orders -> order-service:8080
Integrate Docker into a complete CI/CD pipeline that builds, tests, scans, and deploys containerized applications.
# .github/workflows/docker-ci-cd.yml
name: Docker CI/CD Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run unit tests
run: docker-compose -f docker-compose.test.yml run --rm test
build-and-scan:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t ${{ env.IMAGE_NAME }}:${{ github.sha }} .
- name: Run Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.IMAGE_NAME }}:${{ github.sha }}
severity: CRITICAL,HIGH
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push image
run: |
docker tag ${{ env.IMAGE_NAME }}:${{ github.sha }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
docker tag ${{ env.IMAGE_NAME }}:${{ github.sha }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} --all-tags
deploy-staging:
needs: build-and-scan
runs-on: ubuntu-latest
if: github.event_name == 'push'
steps:
- name: Deploy to staging
run: |
ssh staging-server "cd /app && docker-compose pull && docker-compose up -d"
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production
steps:
- name: Deploy to production
run: |
ssh production-server "cd /app && docker-compose pull && docker-compose up -d"
Create a production-like local development environment with hot reload, debugging, and database seeding.
# docker-compose.dev.yml
version: '3.8'
services:
# Node.js app with hot reload
app:
build:
context: .
target: development
ports:
- "3000:3000"
- "9229:9229" # Debug port
volumes:
- .:/app
- /app/node_modules # Keep container's node_modules
environment:
- NODE_ENV=development
- DEBUG=*
command: npm run dev
depends_on:
- postgres
- redis
# PostgreSQL with seed data
postgres:
image: postgres:15-alpine
ports:
- "5432:5432"
environment:
POSTGRES_USER: devuser
POSTGRES_PASSWORD: devpass
POSTGRES_DB: app_dev
volumes:
- postgres_dev:/var/lib/postgresql/data
- ./scripts/seed.sql:/docker-entrypoint-initdb.d/seed.sql
# Redis with persistence
redis:
image: redis:alpine
ports:
- "6379:6379"
command: redis-server --appendonly yes
volumes:
- redis_dev:/data
# MailHog for email testing
mailhog:
image: mailhog/mailhog
ports:
- "1025:1025" # SMTP
- "8025:8025" # Web UI
# Adminer for database management
adminer:
image: adminer
ports:
- "8080:8080"
volumes:
postgres_dev:
redis_dev:
Deploy a production application with health checks, logging, monitoring, and auto-healing.
# docker-compose.prod.yml
version: '3.8'
services:
app:
image: ${REGISTRY}/myapp:${TAG:-latest}
restart: unless-stopped
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://${DB_USER}:${DB_PASS}@postgres:5432/app
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:15-alpine
restart: unless-stopped
environment:
POSTGRES_PASSWORD: ${DB_PASS}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
cpus: '1'
memory: 1G
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- app
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
grafana:
image: grafana/grafana
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASS}
volumes:
- grafana_data:/var/lib/grafana
volumes:
postgres_data:
prometheus_data:
grafana_data:
Implement a Jenkins pipeline that builds, tests, and deploys Docker containers.
// Jenkinsfile
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'myregistry.azurecr.io'
IMAGE_NAME = 'myapp'
IMAGE_TAG = "${env.BUILD_NUMBER}"
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
script {
docker.build("${IMAGE_NAME}:${IMAGE_TAG}")
}
}
}
stage('Test') {
steps {
sh '''
docker run --rm ${IMAGE_NAME}:${IMAGE_TAG} npm test
docker run --rm ${IMAGE_NAME}:${IMAGE_TAG} npm run lint
'''
}
}
stage('Scan') {
steps {
sh "trivy image ${IMAGE_NAME}:${IMAGE_TAG} --severity CRITICAL --exit-code 1"
}
}
stage('Push') {
steps {
script {
docker.withRegistry("https://${DOCKER_REGISTRY}", 'azure-registry-creds') {
docker.image("${IMAGE_NAME}:${IMAGE_TAG}").push()
docker.image("${IMAGE_NAME}:${IMAGE_TAG}").push('latest')
}
}
}
}
stage('Deploy') {
steps {
sh '''
ssh deploy-server "cd /app && \
docker pull ${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} && \
docker-compose up -d --no-deps app"
'''
}
}
}
post {
failure {
slackSend(color: 'danger', message: "Build failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}")
}
success {
slackSend(color: 'good', message: "Build succeeded: ${env.JOB_NAME} - ${env.BUILD_NUMBER}")
}
}
}
Set up a GPU-accelerated machine learning environment with Jupyter, TensorFlow, and model serving.
# docker-compose.ml.yml
version: '3.8'
services:
# Jupyter Lab with GPU support
jupyter:
image: tensorflow/tensorflow:latest-gpu-jupyter
ports:
- "8888:8888"
volumes:
- ./notebooks:/tf/notebooks
- ./data:/tf/data
environment:
- JUPYTER_ENABLE_LAB=yes
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
command: start-notebook.sh --NotebookApp.token=''
# Model Training
trainer:
build:
context: ./trainer
dockerfile: Dockerfile.gpu
volumes:
- ./data:/data
- ./models:/models
environment:
- CUDA_VISIBLE_DEVICES=0
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
# Model Serving (TensorFlow Serving)
serving:
image: tensorflow/serving:latest-gpu
ports:
- "8501:8501"
volumes:
- ./models:/models
environment:
- MODEL_NAME=my_model
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
# MLflow for experiment tracking
mlflow:
image: mlflow/mlflow
ports:
- "5000:5000"
volumes:
- ./mlruns:/mlruns
command: mlflow server --host 0.0.0.0 --backend-store-uri /mlruns
Deploy a complete WordPress stack with Nginx, PHP-FPM, MySQL, and Redis caching.
# docker-compose.wordpress.yml
version: '3.8'
services:
# Nginx as reverse proxy
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- wordpress:/var/www/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- php
networks:
- web
# PHP-FPM with WordPress
php:
image: wordpress:php8.2-fpm-alpine
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
volumes:
- wordpress:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
networks:
- web
- db
# MySQL Database
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: ${ROOT_PASSWORD}
volumes:
- db_data:/var/lib/mysql
networks:
- db
# Redis Cache
redis:
image: redis:alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
networks:
- web
networks:
web:
db:
internal: true
volumes:
wordpress:
db_data:
redis_data:
- Microservices need proper network isolation - Use internal networks for backend services.
- CI/CD pipelines save time - Automate builds, tests, scans, and deployments.
- Local development with hot reload - Bind mounts + nodemon/nodemon improve productivity.
- Production requires health checks - Implement healthchecks and resource limits.
- GPU support is possible - Use nvidia-docker for ML workloads.
- Always scan images for vulnerabilities - Use Trivy, Snyk, or Docker Scout.
These real-world projects demonstrate Docker's versatility from development to production. Start with the local development environment, then expand to CI/CD and microservices as you gain confidence.