fbpx Docker Compose from Scratch: App + Database with YAML | Certificação Linux

Docker Compose: Orchestrating Containers from Scratch with YAML

📅 07/19/2026 ⏱ 3 min ✍️ Uira Ribeiro
Docker Compose: Orchestrating Containers from Scratch with YAML
Exam Pass App — mais de 7.000 questões LPI, offline, em 5 idiomas, disponível no Android e na App Store
Available on
Google Play
Available on
App Store

Docker Compose is the official tool for defining and running multi-container applications. Instead of running 3 long docker run commands with hard-to-remember options, you describe your entire stack in a YAML file and spin everything up with docker compose up.

Installation

# Docker Compose v2 já vem integrado ao Docker Engine (como plugin)
docker compose version    # deve retornar v2.x

# Se não estiver disponível, instalar o plugin
sudo apt install docker-compose-plugin -y

# Versão standalone (legado, ainda funciona)
sudo apt install docker-compose -y   # docker-compose (com hífen)

Structure of docker-compose.yml

version: "3.9"

services:
  app:
    build: .                          # usa o Dockerfile na raiz
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://user:senha@db:5432/meudb
    depends_on:
      db:
        condition: service_healthy    # espera o banco estar pronto

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER:     user
      POSTGRES_PASSWORD: senha
      POSTGRES_DB:       meudb
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  pgdata:     # volume nomeado, persiste entre restarts

Essential Commands

# Subir todos os serviços em background
docker compose up -d

# Ver logs de todos (ou de um serviço específico)
docker compose logs -f
docker compose logs -f app

# Listar containers do projeto
docker compose ps

# Parar e remover containers (mantém volumes)
docker compose down

# Parar, remover containers E volumes
docker compose down -v

# Rebuildar imagem e recriar container
docker compose up -d --build app

# Rodar comando em container em execução
docker compose exec app bash
docker compose exec db psql -U user meudb

Environment Variables with .env

Never put passwords directly in docker-compose.yml. Use a .env file in the same folder (and add it to .gitignore):

# .env
POSTGRES_USER=user
POSTGRES_PASSWORD=senha_super_segura
POSTGRES_DB=meudb
# docker-compose.yml — referencia com ${VAR}
environment:
  POSTGRES_USER:     ${POSTGRES_USER}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
  POSTGRES_DB:       ${POSTGRES_DB}

Volumes: Data Persistence

services:
  app:
    volumes:
      # Volume nomeado (gerenciado pelo Docker)
      - dados_app:/app/uploads

      # Bind mount (pasta do host mapeada no container)
      # Útil em desenvolvimento para hot-reload
      - ./src:/app/src

      # Arquivo único montado no container
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro

volumes:
  dados_app:

Bind mounts are great for development — you edit the file on the host and the container sees the change immediately. In production, prefer named volumes as they are managed by Docker and easier to back up.

Networks: Communication between Services

By default, all services in the same docker-compose.yml are on the same network and can communicate using the service name as hostname. The app service accesses the database at db:5432, not at localhost:5432.

# Redes customizadas (para isolamento)
networks:
  frontend:
  backend:

services:
  nginx:
    networks: [frontend, backend]
  app:
    networks: [backend]
  db:
    networks: [backend]

Real Example: WordPress + MySQL + Nginx

version: "3.9"
services:
  nginx:
    image: nginx:alpine
    ports: ["80:80"]
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - wordpress:/var/www/html
    depends_on: [wordpress]

  wordpress:
    image: wordpress:php8.2-fpm
    environment:
      WORDPRESS_DB_HOST:     db
      WORDPRESS_DB_USER:     ${DB_USER}
      WORDPRESS_DB_PASSWORD: ${DB_PASS}
      WORDPRESS_DB_NAME:     wordpress
    volumes:
      - wordpress:/var/www/html

  db:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE:      wordpress
      MYSQL_USER:          ${DB_USER}
      MYSQL_PASSWORD:      ${DB_PASS}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
    volumes:
      - dbdata:/var/lib/mysql

volumes:
  wordpress:
  dbdata:

Docker Compose vs Kubernetes

Compose is for one machine; Kubernetes is for a cluster. For projects with 1–5 services on a single server, Compose is the right choice — simple, no K8s learning curve, easy to back up and migrate. Use Kubernetes when you need horizontal auto-scaling or high availability with multiple nodes.

Uira Ribeiro

Prof. Uirá Ribeiro

Chair do Board do Linux Professional Institute

After years of watching professionals waste hours on simple tasks because they didn't know the right Linux tools, I decided to teach.
Today I'm the author of most of LPI's official Learning Materials and mentor to over 14,000 certified students.

See my full story →

That was just one piece. The course teaches the whole path — from your first command to exam day.

Certificação Linux — a plataforma líder em certificações Linux no Brasil
WhatsApp