Linux

Docker Compose for Linux: Create Your First Service Stack

This guide introduces Docker Compose—a container orchestration tool. You'll create a docker-compose.yml file and run a stack with a web service and PostgreSQL. Suitable for beginner Linux developers and admins.

Updated at February 17, 2026
15-20 min
Easy
FixPedia Team
Применимо к:Docker Engine 20.10+Docker Compose v2.0+Ubuntu 20.04/22.04CentOS 8/Rocky 9

Introduction / Why This Is Needed

Docker Compose is a tool that allows you to describe and manage multi-container applications using a single YAML file. Instead of manually launching dozens of containers, configuring networks and volumes, you describe the entire infrastructure as code. This is especially useful for development, testing, and local deployment.

After completing this guide, you will:

  • Understand the basic syntax of docker-compose.yml
  • Learn how to run a stack consisting of a web service and a database
  • Find out how to manage the container lifecycle with a single command

Prerequisites / Preparation

Before starting, make sure you have installed:

  1. Docker Engine (version 20.10 or newer)
  2. Docker Compose v2 (included with Docker Desktop for Linux or as the docker-compose-plugin)
  3. sudo privileges (or a user in the docker group)

Check your installation:

docker --version
docker compose version

If Docker Compose is not installed, on Ubuntu/Debian:

sudo apt update
sudo apt install docker-compose-plugin

On CentOS/Rocky/AlmaLinux:

sudo yum install docker-compose-plugin

Step 1: Create the Project Structure

Create a directory for your application and navigate to it:

mkdir myapp && cd myapp

In this directory, create a docker-compose.yml file. We will deploy a simple stack:

  • web service: Python Flask application
  • db service: PostgreSQL

Step 2: Write the docker-compose.yml File

Create a docker-compose.yml file with the following content:

version: '3.8'

services:
  web:
    image: python:3.11-slim
    command: >
      sh -c "pip install flask psycopg2-binary &&
             echo 'from flask import Flask\nfrom psycopg2 import connect\napp = Flask(__name__)\n@app.route(\"/\")\ndef hello():\n    try:\n        conn = connect(dbname=\"testdb\", user=\"user\", password=\"password\", host=\"db\")\n        return \"Hello from Docker Compose! DB connection: OK\"\n    except Exception as e:\n        return f\"DB error: {e}\"\nif __name__ == \"__main__\":\n    app.run(host=\"0.0.0.0\", port=5000)' > app.py &&
             python app.py"
    ports:
      - "5000:5000"
    depends_on:
      - db
    environment:
      - DATABASE_URL=postgresql://user:password@db/testdb
    networks:
      - app-network

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: testdb
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - app-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  postgres_data:

networks:
  app-network:
    driver: bridge

File Explanations:

  • version: specifies the Compose schema version (use 3.8 for compatibility)
  • services: list of containers (services)
    • web:
      • image: base Python image
      • command: runs a script that installs Flask, creates a simple app, and starts it
      • ports: maps container port 5000 to host port 5000
      • depends_on: ensures db starts before web
      • environment: environment variables (used by the app)
      • networks: attaches the service to the custom app-network
    • db:
      • image: PostgreSQL 15 image
      • environment: database credentials
      • volumes: the postgres_data volume persists database data on the host (even after container removal)
      • healthcheck: checks PostgreSQL readiness (important for depends_on)
  • volumes: declares the named volume postgres_data
  • networks: creates the app-network (default bridge driver)

Step 3: Start the Stack

In the directory with docker-compose.yml, run:

docker compose up -d

What will happen:

  1. Docker Compose reads the configuration
  2. Creates the network myapp_app-network (prefix — directory name)
  3. Pulls the python:3.11-slim and postgres:15-alpine images (if not present locally)
  4. Starts the containers in detached mode (-d)

💡 Tip: The first run may take a minute — Docker downloads the images (~500 MB).

Step 4: Verify Operation

  1. Check container status:
    docker compose ps
    

    The output should show both services in Up state.
  2. Check logs (if something isn't working):
    docker compose logs web
    docker compose logs db
    
  3. Test the application: Open your browser and go to http://localhost:5000. You should see:
    Hello from Docker Compose! DB connection: OK
    

    This means the web container successfully connected to PostgreSQL.
  4. Check the network:
    docker network ls | grep app-network
    docker network inspect myapp_app-network
    

Step 5: Managing the Stack

Essential commands:

CommandAction
docker compose downStops and removes containers, networks (volumes remain)
docker compose down -vAlso removes volumes (database data will be lost!)
docker compose logs -fFollows logs in real time
docker compose exec web bashEnters the web container
docker compose stopStops containers (without removing)
docker compose startStarts stopped containers
docker compose rmRemoves stopped containers

Example of restarting only one service:

docker compose restart web

Step 6: Modification and Rebuilding

If you changed docker-compose.yml or need to rebuild an image (e.g., added a Dockerfile), use:

docker compose up -d --build

To force recreate containers without building:

docker compose up -d --force-recreate

Result Verification

Success Criteria:

  • Containers are running (docker compose ps shows Up)
  • The web app responds at http://localhost:5000 and reports successful DB connection
  • PostgreSQL data is persisted in the postgres_data volume (check docker volume ls)

If something isn't working:

  1. Check logs: docker compose logs
  2. Ensure port 5000 isn't used by another application
  3. Verify both services are on the same network: docker network inspect myapp_app-network

Possible Issues

Error: Error response from daemon: port is already allocated

Cause: Port 5000 is already in use by another process. Solution:

  • Stop the conflicting process (sudo lsof -i:5000 and kill)
  • Or change the port mapping in docker-compose.yml (e.g., "8080:5000")

Error: postgres: connection to server at "db" (172.20.0.2), port 5432 failed: Connection refused

Cause: The web container tries to connect to the DB before it's fully ready. Solution:

  • Ensure db has a healthcheck (as in the example)
  • Add waiting to the web command (e.g., using wait-for-it.sh or dockerize)
  • Or extend depends_on with a condition: service_healthy condition

Error: permission denied while trying to connect to the Docker daemon socket

Cause: The current user is not in the docker group. Solution:

sudo usermod -aG docker $USER
newgrp docker

Or use sudo for Docker commands.

Volume postgres_data is not created

Cause: Syntax error in volumes or insufficient permissions. Solution:

  • Check YAML indentation (spaces, not tabs)
  • Ensure the volume path /var/lib/postgresql/data exists in the PostgreSQL image
  • Check docker volume ls — the volume should be named [directory]_postgres_data

Images fail to download (network errors)

Cause: Problems accessing Docker Hub. Solution:

  • Configure DNS in Docker (/etc/docker/daemon.json)
  • Use a mirror (e.g., registry-mirrors for Kubernetes/OpenShift)
  • Or manually pull images: docker pull python:3.11-slim

F.A.Q.

What is Docker Compose and why do you need it?
How to install Docker Compose on Linux?
What's the difference between `docker-compose` and `docker compose`?
How to run docker-compose in the background?

Hints

Install Docker Compose (if not already installed)
Create a project directory and docker-compose.yml file
Configure services in docker-compose.yml
Run the stack with docker compose up
Check container status
Stop and remove containers
FixPedia

Free encyclopedia for fixing errors. Step-by-step guides for Windows, Linux, macOS and more.

© 2026 FixPedia. All materials are available for free.

Made with for the community