How to use Docker Compose on Linux

How to use Docker Compose on Linux Docker Compose is a powerful tool that simplifies the management of multi-container Docker applications on Linux systems. Whether you're a developer looking to streamline your development workflow or a system administrator managing complex application stacks, Docker Compose provides an elegant solution for defining, running, and orchestrating multiple Docker containers as a single service. This comprehensive guide will walk you through everything you need to know about Docker Compose on Linux, from basic installation to advanced configuration techniques. You'll learn how to create compose files, manage container networks, handle data persistence, and implement best practices for production environments. Table of Contents - [Prerequisites and System Requirements](#prerequisites-and-system-requirements) - [Installing Docker Compose on Linux](#installing-docker-compose-on-linux) - [Understanding Docker Compose Fundamentals](#understanding-docker-compose-fundamentals) - [Creating Your First Docker Compose File](#creating-your-first-docker-compose-file) - [Essential Docker Compose Commands](#essential-docker-compose-commands) - [Working with Multi-Container Applications](#working-with-multi-container-applications) - [Managing Networks and Volumes](#managing-networks-and-volumes) - [Environment Variables and Configuration](#environment-variables-and-configuration) - [Advanced Docker Compose Features](#advanced-docker-compose-features) - [Common Issues and Troubleshooting](#common-issues-and-troubleshooting) - [Best Practices and Security Considerations](#best-practices-and-security-considerations) - [Real-World Examples and Use Cases](#real-world-examples-and-use-cases) - [Conclusion and Next Steps](#conclusion-and-next-steps) Prerequisites and System Requirements Before diving into Docker Compose, ensure your Linux system meets the following requirements: System Requirements - Operating System: Any modern Linux distribution (Ubuntu, CentOS, Debian, Fedora, etc.) - Architecture: x86_64, ARM64, or ARMv7 - RAM: Minimum 2GB, recommended 4GB or more - Storage: At least 10GB of free disk space - Kernel Version: Linux kernel 3.10 or higher Required Software 1. Docker Engine: Docker Compose requires Docker Engine to be installed and running 2. Python: Most Linux distributions include Python by default 3. curl or wget: For downloading Docker Compose binary 4. Text Editor: vim, nano, or any preferred text editor for creating compose files User Permissions Ensure your user account has the necessary permissions to run Docker commands. You can either: - Add your user to the `docker` group: `sudo usermod -aG docker $USER` - Use `sudo` with Docker commands (less recommended for development) Installing Docker Compose on Linux Docker Compose can be installed using several methods. Here are the most common approaches: Method 1: Installing Docker Compose using Package Managers Ubuntu/Debian Systems ```bash Update package index sudo apt update Install Docker Compose sudo apt install docker-compose Verify installation docker-compose --version ``` CentOS/RHEL/Fedora Systems ```bash For CentOS/RHEL with yum sudo yum install docker-compose For Fedora with dnf sudo dnf install docker-compose Verify installation docker-compose --version ``` Method 2: Installing Docker Compose Binary This method provides the latest version directly from the official repository: ```bash Download the latest version sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose Make it executable sudo chmod +x /usr/local/bin/docker-compose Create symbolic link (optional) sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose Verify installation docker-compose --version ``` Method 3: Installing with pip If you prefer using Python's package manager: ```bash Install pip if not already installed sudo apt install python3-pip # Ubuntu/Debian or sudo yum install python3-pip # CentOS/RHEL Install Docker Compose pip3 install docker-compose Verify installation docker-compose --version ``` Understanding Docker Compose Fundamentals Docker Compose uses YAML files to define multi-container applications. Understanding the basic structure and concepts is crucial for effective usage. Core Concepts 1. Services: Define the containers that make up your application 2. Networks: Configure how containers communicate with each other 3. Volumes: Manage data persistence and sharing between containers 4. Environment Variables: Configure application settings dynamically Docker Compose File Structure A typical `docker-compose.yml` file follows this structure: ```yaml version: '3.8' services: service_name: image: image_name:tag ports: - "host_port:container_port" environment: - VARIABLE_NAME=value volumes: - host_path:container_path networks: - network_name networks: network_name: driver: bridge volumes: volume_name: driver: local ``` Version Compatibility Docker Compose file versions correspond to Docker Engine releases: - Version 3.8: Requires Docker Engine 19.03.0+ - Version 3.7: Requires Docker Engine 18.06.0+ - Version 3.6: Requires Docker Engine 18.02.0+ Always use the highest version compatible with your Docker Engine installation. Creating Your First Docker Compose File Let's create a simple web application using Docker Compose to demonstrate basic concepts. Example 1: Simple Web Server Create a directory for your project and a `docker-compose.yml` file: ```bash mkdir my-web-app cd my-web-app nano docker-compose.yml ``` Add the following content: ```yaml version: '3.8' services: web: image: nginx:alpine ports: - "8080:80" volumes: - ./html:/usr/share/nginx/html:ro restart: unless-stopped ``` Create a simple HTML file: ```bash mkdir html echo "

Hello from Docker Compose!

" > html/index.html ``` Run the application: ```bash docker-compose up -d ``` Visit `http://localhost:8080` to see your web server running. Example 2: Web Application with Database Here's a more complex example with a web application and database: ```yaml version: '3.8' services: web: image: wordpress:latest ports: - "8080:80" environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress_password WORDPRESS_DB_NAME: wordpress volumes: - wordpress_data:/var/www/html depends_on: - db restart: unless-stopped db: image: mysql:5.7 environment: MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress_password MYSQL_ROOT_PASSWORD: root_password volumes: - db_data:/var/lib/mysql restart: unless-stopped volumes: wordpress_data: db_data: ``` Essential Docker Compose Commands Master these fundamental Docker Compose commands for daily operations: Basic Operations ```bash Start services in detached mode docker-compose up -d Start services with logs visible docker-compose up Stop services docker-compose down Stop services and remove volumes docker-compose down -v Restart services docker-compose restart View running services docker-compose ps ``` Building and Images ```bash Build or rebuild services docker-compose build Build without cache docker-compose build --no-cache Pull latest images docker-compose pull Build and start services docker-compose up --build ``` Logs and Monitoring ```bash View logs for all services docker-compose logs View logs for specific service docker-compose logs web Follow logs in real-time docker-compose logs -f View last 50 lines of logs docker-compose logs --tail=50 ``` Scaling Services ```bash Scale a service to multiple instances docker-compose up --scale web=3 Scale multiple services docker-compose up --scale web=3 --scale worker=2 ``` Executing Commands ```bash Execute command in running container docker-compose exec web bash Run one-time command docker-compose run web ls -la Run command without dependencies docker-compose run --no-deps web bash ``` Working with Multi-Container Applications Docker Compose excels at managing complex applications with multiple interconnected services. Service Dependencies Use `depends_on` to control startup order: ```yaml version: '3.8' services: web: image: my-web-app depends_on: - db - redis ports: - "8080:80" db: image: postgres:13 environment: POSTGRES_PASSWORD: password redis: image: redis:alpine ``` Health Checks Implement health checks to ensure services are ready: ```yaml version: '3.8' services: web: image: my-web-app healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 start_period: 40s db: image: postgres:13 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 ``` Resource Limits Control resource allocation for containers: ```yaml version: '3.8' services: web: image: my-web-app deploy: resources: limits: cpus: '0.50' memory: 512M reservations: cpus: '0.25' memory: 256M ``` Managing Networks and Volumes Proper network and volume configuration is essential for robust applications. Custom Networks Create isolated networks for different application tiers: ```yaml version: '3.8' services: web: image: nginx networks: - frontend - backend app: image: my-app networks: - backend - database db: image: postgres networks: - database networks: frontend: driver: bridge backend: driver: bridge database: driver: bridge internal: true # No external access ``` Volume Management Implement various volume strategies: ```yaml version: '3.8' services: web: image: nginx volumes: # Named volume - web_data:/usr/share/nginx/html # Bind mount - ./config:/etc/nginx/conf.d:ro # Anonymous volume - /var/cache/nginx db: image: postgres volumes: # External volume - db_data:/var/lib/postgresql/data # Configuration file - ./postgres.conf:/etc/postgresql/postgresql.conf:ro volumes: web_data: driver: local db_data: external: true ``` Network Aliases Use aliases for service discovery: ```yaml version: '3.8' services: web: image: nginx networks: app_network: aliases: - webserver - frontend app: image: my-app networks: app_network: aliases: - application - backend networks: app_network: driver: bridge ``` Environment Variables and Configuration Manage configuration flexibly using environment variables and external files. Environment Variable Methods Method 1: Direct Declaration ```yaml version: '3.8' services: web: image: my-app environment: - DEBUG=true - DATABASE_URL=postgresql://user:pass@db:5432/mydb - API_KEY=your_api_key_here ``` Method 2: Environment Files Create a `.env` file: ```bash .env file DEBUG=true DATABASE_URL=postgresql://user:pass@db:5432/mydb API_KEY=your_api_key_here POSTGRES_PASSWORD=secure_password ``` Reference in docker-compose.yml: ```yaml version: '3.8' services: web: image: my-app env_file: - .env environment: - NODE_ENV=production # Override .env values db: image: postgres environment: - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} ``` Method 3: External Environment Files ```yaml version: '3.8' services: web: image: my-app env_file: - ./config/web.env - ./config/common.env db: image: postgres env_file: - ./config/db.env - ./config/common.env ``` Configuration File Mounting Mount configuration files for more complex setups: ```yaml version: '3.8' services: nginx: image: nginx volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/sites/:/etc/nginx/sites-available/:ro - ./ssl/:/etc/ssl/certs/:ro app: image: my-app volumes: - ./app/config.json:/app/config.json:ro - ./app/logging.conf:/app/logging.conf:ro ``` Advanced Docker Compose Features Explore advanced features for complex deployment scenarios. Multiple Compose Files Use multiple compose files for different environments: ```bash Base configuration docker-compose.yml version: '3.8' services: web: image: my-app ports: - "8080:80" Development overrides docker-compose.override.yml version: '3.8' services: web: environment: - DEBUG=true volumes: - .:/app Production overrides docker-compose.prod.yml version: '3.8' services: web: environment: - DEBUG=false deploy: replicas: 3 ``` Usage: ```bash Development (automatically uses override) docker-compose up Production docker-compose -f docker-compose.yml -f docker-compose.prod.yml up ``` Profiles Use profiles to conditionally start services: ```yaml version: '3.8' services: web: image: nginx ports: - "80:80" db: image: postgres profiles: - production debug: image: my-debug-tools profiles: - debug - development ``` Usage: ```bash Start only web service docker-compose up Start web and db docker-compose --profile production up Start all services docker-compose --profile production --profile debug up ``` Extends and Inheritance Create reusable service definitions: ```yaml common.yml version: '3.8' services: base-service: image: alpine volumes: - /tmp:/tmp environment: - COMMON_VAR=value docker-compose.yml version: '3.8' services: web: extends: file: common.yml service: base-service image: nginx ports: - "80:80" ``` Common Issues and Troubleshooting Address frequent problems encountered when using Docker Compose on Linux. Port Conflicts Problem: Port already in use error ```bash ERROR: for web Cannot start service web: driver failed programming external connectivity ``` Solutions: ```bash Check what's using the port sudo netstat -tulpn | grep :8080 sudo lsof -i :8080 Kill the process using the port sudo kill -9 Or change the port in docker-compose.yml ports: - "8081:80" # Use different host port ``` Permission Issues Problem: Permission denied when mounting volumes Solutions: ```bash Fix ownership sudo chown -R $USER:$USER ./data Use proper user in compose file version: '3.8' services: web: image: nginx user: "${UID}:${GID}" volumes: - ./data:/data ``` Set UID and GID in .env: ```bash echo "UID=$(id -u)" >> .env echo "GID=$(id -g)" >> .env ``` Network Connectivity Issues Problem: Services cannot communicate Diagnostic commands: ```bash Check network configuration docker-compose ps docker network ls docker network inspect Test connectivity between containers docker-compose exec web ping db docker-compose exec web nslookup db ``` Solutions: ```yaml Ensure services are on the same network version: '3.8' services: web: image: nginx networks: - app_network db: image: postgres networks: - app_network networks: app_network: driver: bridge ``` Memory and Resource Issues Problem: Containers running out of memory Monitoring: ```bash Check container resource usage docker stats Check system resources free -h df -h ``` Solutions: ```yaml version: '3.8' services: web: image: my-app deploy: resources: limits: memory: 1G reservations: memory: 512M ``` Log Management Problem: Logs consuming too much disk space Solutions: ```yaml version: '3.8' services: web: image: nginx logging: driver: "json-file" options: max-size: "10m" max-file: "3" ``` Or configure globally in `/etc/docker/daemon.json`: ```json { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } } ``` Best Practices and Security Considerations Implement security best practices and optimization techniques. Security Best Practices Use Non-Root Users ```yaml version: '3.8' services: web: image: nginx user: "1000:1000" # or user: "nginx:nginx" ``` Limit Container Capabilities ```yaml version: '3.8' services: web: image: nginx cap_drop: - ALL cap_add: - CHOWN - SETGID - SETUID ``` Use Read-Only Root Filesystem ```yaml version: '3.8' services: web: image: nginx read_only: true tmpfs: - /var/run - /var/cache/nginx ``` Secure Networks ```yaml version: '3.8' services: web: image: nginx networks: - frontend db: image: postgres networks: - backend networks: frontend: driver: bridge backend: driver: bridge internal: true # No external access ``` Performance Optimization Resource Limits ```yaml version: '3.8' services: web: image: nginx deploy: resources: limits: cpus: '0.50' memory: 512M reservations: cpus: '0.25' memory: 256M restart_policy: condition: on-failure delay: 5s max_attempts: 3 ``` Health Checks ```yaml version: '3.8' services: web: image: nginx healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s ``` Efficient Image Usage ```yaml version: '3.8' services: web: image: nginx:alpine # Use alpine variants when possible # or build optimized images build: context: . dockerfile: Dockerfile.prod args: - BUILD_ENV=production ``` Development vs Production Development Configuration ```yaml docker-compose.dev.yml version: '3.8' services: web: build: . volumes: - .:/app - /app/node_modules environment: - NODE_ENV=development - DEBUG=true ports: - "3000:3000" ``` Production Configuration ```yaml docker-compose.prod.yml version: '3.8' services: web: image: my-app:latest environment: - NODE_ENV=production - DEBUG=false deploy: replicas: 3 restart_policy: condition: on-failure resources: limits: memory: 512M reservations: memory: 256M logging: driver: "json-file" options: max-size: "10m" max-file: "3" ``` Real-World Examples and Use Cases Explore practical implementations for common scenarios. Example 1: LAMP Stack Complete LAMP (Linux, Apache, MySQL, PHP) stack: ```yaml version: '3.8' services: web: image: php:7.4-apache ports: - "80:80" volumes: - ./src:/var/www/html - ./apache/apache2.conf:/etc/apache2/apache2.conf depends_on: - db environment: - APACHE_DOCUMENT_ROOT=/var/www/html networks: - lamp_network db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_DATABASE: myapp MYSQL_USER: myuser MYSQL_PASSWORD: mypassword volumes: - db_data:/var/lib/mysql - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql networks: - lamp_network phpmyadmin: image: phpmyadmin/phpmyadmin ports: - "8080:80" environment: PMA_HOST: db PMA_PORT: 3306 depends_on: - db networks: - lamp_network volumes: db_data: networks: lamp_network: driver: bridge ``` Example 2: Microservices Architecture Multi-service application with API gateway: ```yaml version: '3.8' services: # API Gateway gateway: image: nginx:alpine ports: - "80:80" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf depends_on: - user-service - product-service - order-service networks: - frontend - backend # User Service user-service: build: ./services/user environment: - DB_HOST=user-db - DB_NAME=users - REDIS_HOST=redis depends_on: - user-db - redis networks: - backend - user_network # Product Service product-service: build: ./services/product environment: - DB_HOST=product-db - DB_NAME=products depends_on: - product-db networks: - backend - product_network # Order Service order-service: build: ./services/order environment: - DB_HOST=order-db - DB_NAME=orders - USER_SERVICE_URL=http://user-service:3000 - PRODUCT_SERVICE_URL=http://product-service:3000 depends_on: - order-db networks: - backend - order_network # Databases user-db: image: postgres:13 environment: POSTGRES_DB: users POSTGRES_PASSWORD: password volumes: - user_db_data:/var/lib/postgresql/data networks: - user_network product-db: image: postgres:13 environment: POSTGRES_DB: products POSTGRES_PASSWORD: password volumes: - product_db_data:/var/lib/postgresql/data networks: - product_network order-db: image: postgres:13 environment: POSTGRES_DB: orders POSTGRES_PASSWORD: password volumes: - order_db_data:/var/lib/postgresql/data networks: - order_network # Redis for caching redis: image: redis:alpine volumes: - redis_data:/data networks: - backend volumes: user_db_data: product_db_data: order_db_data: redis_data: networks: frontend: driver: bridge backend: driver: bridge user_network: driver: bridge product_network: driver: bridge order_network: driver: bridge ``` Example 3: Monitoring Stack Complete monitoring solution with Prometheus, Grafana, and Alertmanager: ```yaml version: '3.8' services: # Prometheus prometheus: image: prom/prometheus:latest ports: - "9090:9090" volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - ./prometheus/rules:/etc/prometheus/rules - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' - '--web.enable-lifecycle' networks: - monitoring # Grafana 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 - ./grafana/datasources:/etc/grafana/provisioning/datasources networks: - monitoring # Node Exporter node-exporter: image: prom/node-exporter:latest ports: - "9100:9100" volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)' networks: - monitoring # Alertmanager alertmanager: image: prom/alertmanager:latest ports: - "9093:9093" volumes: - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml - alertmanager_data:/alertmanager networks: - monitoring volumes: prometheus_data: grafana_data: alertmanager_data: networks: monitoring: driver: bridge ``` Conclusion and Next Steps Docker Compose is an invaluable tool for managing multi-container applications on Linux systems. Throughout this comprehensive guide, you've learned how to: - Install and configure Docker Compose on various Linux distributions - Create and manage complex multi-container applications - Implement networking, volume management, and service orchestration - Apply security best practices and performance optimizations - Troubleshoot common issues and implement monitoring solutions - Deploy real-world applications using industry-standard patterns Key Takeaways 1. Start Simple: Begin with basic single-service compositions and gradually add complexity 2. Security First: Always implement security best practices from the beginning 3. Environment Separation: Use different compose files for development, staging, and production 4. Monitor and Log: Implement proper logging and monitoring for production deployments 5. Documentation: Maintain clear documentation for your compose configurations Next Steps To further advance your Docker Compose skills, consider exploring: 1. Docker Swarm: Learn about Docker's native clustering and orchestration 2. Kubernetes: Explore container orchestration at enterprise scale 3. CI/CD Integration: Implement automated deployment pipelines 4. Advanced Networking: Deep dive into custom network configurations 5. Performance Tuning: Optimize containers for production workloads 6. Security Hardening: Implement advanced security measures and compliance Additional Resources - Official Documentation: [Docker Compose Documentation](https://docs.docker.com/compose/) - Docker Hub: Explore pre-built images and official repositories - Community Forums: Engage with the Docker community for support and best practices - GitHub Examples: Study open-source projects using Docker Compose Docker Compose continues to evolve with new features and improvements. Stay updated with the latest releases and community best practices to maximize the effectiveness of your containerized applications on Linux systems. Whether you're developing microservices, deploying web applications, or managing complex data pipelines, Docker Compose provides the flexibility and power needed for modern application deployment and management.