Alternar tema

Docker Compose com vários serviços: inicie o ambiente de desenvolvimento local com um único comando

Easton editorial illustration: route-map drafting table

Na tarde do meu primeiro dia de trabalho, eu encarava a quinta mensagem de erro na tela: a porta do MySQL estava ocupada, a versão do Redis era incompatível e o RabbitMQ simplesmente não conectava. Um colega mais experiente olhou para a minha tela e suspirou: “Há quanto tempo você está instalando tudo isso?”

“Desde as 9 da manhã”, respondi em voz baixa.

Quatro horas. Levei quatro horas para instalar três bancos de dados. E aquilo era apenas o começo: ainda faltavam ElasticSearch e MongoDB.

Foi quando percebi pela primeira vez que preparar um ambiente de desenvolvimento local era um problema enorme, daqueles que parecem não ter fim.

Mais tarde, nossa equipe adotou o Docker Compose. Um novo integrante clonava o repositório, executava docker-compose up -d e, em 5 minutos, todos os serviços estavam ativos. MySQL, Redis, RabbitMQ, API e Web: um único comando e tudo organizado. Para trocar de projeto, bastava mudar de diretório e iniciar outro arquivo Compose. Para limpar, docker-compose down -v removia inclusive os volumes, sem deixar resíduos.

É essa mudança que quero compartilhar neste artigo: como usar o Docker Compose para orquestrar vários serviços e transformar o ambiente de desenvolvimento local de um pesadelo em algo resolvido com um único comando.

Por que orquestrar vários serviços

Para falar a verdade, dez anos atrás, quando trabalhávamos com aplicações monolíticas, configurar o ambiente era muito simples: instalar o JDK, definir a string de conexão com o banco de dados e executar o projeto. Hoje é diferente.

A maioria dos projetos foi dividida em uma arquitetura de microsserviços ou, no mínimo, separa frontend e backend. Um ambiente de desenvolvimento local típico precisa de pelo menos estes componentes: um serviço Web para o frontend, uma API para o backend, MySQL para os dados de negócio, Redis para cache e sessões e RabbitMQ para mensagens assíncronas. Alguns projetos também usam ElasticSearch para busca e MongoDB para armazenar logs.

É aí que começam os problemas.

O sofrimento da instalação manual

É preciso instalar tudo em cada máquina. Qual versão do MySQL escolher: 5.7 ou 8.0? Se a versão estiver errada, a sintaxe SQL pode ser incompatível. No Redis, é preciso configurar a porta: a padrão é 6379, mas e se outro serviço já estiver usando essa porta? O RabbitMQ ainda exige a instalação do ambiente de execução Erlang. Só o tutorial de instalação do RabbitMQ me tomou meia hora.

Depois da instalação, ainda há conflitos de versão. Um projeto anterior pode ter deixado dados de uma versão antiga do MySQL na máquina. Uma porta entra em conflito e o serviço não inicia. Depois de muito investigar, você descobre que havia um processo zumbi que não foi encerrado corretamente.

O pior é trocar de projeto. Você acaba o projeto A e precisa passar para o projeto B. O MySQL do projeto A está usando a porta 3306, e o projeto B também quer usar 3306. É preciso alterar o arquivo de configuração ou parar os serviços do projeto A. Dois dias depois, você volta ao projeto A e precisa desfazer as alterações.

É um trabalho repetitivo e desgastante.

O pesadelo da colaboração em equipe

“Na minha máquina funciona.”

Toda equipe já ouviu essa frase. Um novo integrante clona o código, instala o ambiente e o projeto não funciona. Por quê? O projeto antigo usava MySQL 5.7, mas a pessoa instalou o 8.0; o Redis do projeto não tinha senha, mas o Redis local foi configurado com senha. Ela altera vários trechos dos arquivos de configuração e, mesmo assim, nada funciona.

Por fim, um colega mais experiente precisa ajudar. Os dois passam mais de meio dia até fazer o ambiente funcionar.

E assim um dia inteiro é desperdiçado.

A solução proposta pelo Compose

A ideia do Docker Compose é simples: empacotar todos os serviços em contêineres e gerenciá-los em conjunto por meio de um único arquivo de configuração.

Você não precisa se preocupar em instalar cada banco de dados, configurar versões ou distribuir portas. Tudo fica definido no arquivo Compose. Um comando inicia os serviços exatamente conforme a configuração. Para trocar de projeto, mude de diretório e execute outro arquivo Compose. Para limpar, um comando remove todos os contêineres e volumes.

