Skip to content
Commitpedia
Log in Join & edit

Docker Compose: run a small web app with a database

Docker Compose describes several containers, their ports, volumes and environment in one compose.yaml file, then starts them all with docker compose up.

Not checked by a trusted editor yet Last edited Outdated?

Edit history of Docker Compose: run a small web app with a database: 1 recorded edit
Edit history · 1 edit
Type
Article
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Reading
3 min

Most apps are more than one process: a web server, a database, maybe a cache. Starting each with a long docker run command gets old fast. Docker Compose lets you describe them in one YAML file and manage them together. Compose v2 is a Docker CLI plugin, so the command is docker compose with a space. The older docker-compose tool with a hyphen is no longer maintained.

The project layout

myapp/
  compose.yaml
  .env
  web/
    Dockerfile
    requirements.txt
    app.py

The web folder holds a small Python app with its own Dockerfile, such as the one shown in the Docker basics article. The app reads its database address from an environment variable.

compose.yaml

services:
  web:
    build: ./web
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: postgresql://app:${POSTGRES_PASSWORD}@db:5432/app
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:16
    environment:
      POSTGRES_USER: app
      POSTGRES_DB: app
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d app"]
      interval: 5s
      timeout: 3s
      retries: 10

volumes:
  pgdata:

A few things worth noticing:

  • Service names are hostnames. Compose puts all services on a shared network, so the web app reaches the database at db:5432, not localhost.
  • Only web publishes a port. The database is reachable by other services but not from outside, which is safer. Add ports: ["5432:5432"] to db only if you need to connect from your machine.
  • The named volume pgdata keeps database files when containers are recreated.
  • depends_on with service_healthy waits until the healthcheck passes, not just until the container starts. Without it, the app may try to connect before Postgres accepts connections.
  • The top-level version: key from old tutorials is obsolete and can be left out.

Keep secrets in .env

Compose automatically reads a file named .env next to compose.yaml and substitutes ${VARIABLES}. Add .env to .gitignore and commit a .env.example with placeholder values instead.

POSTGRES_PASSWORD=change-me-locally

Everyday commands

docker compose up -d            # build if needed, start everything in the background
docker compose ps               # status of this project's services
docker compose logs -f web      # follow one service's logs
docker compose exec db psql -U app app   # open a SQL shell in the db
docker compose up -d --build    # rebuild after changing the Dockerfile or dependencies
docker compose restart web      # restart one service
docker compose down             # stop and remove containers and the network
docker compose down -v          # ...and delete volumes: this erases the database

Run these from the folder that contains compose.yaml. Compose names the project after the folder, so two checkouts in different folders do not collide.

Live code reloading in development

Rebuilding the image after every edit is slow. During development, mount your source folder into the container so changes appear immediately:

services:
  web:
    build: ./web
    volumes:
      - ./web:/app
    command: ["python", "app.py"]

Keep this in a separate compose.override.yaml, which Compose merges automatically when present, so your base file stays production-like.

Troubleshooting

  • Bind for 0.0.0.0:8000 failed: port is already allocated: something else uses port 8000. Stop it or change the left side of the mapping, for example "8001:8000".
  • The app cannot reach the database: check that it uses the service name db as host, and look at docker compose logs db.
  • Changes to the Dockerfile do nothing: up reuses existing images, so add --build.
  • Validate the file with docker compose config, which prints the fully merged configuration or an error.

Did this work for you?

No votes yet. Be the first.

If it did not work, the report form below tells the editors what went wrong.

See also

  • 0055 Docker basics: images, containers and the commands you need An image is a read-only package of an app and its dependencies, and a container is a running instance of it. Learn… Beginner · Explains an idea · Linux, macOS, Windows Article Docker basics 15 Oct 2026
  • 0250 Containerize a Node.js app and run it with PostgreSQL using Docker Compose Package a small Node.js web app in a multi-stage Docker image, then run it next to PostgreSQL with Docker Compose, named volumes,… Intermediate · Guided project · Linux, macOS, Windows Article Docker basics · Docker Compose · PostgreSQL 15 Oct 2026
  • 0268 What is a container? A container is a lightweight box that packs a program with everything it needs so it runs the same on any computer. Beginner · Explains an idea · Any system Article Docker basics 15 Oct 2026
  • 0327 Docker images, containers and volumes explained An image is a read-only template, a container is a running copy of it with a thin writable layer, and a volume… Beginner · Explains an idea · Linux, macOS, Windows Article Docker basics 15 Oct 2026
  • 0328 Install Docker Engine on Ubuntu and Debian Set up Docker's official apt repository, install Docker Engine with the Compose and Buildx plugins, run hello-world and let your user run… Beginner · Step by step · Linux Article Docker basics · Packages & updates 15 Oct 2026
  • 0329 Docker CLI cheat sheet The Docker commands you reach for every day, grouped by what they act on: containers, images, volumes, networks, logs and cleanup, with… Beginner · Cheat sheet · Linux, macOS, Windows Article Docker basics 15 Oct 2026

Repos in the wild

  • docker/compose docker/compose The source of Docker Compose, the tool that defines and runs multi-container applications from a compose.yaml file. Useful for release notes, the issue tracker and the examples directory. GitHub
  • Watchtower (maintained fork): automatic container image updates nicholas-fedor/watchtower Watchtower watches your running containers, pulls newer versions of their images and restarts them with the same settings. This fork continues the project after the original containrrr repository was archived. GitHub
  • Uptime Kuma: self-hosted uptime monitoring louislam/uptime-kuma Uptime Kuma is a self-hosted monitoring tool with a web UI that checks websites, TCP ports, DNS, Docker containers and more, draws uptime history and sends alerts. One container is all it needs. GitHub
  • Traefik: a reverse proxy that configures itself from Docker and Kubernetes traefik/traefik Traefik is an open-source edge router that discovers services from Docker labels, Kubernetes resources and other providers and routes traffic to them, with automatic Let's Encrypt certificates and a dashboard. GitHub

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. Commitpedia +3,950 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?