Conteúdo
Tutorial de Docker Compose: gerencie vários contêineres com um único arquivo
Um aplicativo real costuma ter mais de um contêiner: site, banco de dados, cache... Para cada um, você precisa lembrar uma longa lista de parâmetros de docker run, criar uma rede e um Volume antes e prestar atenção à ordem de inicialização.
Docker Compose permite colocar essas configurações em um arquivo YAML e iniciar tudo com um único comando:
docker compose up -d
Instalação e versão
- Docker Desktop (Windows e macOS) já inclui o Compose.
- Linux: siga as etapas de instalação do Docker e instale
docker-compose-plugin.
$ docker compose version
Docker Compose version v5.6.0
O antigo programa independente se chama
docker-compose(com hífen, v1) e não recebe mais manutenção; agora, usedocker compose(com espaço). O número da versão do Compose saltou diretamente da v2 para a v5, mas o uso não mudou. Tutoriais antigos na internet misturam os dois; os comandos e parâmetros são praticamente os mesmos.
Projeto de exemplo: site + banco de dados + interface de administração
Crie a pasta compose-demo com a seguinte estrutura:
compose-demo/
├── compose.yaml
└── site/
└── index.html
Coloque uma página simples em site/index.html (o conteúdo fica a seu critério). compose.yaml:
services:
web:
image: nginx:1.30-alpine
ports:
- "8080:80"
volumes:
- ./site:/usr/share/nginx/html:ro
db:
image: postgres:18
environment:
POSTGRES_PASSWORD: example
volumes:
- pgdata:/var/lib/postgresql
adminer:
image: adminer
ports:
- "8081:8080"
depends_on:
- db
volumes:
pgdata:
Os três serviços:
| Serviço | Função |
|---|---|
web | nginx, que usa a pasta ./site como site, na porta 8080 do host |
db | PostgreSQL 18; os dados ficam no Volume chamado pgdata (atenção: a montagem da versão 18 é em /var/lib/postgresql; consulte Volume) |
adminer | Ferramenta web de administração de banco de dados, na porta 8081 do host |
Para escrever a mesma configuração com docker run, você precisaria primeiro executar docker network create e docker volume create e, em seguida, executar três comandos docker run bem longos.
Inicialização: docker compose up
Execute na pasta compose-demo:
$ docker compose up -d
[+] up 34/34
✔ Image nginx:1.30-alpine Pulled 7.8s
✔ Image adminer Pulled 8.7s
✔ Network compose-demo_default Created 0.1s
✔ Volume compose-demo_pgdata Created 0.0s
✔ Container compose-demo-web-1 Started 1.7s
✔ Container compose-demo-db-1 Started 0.8s
✔ Container compose-demo-adminer-1 Started 1.0s
Um único comando fez tudo: baixou as imagens (Pulled, algo que só acontece na primeira vez), criou a rede e o Volume e iniciou os três contêineres.
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
compose-demo-adminer-1 adminer "entrypoint.sh docke…" adminer 10 seconds ago Up 9 seconds 0.0.0.0:8081->8080/tcp, [::]:8081->8080/tcp
compose-demo-db-1 postgres:18 "docker-entrypoint.s…" db 10 seconds ago Up 10 seconds 5432/tcp
compose-demo-web-1 nginx:1.30-alpine "/docker-entrypoint.…" web 10 seconds ago Up 9 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp
$ docker network ls --filter name=compose-demo
NETWORK ID NAME DRIVER SCOPE
a722da926fbd compose-demo_default bridge local
$ docker volume ls --filter name=compose-demo
DRIVER VOLUME NAME
local compose-demo_pgdata
- O nome do contêiner segue o formato
nome-do-projeto-nome-do-serviço-número. Por padrão, o nome do projeto é o da pasta (compose-demo), então projetos em pastas diferentes não interferem uns nos outros. - O Compose criou automaticamente a rede
compose-demo_default. Os três serviços estão nela e podem se conectar entre si usando o nome do serviço. - O nome real do Volume
pgdataécompose-demo_pgdata. dbnão temportsconfigurado, então o campo PORTS mostra apenas5432/tcp; não é possível acessá-lo de fora.
Abra http://localhost:8080:

Gerencie o banco de dados com o Adminer
Ao abrir http://localhost:8081, você verá a tela de login do Adminer. Observe que System é MySQL por padrão:

Faça login com as configurações abaixo:
| Campo | Preencha com |
|---|---|
| System | PostgreSQL (é obrigatório alterar, caso contrário, a conexão será feita como MySQL e falhará) |
| Server | db (nome do serviço, resolvido pela rede do Compose) |
| Username | postgres |
| Password | example (POSTGRES_PASSWORD em compose.yaml) |

Após fazer login, a tela exibirá a versão do PostgreSQL e a lista de bancos de dados:

Clique em SQL command à esquerda e insira o SQL:
CREATE TABLE guestbook (id serial PRIMARY KEY, name text, message text);
INSERT INTO guestbook (name, message) VALUES ('Docker', 'Hello from Compose!');
SELECT * FROM guestbook;

Clique em Execute para executar os três comandos em sequência. O SELECT final lista os dados que você acabou de adicionar:

Consulte os logs
$ docker compose logs --tail 2
web-1 | 2026/10/13 00:14:23 [notice] 1#1: start worker processes
web-1 | 2026/10/13 00:14:23 [notice] 1#1: start worker process 30
db-1 | 2026-10-13 00:14:24.205 UTC [71] LOG: database system was shut down at 2026-10-13 00:14:24 UTC
db-1 | 2026-10-13 00:14:24.210 UTC [1] LOG: database system is ready to accept connections
adminer-1 | [Tue Oct 13 00:14:22 2026] PHP 8.4.26 Development Server (http://[::]:8080) started
docker compose logs combina e exibe os logs de todos os serviços, com o nome do serviço no início de cada linha. --tail 2 exibe apenas as 2 últimas linhas de cada serviço, -f acompanha os logs continuamente, e docker compose logs db exibe somente os logs de db.
Pare e inicie
$ docker compose stop
[+] stop 3/3
✔ Container compose-demo-adminer-1 Stopped 0.4s
✔ Container compose-demo-web-1 Stopped 0.4s
✔ Container compose-demo-db-1 Stopped 0.3s
$ docker compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
compose-demo-adminer-1 adminer "entrypoint.sh docke…" adminer 53 seconds ago Exited (0) Less than a second ago
compose-demo-db-1 postgres:18 "docker-entrypoint.s…" db 53 seconds ago Exited (0) Less than a second ago
compose-demo-web-1 nginx:1.30-alpine "/docker-entrypoint.…" web 53 seconds ago Exited (0) Less than a second ago
$ docker compose start
[+] start 3/3
✔ Container compose-demo-db-1 Started 0.3s
✔ Container compose-demo-web-1 Started 1.0s
✔ Container compose-demo-adminer-1 Started 0.4s
stop apenas para os contêineres (Exited (0)); os contêineres, a rede e o Volume continuam lá. start os inicia novamente.
down: remova os contêineres, mas mantenha os dados
$ docker compose down
[+] down 4/4
✔ Container compose-demo-adminer-1 Removed 0.7s
✔ Container compose-demo-web-1 Removed 0.7s
✔ Container compose-demo-db-1 Removed 0.3s
✔ Network compose-demo_default Removed 0.1s
down removeu os contêineres e a rede, mas não removeu o Volume. Execute up novamente, e os dados continuarão lá:
$ docker compose up -d
[+] up 4/4
✔ Network compose-demo_default Created 0.1s
✔ Container compose-demo-web-1 Started 0.7s
✔ Container compose-demo-db-1 Started 1.1s
✔ Container compose-demo-adminer-1 Started 1.6s
$ docker compose exec db psql -U postgres -c "SELECT * FROM guestbook;"
id | name | message
----+--------+---------------------
1 | Docker | Hello from Compose!
(1 row)
down -v: remova também os dados
$ docker compose down -v
[+] down 5/5
✔ Container compose-demo-adminer-1 Removed 0.7s
✔ Container compose-demo-web-1 Removed 0.7s
✔ Container compose-demo-db-1 Removed 0.2s
✔ Volume compose-demo_pgdata Removed 0.1s
✔ Network compose-demo_default Removed 0.1s
A opção -v também remove o Volume compose-demo_pgdata, apagando os dados do banco de dados. Tenha cuidado ao usar down -v em produção.
Resumo das operações básicas
docker compose up -d # Cria e inicia todos os serviços em segundo plano
docker compose ps # Verifica o status dos serviços
docker compose logs -f # Acompanha os logs de todos os serviços
docker compose logs -f db # Mostra apenas db
docker compose stop # Para (os contêineres são mantidos)
docker compose start # Inicia novamente
docker compose down # Para e remove os contêineres e a rede (o Volume é mantido)
docker compose down -v # Remove também o Volume (os dados serão perdidos!)
Depois de modificar compose.yaml, execute docker compose up -d novamente. O Compose recria apenas os serviços que foram alterados (veja o exemplo em Comandos do docker compose).
Nome do projeto e nome do arquivo
- Por padrão, o nome do projeto é o nome da pasta. Você também pode especificar
name: myprojectno início decompose.yamlou usardocker compose -p myproject. - Por padrão, o Compose procura, nesta ordem, por
compose.yaml,compose.yml,docker-compose.yamledocker-compose.yml. Para projetos novos, recomendamos usarcompose.yaml. version: "3.8"no início do arquivo é uma sintaxe antiga. Atualmente, não é mais necessário e, se você incluí-lo, apenas receberá um aviso.
Próximos passos
- Explicação completa da sintaxe de compose.yaml: build, ports, volumes, environment, depends_on, healthcheck...
- Comandos comuns do docker compose
- Exemplo prático: configure o WordPress com Compose
Recapitulação
compose.yamldescreve vários serviços, redes e Volumes, que podem ser iniciados todos com um único comando.- O Compose cria automaticamente uma rede para o projeto, e os serviços se conectam uns aos outros usando os nomes dos serviços.
docker compose downmantém o Volume;down -vexclui os dados.- O Docker Desktop exibe os projetos do Compose agrupados.
Exercícios
Exercício 1: No projeto deste capítulo, use um único comando para ver apenas as 5 últimas linhas de log do serviço db.
Resposta
docker compose logs --tail 5 db
Exercício 2: Depois de executar docker compose down e, em seguida, up -d, as tabelas criadas no Adminer ainda estarão lá? E se você usar down -v?
Resposta
Depois de down, os dados continuam lá porque o Volume pgdata é mantido; down -v exclui o Volume, o banco de dados é inicializado novamente e as tabelas desaparecem.
Perguntas frequentes
Qual é a diferença entre docker-compose e docker compose?
docker-compose (com hífen) é o programa independente v1, que não recebe mais manutenção; hoje, use o plugin docker compose da Docker CLI (com espaço). Este tutorial usa a v5.
Tanto compose.yaml quanto docker-compose.yml funcionam?
Sim. O Compose procura os arquivos nessa ordem. Para novos projetos, recomendamos compose.yaml.
Como o nome do projeto é definido?
Por padrão, é o nome da pasta onde está o compose.yaml. Os nomes dos contêineres, da rede e do Volume recebem esse nome como prefixo. Você pode defini-lo com name: ou -p.
Atualizado 14 de outubro de 2026