É como trocar a tarefa de montar um computador peça por peça pela compra de uma máquina pronta. Você não precisa descobrir como encaixar a memória nem como conectar os cabos de energia da placa de vídeo: o fabricante já fez isso, e basta ligar o equipamento.

Configuração essencial do docker-compose.yml

Comecemos por um arquivo de configuração completo. Imagine que o projeto tenha quatro serviços: frontend Web, backend API, banco de dados MySQL e cache Redis.

# docker-compose.yml
version: "3.8"  # versão do arquivo Compose; 3.8 aceita a maioria das opções de configuração

services:
  # serviço Web do frontend
  web:
    build: ./frontend  # cria a imagem a partir do diretório local frontend
    ports:
      - "3000:3000"  # porta 3000 do host -> porta 3000 do contêiner
    depends_on:
      - api  # depende do serviço api, que inicia primeiro
    environment:
      - API_URL=http://api:8080  # endereço usado pelo frontend para acessar o backend

  # serviço API do backend
  api:
    build: ./backend  # cria a imagem a partir do diretório local backend
    ports:
      - "8080:8080"
    depends_on:
      - mysql
      - redis  # depende do banco de dados e do cache
    environment:
      - DB_HOST=mysql  # endereço do banco de dados (nome do contêiner)
      - DB_PORT=3306
      - DB_USER=root
      - DB_PASSWORD=dev123  # senha do ambiente de desenvolvimento; em produção, use um arquivo .env
      - REDIS_HOST=redis
      - REDIS_PORT=6379

  # banco de dados MySQL
  mysql:
    image: mysql:8.0  # usa diretamente a imagem oficial, sem construir outra
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=dev123
      - MYSQL_DATABASE=myapp  # cria o banco de dados automaticamente
    volumes:
      - mysql_data:/var/lib/mysql  # persiste os dados no volume

  # cache Redis
  redis:
    image: redis:7-alpine  # a versão alpine é menor
    ports:
      - "6379:6379"

volumes:
  mysql_data:  # define o volume usado para persistir os dados do MySQL

Explicação dos principais campos

Em services, você define todos os serviços. Cada um pode ter três origens: build cria uma imagem a partir do código local, image baixa diretamente uma imagem oficial ou você pode combinar os dois, construindo localmente com base em uma imagem específica.

ports define o mapeamento de portas. O formato é "porta do host:porta do contêiner". Na configuração acima, a Web usa 3000, a API usa 8080, o MySQL usa 3306 e o Redis usa 6379. Se uma porta local estiver ocupada, altere a porta do host. Por exemplo, com "13006:3306", você se conecta ao MySQL por localhost:13006.

depends_on controla a ordem de inicialização. MySQL e Redis iniciam primeiro, depois a API, que depende deles, e por último a Web, que depende da API. Mas há uma armadilha que veremos adiante.

environment define variáveis de ambiente. Senhas do banco de dados, endereços de conexão e portas podem ser configurados aqui. Em produção, não coloque senhas diretamente nesse campo; use um arquivo .env ou injete variáveis de ambiente.

volumes garante a persistência dos dados. Os dados do MySQL são armazenados no volume mysql_data, portanto não são perdidos quando o contêiner é removido. Na próxima inicialização, eles continuarão disponíveis.

Uma armadilha comum

O nome do contêiner corresponde ao nome do serviço. Na configuração acima, a API se conecta ao banco de dados usando DB_HOST=mysql, e não localhost. Por quê?

Cada contêiner tem seu próprio ambiente de rede. Dentro do contêiner da API, localhost aponta para o próprio contêiner da API, não para a máquina host nem para o contêiner do MySQL. O Compose cria automaticamente uma rede interna, e os serviços usam seus nomes para se comunicar. O nome mysql é o endereço do contêiner do MySQL nessa rede.

Na primeira vez que escrevi um arquivo Compose, caí nessa armadilha: usei localhost:3306 e não consegui me conectar ao banco de dados. Só depois descobri que precisava usar o nome do contêiner.

Dependências e ordem de inicialização dos serviços

O depends_on parece simples: o MySQL inicia primeiro e a API depois. Na prática, há uma questão sutil.

