BLOG POSTS
    MangoHost Blog / Install and Use Docker Compose on Ubuntu 24 – Hosting Setup
Install and Use Docker Compose on Ubuntu 24 – Hosting Setup

Install and Use Docker Compose on Ubuntu 24 – Hosting Setup

Docker Compose is an essential tool for orchestrating multi-container Docker applications, allowing developers to define and manage complex application stacks using simple YAML configuration files. On Ubuntu 24, setting up Docker Compose properly is crucial for development environments, staging servers, and production deployments. This guide will walk you through the complete installation process, basic usage patterns, troubleshooting common issues, and practical hosting scenarios that you’ll encounter when managing containerized applications on your Ubuntu server.

Understanding Docker Compose Architecture

Docker Compose operates as a wrapper around the Docker engine, interpreting YAML configuration files to orchestrate multiple containers as a single application stack. Unlike running individual Docker containers manually, Compose manages networking, volumes, environment variables, and dependencies between services automatically.

The tool works by reading a docker-compose.yml file that defines services, networks, and volumes. When you execute compose commands, it translates these definitions into Docker API calls, creating and managing containers according to your specifications. Each service in your compose file becomes one or more containers, and Compose handles the networking between them using Docker’s built-in networking capabilities.

Installation Methods on Ubuntu 24

Ubuntu 24 offers several approaches for installing Docker Compose, each with different advantages depending on your specific needs and environment setup.

Method 1: Installing via Docker’s Official Repository

This method provides the most up-to-date version directly from Docker’s maintained repositories:

# Update package index
sudo apt update

# Install required packages for HTTPS repository access
sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release

# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Update package index again
sudo apt update

# Install Docker Engine and Docker Compose
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Method 2: Standalone Binary Installation

For environments where you need more control over the specific version or prefer manual installation:

# Download the latest stable release
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# Make the binary executable
sudo chmod +x /usr/local/bin/docker-compose

# Create symbolic link for easier access
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

Method 3: Installation via Python pip

This approach works well in Python-heavy environments but requires additional dependency management:

# Install Python pip if not already available
sudo apt install python3-pip

# Install Docker Compose via pip
pip3 install docker-compose

# Add local bin to PATH if needed
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Verification and Initial Configuration

After installation, verify that Docker Compose is working correctly and configure user permissions for non-root usage:

# Check Docker Compose version
docker-compose --version

# Verify Docker service status
sudo systemctl status docker

# Add current user to docker group (eliminates need for sudo)
sudo usermod -aG docker $USER

# Apply group membership (requires logout/login or newgrp)
newgrp docker

# Test Docker without sudo
docker run hello-world

Basic Docker Compose Usage Patterns

Understanding fundamental Compose patterns will help you build more complex applications. Here’s a practical example that demonstrates core concepts:

# Create project directory
mkdir my-web-app && cd my-web-app

# Create docker-compose.yml
cat > docker-compose.yml << EOF
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
    depends_on:
      - api
    environment:
      - NGINX_HOST=localhost
      - NGINX_PORT=80

  api:
    image: node:16-alpine
    working_dir: /app
    volumes:
      - ./api:/app
    ports:
      - "3000:3000"
    command: npm start
    environment:
      - NODE_ENV=development
      - DB_HOST=database

  database:
    image: postgres:13
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=developer
      - POSTGRES_PASSWORD=secure_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  postgres_data:

networks:
  default:
    driver: bridge
EOF

Essential commands for managing this stack:

# Start all services in background
docker-compose up -d

# View running services
docker-compose ps

# Check service logs
docker-compose logs web
docker-compose logs -f api  # Follow log output

# Scale specific services
docker-compose up -d --scale api=3

# Stop all services
docker-compose down

# Stop and remove volumes
docker-compose down -v

Real-World Hosting Examples

These examples demonstrate practical hosting scenarios you'll encounter when deploying applications using Docker Compose on Ubuntu servers.

WordPress with MySQL and Redis

version: '3.8'

services:
  wordpress:
    image: wordpress:latest
    restart: unless-stopped
    ports:
      - "80:80"
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wordpress_data:/var/www/html
    depends_on:
      - mysql
      - redis

  mysql:
    image: mysql:8.0
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    volumes:
      - mysql_data:/var/lib/mysql
    command: '--default-authentication-plugin=mysql_native_password'

  redis:
    image: redis:alpine
    restart: unless-stopped
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data

volumes:
  wordpress_data:
  mysql_data:
  redis_data:

Development Stack with Hot Reloading

version: '3.8'

services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - ./frontend:/app
      - /app/node_modules
    environment:
      - REACT_APP_API_URL=http://localhost:8000

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile.dev
    ports:
      - "8000:8000"
    volumes:
      - ./backend:/app
    environment:
      - DEBUG=1
      - DATABASE_URL=postgresql://dev:dev@postgres:5432/devdb
    depends_on:
      - postgres

  postgres:
    image: postgres:13
    environment:
      POSTGRES_DB: devdb
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: dev
    volumes:
      - postgres_dev_data:/var/lib/postgresql/data

