Docker para Desenvolvedores - Parte 6: Orquestrando com Docker Compose
Ao longo desta série, vimos containers, volumes, redes e gerenciamento de imagens, sempre usando comandos individuais do docker run, docker network create, docker volume create, etc. Isso funciona, mas se torna trabalhoso (e propenso a erros) conforme uma aplicação passa a depender de múltiplos serviços. É aí que o Docker Compose entra: ele permite descrever toda essa configuração em um único arquivo declarativo, tornando o processo mais limpo, mais fácil de repetir e de versionar em um repositório Git.
Criando seu docker-compose.yaml
Um docker-compose.yaml mínimo
A estrutura mais simples possível, rodando um único serviço:
services:
web:
image: httpd
ports:
- "8080:80"
Isso já é equivalente a rodar docker run -p 8080:80 httpd, mas de forma declarativa, reaplicável e fácil de versionar.
Acrescentando um volume
Para persistir dados desse serviço (como vimos na Parte 3 desta série), basta adicionar uma seção volumes:
services:
web:
image: httpd
ports:
- "8080:80"
volumes:
- web-data:/usr/local/apache2/htdocs
volumes:
web-data:
Repare que o volume precisa ser declarado em dois lugares: referenciado dentro do serviço (volumes: dentro de web) e definido na seção raiz volumes: no final do arquivo, é ali que o Compose realmente cria o volume nomeado.
Acrescentando uma rede
Da mesma forma, é possível declarar redes customizadas (vistas na Parte 4):
services:
web:
image: httpd
ports:
- "80:80"
volumes:
- web-data:/usr/local/apache2/htdocs
networks:
- app-network
volumes:
web-data:
networks:
app-network:
Na prática, quando você não declara uma rede explicitamente, o Compose já cria uma rede padrão para o projeto automaticamente, permitindo que os serviços do mesmo
docker-compose.yamlse enxerguem entre si pelo nome. Declarar redes manualmente vale a pena quando você precisa de mais de uma rede isolada, ou quer conectar serviços de arquivos Compose diferentes.
Subindo os containers
Para criar e iniciar todos os serviços definidos no arquivo:
$ docker compose up
Assim como no docker run, o terminal fica preso mostrando os logs de todos os serviços. Para rodar em segundo plano:
$ docker compose up -d
Derrubando os containers
Para parar e remover os containers, redes e (por padrão) preservar os volumes criados pelo Compose:
$ docker compose down
Por padrão,
docker compose downnão remove volumes, isso evita perda acidental de dados. Se você quiser remover os volumes também, usedocker compose down -v(com cautela).
Juntando vários containers: App + Database + Redis
O verdadeiro poder do Compose aparece quando uma aplicação depende de múltiplos serviços trabalhando juntos. Um exemplo comum: um proxy Nginx na frente, uma aplicação, um banco de dados MySQL e um cache Redis.
services:
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- app
networks:
- app-network
app:
image: myapp:1.0.0
environment:
DB_HOST: db
DB_USER: appuser
DB_PASSWORD: apppassword
REDIS_HOST: redis
depends_on:
- db
- redis
networks:
- app-network
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: appdb
MYSQL_USER: appuser
MYSQL_PASSWORD: apppassword
volumes:
- db-data:/var/lib/mysql
networks:
- app-network
redis:
image: redis:alpine
networks:
- app-network
volumes:
db-data:
networks:
app-network:
Alguns pontos importantes desse exemplo:
-
depends_on: define a ordem de inicialização dos containers (oappsó sobe depois dodbe doredis). Vale notar que isso garante apenas a ordem de início do container, não que o serviço interno (como o MySQL) já esteja pronto para aceitar conexões, para isso, a aplicação normalmente precisa implementar alguma lógica de retry na conexão com o banco; -
Variáveis de ambiente (
environment): usadas para configurar a aplicação e o MySQL sem precisar alterar imagens ou hardcodar valores; -
db-data: volume nomeado garantindo que os dados do MySQL sobrevivam a reinicializações e recriações do container; -
app-network: todos os serviços compartilham a mesma rede, permitindo que se comuniquem entre si pelo nome do serviço (db,redis) em vez de IPs fixos.
Subindo tudo de uma vez:
$ docker compose up -d
Com um único comando, o Compose cria a rede, os volumes, e sobe os quatro containers já conectados e prontos para se comunicar entre si.
Considerações finais da série
Ao longo desta série, cobrimos o ciclo completo do Docker no dia a dia: instalação, comandos essenciais da CLI, persistência de dados com volumes, comunicação entre containers via redes, gerenciamento e publicação de imagens, e, por fim, orquestração de múltiplos serviços com Docker Compose. Com essa base, você já tem tudo o que precisa para rodar aplicações containerizadas de forma profissional, seja em um ambiente de desenvolvimento local, seja em um servidor de produção.
Para quem quiser ir além de um único host, o próximo passo natural é o Kubernetes, que resolve os mesmos problemas de orquestração, mas em escala, distribuindo containers entre múltiplos servidores.
Você pode encontrar uma série de artigo que fiz sobre kubernetes
Top comments (0)