O depends_on do Compose garante apenas a ordem de inicialização dos contêineres, não a ordem em que os serviços ficam prontos. Em outras palavras, o contêiner do MySQL pode ter iniciado enquanto o serviço MySQL ainda não aceita conexões, pois está inicializando o banco, carregando configurações ou abrindo a porta de escuta. Se a API tentar se conectar nesse momento, provavelmente falhará.

Já passei por isso. Logo depois de executar docker-compose up, a API apresentou um erro de conexão com o banco de dados. Dez segundos depois, tentei novamente e funcionou. O contêiner do MySQL estava ativo, mas o serviço ainda não estava pronto.

Solução 1: verificação de integridade

O Compose permite adicionar uma verificação de integridade à configuração. O serviço dependente só inicia depois que essa verificação é aprovada.

services:
  mysql:
    image: mysql:8.0
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s  # verifica a cada 5 segundos
      timeout: 3s   # tempo limite
      retries: 10   # considera unhealthy somente depois de 10 falhas
    # ... outras configurações

  api:
    depends_on:
      mysql:
        condition: service_healthy  # aguarda a aprovação da verificação de integridade do MySQL

O MySQL executa mysqladmin ping para verificar se consegue aceitar conexões. A verificação ocorre a cada 5 segundos, com no máximo 10 tentativas, totalizando 50 segundos. A API só inicia quando a verificação é aprovada.

Esse método funciona, mas tem uma desvantagem: você precisa escrever uma configuração de integridade para cada serviço. Algumas imagens oficiais, como a do Redis, não oferecem um comando conveniente para isso, então é necessário criar outra solução.

Solução 2: tentativas na aplicação

Uma opção mais prática é implementar tentativas na própria aplicação. Se a conexão falhar, aguarde alguns segundos e tente novamente. Se o MySQL demorar para iniciar, basta esperar até que esteja pronto.

Uma estratégia comum é o backoff exponencial: aguarde 1 segundo na primeira tentativa, 2 segundos na segunda, 4 segundos na terceira e aumente o intervalo gradualmente. A maioria dos bancos de dados fica pronta em até 30 segundos.

Em Node.js, você pode usar a configuração do pool de conexões do mysql2:

const pool = mysql.createPool({
  host: 'mysql',
  port: 3306,
  user: 'root',
  password: 'dev123',
  database: 'myapp',
  waitForConnections: true,  // aguarda uma conexão ficar disponível
  connectionLimit: 10,
  queueLimit: 0,
});

Em Python, use a biblioteca tenacity para implementar as tentativas:

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(5), wait=wait_exponential(multiplier=1, min=2, max=10))
def connect_db():
    return mysql.connector.connect(host='mysql', ...)

Como escolher entre as duas soluções

A verificação de integridade é mais precisa: a API só inicia quando o banco de dados está realmente pronto. Porém, a configuração é um pouco mais trabalhosa, pois cada banco precisa de um comando de verificação específico.

As tentativas na aplicação são mais simples: bastam algumas linhas de código, sem alterar a configuração do Compose. A desvantagem é que, depois de iniciar, a API pode passar algum tempo repetindo as tentativas, e os logs mostrarão erros de conexão, embora isso não afete o resultado final.

Eu prefiro as tentativas na aplicação porque dão menos trabalho e funcionam bem na maioria dos casos. Deixo a verificação de integridade como alternativa para serviços que demoram especialmente para iniciar.

Estratégia de configuração para vários ambientes

As configurações de desenvolvimento local, teste e produção costumam ser diferentes. Um exemplo é o mapeamento de portas: no desenvolvimento, é útil expor a porta do banco de dados para depurar localmente; em produção, isso não é necessário, pois o banco deve ser acessado apenas pela rede interna dos contêineres.

Se todas essas configurações estiverem no mesmo arquivo, trocar de ambiente exige editar o conteúdo e depois desfazer as mudanças. Além de inconveniente, isso aumenta o risco de erro.

O Compose resolve esse problema com um arquivo base e arquivos de sobreposição.

Arquivo base: configuração compartilhada

O docker-compose.yml contém as configurações compartilhadas por todos os ambientes: definição dos serviços, versões das imagens, rede interna e volumes de dados.

# docker-compose.yml (configuração base)
version: "3.8"