volumes:
  postgres_dev_data:

Performance Optimization and Best Practices

Optimizing Docker Compose deployments involves several considerations that directly impact application performance and resource utilization.

Optimization Area Default Behavior Optimized Approach Performance Impact
Image Size Full OS images Alpine-based images 50-80% size reduction
Build Caching No cache optimization Multi-stage builds 60-90% faster builds
Resource Limits Unlimited resources CPU/Memory limits Better resource allocation
Network Mode Bridge networking Host networking (when appropriate) 10-15% network performance

Key optimization techniques:

  • Use multi-stage Dockerfiles to minimize final image size
  • Implement health checks for better service management
  • Configure resource limits to prevent resource exhaustion
  • Use named volumes for persistent data instead of bind mounts in production
  • Implement proper logging drivers to manage log file growth
# Example optimized service configuration
services:
  web:
    image: nginx:alpine
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 256M
          cpus: '0.5'
        reservations:
          memory: 128M
          cpus: '0.25'
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

Common Issues and Troubleshooting

Docker Compose deployments frequently encounter specific issues that can disrupt service availability. Understanding these problems and their solutions will save significant debugging time.

Permission and Volume Issues

Volume mounting problems often arise from incorrect permissions or ownership conflicts:

# Fix common permission issues
# Check current ownership
ls -la /path/to/volume

# Fix ownership for web applications
sudo chown -R www-data:www-data /path/to/web/files
sudo chmod -R 755 /path/to/web/files

# For database volumes
sudo chown -R 999:999 /path/to/postgres/data

# Set proper SELinux context if enabled
sudo chcon -Rt svirt_sandbox_file_t /path/to/volume

Network Connectivity Problems

Services unable to communicate often indicate network configuration issues:

# Debug network connectivity
docker-compose exec web ping api
docker-compose exec api nslookup database

# List networks
docker network ls

# Inspect specific network
docker network inspect $(docker-compose ps -q | head -1 | xargs docker inspect --format='{{range .NetworkSettings.Networks}}{{.NetworkID}}{{end}}')

# Manual network creation for complex setups
docker network create --driver bridge my-network

Resource Exhaustion Issues

Monitor and address resource constraints that can cause service failures:

# Monitor resource usage
docker stats

# Check disk usage by containers
docker system df

# Clean up unused resources
docker system prune -a

# Remove unused volumes
docker volume prune

# Identify resource-heavy containers
docker-compose top

Environment-Specific Configuration

Managing different environments requires structured approaches to configuration management. Use environment files and override configurations for flexibility:

# Create .env file for sensitive data
cat > .env << EOF
MYSQL_ROOT_PASSWORD=super_secure_root_password
MYSQL_PASSWORD=secure_app_password
REDIS_PASSWORD=redis_secure_password
DOMAIN_NAME=yourdomain.com
EOF

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

services:
  web:
    restart: unless-stopped
    deploy:
      replicas: 2
      resources:
        limits:
          memory: 512M
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://logs.yourdomain.com:514"

  database:
    restart: unless-stopped
    volumes:
      - /backup/mysql:/backup:ro

# Deploy using override
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Integration with CI/CD and Hosting Platforms

Docker Compose integrates seamlessly with continuous integration workflows and hosting environments. For VPS deployments, automated deployment scripts can significantly streamline your workflow:

#!/bin/bash
# deploy.sh - Automated deployment script

set -e

# Pull latest changes
git pull origin main

# Build and deploy with zero downtime
docker-compose pull
docker-compose up --build -d --remove-orphans

# Clean up unused images
docker image prune -f

# Verify deployment
docker-compose ps
curl -f http://localhost/health || exit 1

echo "Deployment completed successfully"

For more resource-intensive applications requiring dedicated hardware, dedicated server hosting provides the performance and isolation necessary for production Docker Compose deployments.

Security Considerations and Hardening

Securing Docker Compose deployments requires attention to multiple layers, from container isolation to network security:

  • Never store secrets in docker-compose.yml files; use environment variables or Docker secrets
  • Run containers with non-root users whenever possible
  • Use specific image tags instead of 'latest' for production deployments
  • Implement network segmentation using custom networks
  • Regularly update base images to patch security vulnerabilities
  • Enable Docker Content Trust for image signature verification
# Example security-hardened service
services:
  app:
    image: myapp:1.2.3  # Specific version, not 'latest'
    user: "1000:1000"   # Non-root user
    read_only: true     # Read-only filesystem
    tmpfs:
      - /tmp
      - /var/cache
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    security_opt:
      - no-new-privileges:true
    networks:
      - frontend
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

networks:
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24

Docker Compose on Ubuntu 24 provides a robust foundation for containerized application deployment. The installation process is straightforward, but success depends on understanding the underlying concepts, following security best practices, and implementing proper monitoring and maintenance procedures. Regular updates, resource monitoring, and backup strategies ensure reliable long-term operation of your containerized services.

For additional information and advanced configuration options, consult the official Docker Compose documentation and the Docker Engine installation guide for Ubuntu.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked