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.

Microservices CI/CD Integration Local Development Production
Project 1: Building a Microservices Architecture

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
Project 2: CI/CD Pipeline with GitHub Actions

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"
Project 3: Complete Local Development Environment

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:
Project 4: Production-Ready Deployment

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:
Project 5: Docker Pipeline with Jenkins

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}") } } }
Project 6: Docker for Machine Learning (GPU Support)

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
Project 7: WordPress Stack with Docker

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:
Key Takeaways
  • 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.
Frequently Asked Questions
How do I choose between microservices vs monolith with Docker?
Start with a modular monolith. If you have independent teams, different scaling requirements, or need to deploy services independently, break into microservices. Docker makes both approaches easy.
Should I use Docker in production without orchestration?
Yes, for small-scale deployments. Use restart policies, health checks, and log rotation. For multiple hosts or high availability, use Swarm or Kubernetes.
How do I handle database migrations in CI/CD?
Run migrations as a separate job before deploying the app. Use `docker run --rm` to run migration containers, then deploy the app container.
What's the best way to manage secrets in CI/CD pipelines?
Use GitHub Secrets, GitLab CI variables, or Jenkins credentials. Never hardcode secrets. Use Docker secrets in Swarm or external secret managers in K8s.
How do I debug microservices locally?
Use docker-compose with all services. Expose debug ports, use `docker compose logs -f service`, and use tools like Jaeger for tracing. VS Code Remote - Containers is excellent for debugging.
Previous: Docker Interview Questions Next: Docker in DevOps Pipelines

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.