services:
  web:
    build: ./frontend
    # ports não é definido aqui; o arquivo de sobreposição o complementa

  api:
    build: ./backend
    environment:
      - DB_HOST=mysql
      - REDIS_HOST=redis
    # ports não é definido aqui

  mysql:
    image: mysql:8.0
    volumes:
      - mysql_data:/var/lib/mysql
    # ports não é definido aqui; em produção, não é preciso expor a porta

  redis:
    image: redis:7-alpine

volumes:
  mysql_data:

O mapeamento de portas não aparece porque a configuração varia entre ambientes.

Arquivo de sobreposição para desenvolvimento

O docker-compose.override.yml acrescenta as configurações específicas do ambiente de desenvolvimento: mapeamento de portas, senha de desenvolvimento e variáveis de ambiente usadas na depuração.

# docker-compose.override.yml (ambiente de desenvolvimento)
version: "3.8"

services:
  web:
    ports:
      - "3000:3000"  # expõe a porta no desenvolvimento para facilitar o acesso local

  api:
    ports:
      - "8080:8080"
    environment:
      - DEBUG=true  # ativa o modo de depuração no ambiente de desenvolvimento

  mysql:
    ports:
      - "3306:3306"  # expõe a porta do banco no desenvolvimento para facilitar a depuração
    environment:
      - MYSQL_ROOT_PASSWORD=dev123  # senha simples para o ambiente de desenvolvimento

  redis:
    ports:
      - "6379:6379"

O Compose tem um comportamento padrão: ao executar docker-compose up, combina automaticamente docker-compose.yml e docker-compose.override.yml. As configurações dos dois arquivos são mescladas, e o override prevalece sobre a configuração base.

Por isso, no desenvolvimento local, basta executar docker-compose up para obter a configuração completa do ambiente.

Arquivo de sobreposição para produção

O docker-compose.prod.yml acrescenta as configurações de produção: não expõe portas, usa senhas de produção e se conecta a serviços externos.

# docker-compose.prod.yml (ambiente de produção)
version: "3.8"

services:
  web:
    # não expõe a porta; o acesso é feito por um proxy reverso (nginx)

  api:
    environment:
      - DB_HOST={{DB_HOST}}  # lê a variável de ambiente, sem gravar a senha no arquivo
      - DB_PASSWORD={{DB_PASSWORD}}

  mysql:
    # não expõe a porta, impedindo conexões externas diretas
    environment:
      - MYSQL_ROOT_PASSWORD={{MYSQL_ROOT_PASSWORD}}

No ambiente de produção, use o parâmetro -f para especificar os arquivos de configuração:

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Os dois arquivos são combinados, e a configuração de produção prevalece sobre a base. A porta do banco de dados não fica exposta, e a senha é lida das variáveis de ambiente.

Injeção de variáveis de ambiente

Senhas de produção não devem ser gravadas no arquivo. O Compose pode ler os valores de um arquivo .env ou das variáveis de ambiente do sistema.

# arquivo .env (não envie para o Git)
DB_HOST=prod-mysql.internal
DB_PASSWORD=super_secret_password_123
MYSQL_ROOT_PASSWORD=another_secret

No arquivo de configuração, use a sintaxe {{VAR:-default}} para referenciar os valores:

environment:
  - DB_HOST={{DB_HOST:-localhost}}  # se DB_HOST não estiver definida, usa localhost
  - DB_PASSWORD={{DB_PASSWORD:-dev123}}

Não envie o arquivo .env ao controle de versão. Crie um .env.example com valores de exemplo para que cada integrante da equipe possa copiá-lo e preencher sua própria configuração.

Comandos práticos para controlar tudo

Com a configuração pronta, é hora de iniciar, parar e depurar. Estes comandos cobrem praticamente todas as operações do dia a dia.

Iniciar todos os serviços

docker-compose up -d

up inicia todos os serviços. -d significa execução em segundo plano, ou detached mode, e deixa o terminal livre. Sem -d, os logs de todos os serviços são exibidos diretamente no terminal, e Ctrl+C os interrompe.

Durante a inicialização, o Compose baixa imagens quando você usa image, constrói imagens quando usa build, cria os contêineres e inicia os serviços. A primeira execução é mais lenta por causa do download das imagens. Nas próximas, ela será mais rápida porque as imagens já estarão disponíveis.

Ver o status dos serviços

docker-compose ps

Esse comando lista o estado de todos os contêineres. A saída é semelhante a esta:

NAME                COMMAND             SERVICE   STATUS    PORTS
myapp-web-1         "npm start"         web       running   0.0.0.0:3000->3000/tcp
myapp-api-1         "node index.js"     api       running   0.0.0.0:8080->8080/tcp
myapp-mysql-1       "mysqld"            mysql     running   0.0.0.0:3306->3306/tcp
myapp-redis-1       "redis-server"      redis     running   0.0.0.0:6379->6379/tcp

Quando STATUS mostra running, o serviço está funcionando. Se aparecer exited ou error, a inicialização falhou.

Ver os logs de um serviço

docker-compose logs -f api

Esse comando mostra os logs do serviço de API. -f acompanha continuamente a saída, exibindo novos registros em tempo real. Sem -f, apenas os logs existentes são mostrados.

Sem informar o nome do serviço, docker-compose logs -f exibe os logs de todos os serviços, mas a saída pode ficar confusa quando o volume é grande.

Parar e limpar

docker-compose down

Esse comando para todos os contêineres e remove contêineres e redes. Os volumes de dados permanecem, portanto os dados do MySQL continuam disponíveis.

Para fazer uma limpeza completa, incluindo os volumes:

docker-compose down -v

-v remove os volumes. Na próxima inicialização, o MySQL será inicializado novamente e todos os dados terão sido apagados. Esse comando é usado com frequência durante a depuração: quando os dados ficam inconsistentes, você os apaga e recomeça.

Reconstruir uma imagem

Depois de alterar o código, reconstrua a imagem:

docker-compose build api

Esse comando constrói apenas a imagem do serviço de API. Depois, reinicie o contêiner:

docker-compose up -d api

Também é possível construir e reiniciar em uma única etapa:

docker-compose up -d --build api

--build força a reconstrução da imagem, mesmo quando ela já existe.

Tabela de referência dos comandos mais usados

ComandoFunção
docker-compose up -dInicia todos os serviços em segundo plano
docker-compose psMostra o status dos serviços
docker-compose logs -f apiMostra os logs da API
docker-compose downPara e remove os contêineres
docker-compose down -vPara e remove contêineres e volumes de dados
docker-compose restart apiReinicia o serviço de API
docker-compose build apiReconstrói a imagem da API

Esses comandos cobrem 90% das operações diárias. Consulte a documentação quando precisar de outros comandos, como exec, cp ou top.

Conclusão

Compare a eficiência da abordagem tradicional com a do Compose:

OperaçãoAbordagem tradicionalAbordagem com Compose
Preparar o ambiente para um novo integrante4 a 8 horas5 minutos (clone + up)
Trocar de projetoAlterar configurações, parar serviços e reiniciarMudar de diretório e iniciar outro compose
Limpar o ambienteDesinstalar manualmente e procurar processos residuaisRemover contêineres e volumes com um comando
Manter ambientes consistentes na equipeCada máquina pode ser diferenteUm único arquivo de configuração garante ambientes iguais

A diferença é evidente.

Se você ainda instala bancos de dados manualmente, altera arquivos de configuração e investiga conflitos de portas, experimente o Docker Compose. Comece com um projeto simples: uma API e um MySQL. Escreva um docker-compose.yml e execute-o. Quando dominar o processo, acrescente Redis e RabbitMQ e crie configurações para vários ambientes.

Para adotar a solução na equipe, envie docker-compose.yml e docker-compose.override.yml ao repositório e acrescente ao README as etapas de inicialização. Assim, um novo integrante clona o código, executa um único comando e tem o ambiente de desenvolvimento pronto.

Isso é muito mais confiável do que escrever um “manual de configuração do ambiente”. A documentação fica desatualizada; o arquivo de configuração, não.

Orquestração prática de vários serviços com Docker Compose

Use o Docker Compose para orquestrar quatro serviços — Web, API, MySQL e Redis — e iniciar o ambiente de desenvolvimento local com um único comando

⏱️ Estimated time: 15 min

  1. 1

    Step 1: Crie o arquivo docker-compose.yml

    Crie o arquivo de configuração na raiz do projeto:

    ```yaml
    version: "3.8"
    services:
    web:
    build: ./frontend
    ports: ["3000:3000"]
    depends_on: [api]
    api:
    build: ./backend
    ports: ["8080:8080"]
    depends_on: [mysql, redis]
    mysql:
    image: mysql:8.0
    environment:
    MYSQL_ROOT_PASSWORD: dev123
    MYSQL_DATABASE: myapp
    redis:
    image: redis:7-alpine
    ```

    Observação: para a comunicação entre contêineres, use o nome do serviço, como DB_HOST=mysql, e não localhost
  2. 2

    Step 2: Inicie todos os serviços

    Execute no diretório que contém o docker-compose.yml:

    ```bash
    docker-compose up -d
    ```

    • Na primeira execução, o download das imagens pode demorar
    • Nas próximas execuções, as imagens existentes serão usadas e a inicialização levará apenas alguns segundos
    • Sem -d, o terminal ficará ocupado exibindo os logs
  3. 3

    Step 3: Verifique o status dos serviços

    Confirme se todos os contêineres foram iniciados corretamente:

    ```bash
    docker-compose ps
    ```

    • STATUS com running indica funcionamento normal
    • Se aparecer exited ou error, investigue com logs:
    ```bash
    docker-compose logs api
    ```
  4. 4

    Step 4: Configure vários ambientes (opcional)

    Crie o docker-compose.override.yml para o ambiente de desenvolvimento:

    ```yaml
    version: "3.8"
    services:
    mysql:
    ports: ["3306:3306"]
    ```

    • O Compose combina automaticamente o arquivo override
    • No ambiente de produção, especifique os arquivos com -f:
    ```bash
    docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
    ```
  5. 5

    Step 5: Limpe o ambiente

    Pare e remova todos os contêineres:

    ```bash
    docker-compose down # mantém os volumes de dados
    docker-compose down -v # remove os volumes e apaga os dados
    ```

    • Ao trocar de projeto, use down para fazer a limpeza
    • Se os dados estiverem inconsistentes e você quiser recomeçar, use down -v

FAQ

Qual é a diferença entre docker-compose.yml e Dockerfile?
O Dockerfile define as etapas de construção de uma única imagem, enquanto o docker-compose.yml define como vários contêineres trabalham em conjunto. Em resumo: o Dockerfile cria imagens; o Compose gerencia contêineres. Normalmente, um projeto tem um Dockerfile — ou vários, um para cada serviço — e um docker-compose.yml.
O depends_on garante que o serviço esteja pronto?
Não. O depends_on garante apenas a ordem de inicialização dos contêineres, não que os serviços estejam prontos. O contêiner do MySQL pode estar ativo enquanto o serviço ainda está sendo inicializado. Há duas soluções: adicionar um healthcheck ao docker-compose.yml ou implementar tentativas na aplicação. Recomendo as tentativas na aplicação por serem mais simples e confiáveis.
Como acessar um serviço da máquina host a partir de um contêiner?
Use host.docker.internal no Docker Desktop ou o IP da máquina host no Linux. Por exemplo, se o Redis estiver sendo executado no host, conecte-se a host.docker.internal:6379 a partir do contêiner. No Linux, host.docker.internal exige configuração adicional; uma opção mais simples é usar o modo --network host, embora isso elimine o isolamento de rede.
Onde os dados ficam armazenados? Eles são perdidos quando o contêiner é removido?
Os dados configurados em volumes ficam em volumes gerenciados pelo Docker e não são perdidos quando o contêiner é removido. O docker-compose down remove apenas contêineres e redes, não os volumes. Para apagar os dados, use docker-compose down -v. Esse comando é comum durante a depuração no ambiente de desenvolvimento: se os dados ficarem inconsistentes, apague tudo e recomece.
Como gerenciar configurações para vários ambientes, como dev, test e prod?
Use uma estratégia de arquivo base mais arquivos de sobreposição. Coloque a configuração comum no docker-compose.yml, a configuração de desenvolvimento no docker-compose.override.yml, que o Compose carrega automaticamente, e a configuração de produção no docker-compose.prod.yml. Na inicialização, especifique os arquivos com -f: docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d.
O que fazer quando uma porta já está em uso?
Altere o mapeamento da porta no host. Por exemplo, se o MySQL usa 3306:3306 e a porta local 3306 estiver ocupada, mude para 13006:3306 e conecte-se usando localhost:13006. Outra opção é remover a configuração ports e acessar o serviço apenas pela rede interna dos contêineres, o que é mais seguro.

15 min de leitura · Publicado em: 9 abr 2026 · Atualizado em: 4 set 2026

Comentários

Entre com GitHub para comentar

Easton BlogEaston Blog