SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-28

Docker Compose: comandos essenciais em servidores

Veja os comandos Compose V2 usados no dia a dia: subir serviços, aplicar mudanças, consultar logs, abrir shells e limpar volumes e redes com segurança.

Os comandos do Compose que vai realmente utilizar

O Docker Compose disponibiliza mais de quarenta subcomandos. O trabalho diário num servidor utiliza cerca de uma dúzia. Esta página agrupa-os pela tarefa que está a executar, apresenta uma razão simples para cada um e aponta para a explicação detalhada quando um comando esconde uma armadilha.

Tudo aqui utiliza o Compose V2: docker compose com um espaço, e não o script antigo docker-compose. O V2 é um plugin Go que é instalado com o Docker Engine, e o V1 deixou de fazer parte dos pacotes atuais. Por isso, um docker-compose: command not found numa instalação nova do Ubuntu em julho de 2026 é esperado, não indica uma falha. Confirme com docker compose version. Se não for apresentada qualquer saída, instale o pacote docker-compose-plugin.

Todos os comandos abaixo são executados a partir do diretório que contém o seu compose.yaml, porque o Compose obtém o nome do projeto desse diretório e procura o ficheiro relativamente a ele. Execute o mesmo comando um nível acima e o Compose termina com no configuration file provided: not found. Se o formato do ficheiro ainda lhe for desconhecido, comece por um primeiro ficheiro Compose num VPS e volte aqui para consultar os comandos.

Ciclo de vida: os quatro comandos que escreve e o que remove contentores

docker compose up -d
docker compose up -d --wait
docker compose stop
docker compose start
docker compose restart web
docker compose down

up -d cria a rede, cria os contentores, inicia-os e termina. Termina assim que os contentores são criados, e é por isso que um script de implementação que execute uma verificação curl logo a seguir falha frequentemente na primeira tentativa. up -d --wait bloqueia até que todos os serviços que declaram uma verificação de integridade indiquem um estado saudável e termina com um código diferente de zero se algum nunca o alcançar. A opção só é tão boa quanto a verificação que executa, por isso escreva uma verificação de integridade em que o Compose possa confiar antes de depender dela na automatização.

stop para os contentores e mantém-nos, por isso start volta a iniciar os mesmos contentores com a mesma camada gravável. down para os contentores e depois remove-os, juntamente com a rede do projeto. Tudo o que for escrito dentro do contentor e fora de um volume é eliminado com eles. Este é o equívoco mais dispendioso no Compose, e a diferença completa entre down e stop explica onde ele causa problemas.

restart não é um reload. Para e inicia o mesmo contentor com a configuração que este já tem, por isso uma variável de ambiente alterada, uma nova tag de imagem ou um mapeamento de portas editado não produzem qualquer efeito. Para aplicar uma alteração no ficheiro, execute novamente up -d. O Compose compara cada serviço com o respetivo contentor em execução e recria apenas os contentores cuja configuração foi alterada.

Aplicar uma alteração: recriar, obter ou reconstruir

docker compose up -d --force-recreate
docker compose pull && docker compose up -d
docker compose build --no-cache web
docker compose up -d --build web

up -d isoladamente não faz nada quando não há alterações, o que o torna seguro para executar repetidamente. --force-recreate ignora essa comparação e substitui todos os contentores, mesmo quando a configuração é idêntica. Por isso, é a forma mais rápida de limpar um estado estranho dentro dos contentores.

Atualizar uma imagem requer dois comandos porque eles executam tarefas diferentes. pull baixa a imagem atual para cada tag indicada no ficheiro. up -d deteta então que o ID da imagem do serviço já não corresponde ao do contentor em execução e recria-o. Se ignorar o pull, up -d mantém o latest do mês passado em execução sem apresentar erros. O risco oposto ocorre numa stack com vários serviços, onde fazer pull de latest para todos os serviços ao mesmo tempo pode interromper uma aplicação que estava a funcionar dez segundos antes. Por isso, um workspace AFFiNE autoalojado fixa cada uma das quatro tags de imagem. A fixação também transforma uma atualização numa edição deliberada da tag, seguida do mesmo pull e da recriação. Numa stack que migra a base de dados durante o arranque, deve ter um dump disponível antes de executar qualquer um dos comandos. É esse o procedimento seguido por um help desk Chatwoot autoalojado em cada atualização de versão.

build aplica-se a serviços que declaram uma secção build: em vez de uma image:. up -d --build compila e inicia num único passo. Este é o ciclo normal enquanto altera o código. Use --no-cache apenas quando uma camada em cache estiver claramente desatualizada, porque este comando reconstrói todas as camadas de raiz. Quando uma stack é implementada a partir de uma tag git obtida por checkout, em vez de uma imagem de um registry, esse mesmo ciclo de compilação também é o processo de atualização. É assim que um rastreador de treinos openGym autoalojado passa de uma versão fixa para a seguinte.

O que está em execução

docker compose ps
docker compose ps -a
docker compose logs -f --tail=100
docker compose logs --since 15m --timestamps db
docker compose top
docker compose ls

ps lista apenas os contentores em execução. Um serviço que falhou durante o arranque não aparece nessa listagem até adicionar -a. Por isso, um contentor ausente em ps enquanto ps -a o mostra como Exited (1) representa normalmente uma falha de arranque. Leia o código de saída e depois consulte os logs.

logs -f acompanha todos os serviços em simultâneo e acrescenta o nome do serviço no início de cada linha. Esta é a vista adequada quando os serviços comunicam entre si e a ordem dos eventos é importante. Indique um serviço para limitar a saída. --tail=100 é importante num contentor que está em execução há um mês, porque, por predefinição, mostra todo o histórico e enche o terminal. --since 15m responde à pergunta mais comum: o que aconteceu durante o reinício que acabou de fazer.

top lista os processos dentro de cada contentor. Isto permite distinguir entre "o contentor está em execução" e "o processo dentro dele está em execução". ls sai do diretório atual e lista todos os projetos Compose no host com o respetivo estado. Assim, pode localizar a stack que iniciou há três meses.

Obter um shell dentro de um serviço

docker compose exec web sh
docker compose exec -u root web sh
docker compose run --rm web env
docker compose run --rm --no-deps web sh

exec executa um comando dentro de um contentor que já está em execução. run inicia um novo contentor a partir da mesma definição de serviço. É isso que deve usar quando o serviço não permanece ativo tempo suficiente para permitir a execução de um comando. Associe sempre run a --rm. Sem essa opção, cada execução deixa um contentor parado, e esses contentores acumulam-se até docker compose ps -a ficar ilegível.

Experimente sh antes de bash. As imagens baseadas em Alpine não incluem bash, e a falha apresenta exec: "bash": executable file not found in $PATH. Adicionar --no-deps a run ignora as dependências do serviço. Assim, uma verificação rápida da configuração não inicia toda a sua base de dados.

run --rm web env é a forma mais rápida de ver o ambiente que um serviço recebeu efetivamente, depois de todos os ficheiros .env, blocos environment: e variáveis de shell terem sido combinados. Quando um valor está incorreto, a causa costuma ser a ordem de combinação. como o Compose resolve ficheiros env e secrets explica qual fonte tem precedência.

Redes, portas e resolução de nomes

docker compose port web 80
docker compose exec web getent hosts db
docker compose config --networks

O Compose coloca todos os serviços numa única rede do projeto, e cada nome de serviço funciona como um nome DNS nessa rede. Executar getent hosts db dentro de web mostra o IP do contentor quando a resolução funciona e não mostra nada quando falha. Assim, responde em dois segundos à pergunta "estes contentores conseguem comunicar entre si?". Se o nome for resolvido, mas a ligação for recusada, o processo dentro de db está associado a 127.0.0.1 em vez de 0.0.0.0. Por isso, nunca aceita um pacote de outro contentor. O mesmo limite explica por que razão um contentor iniciado fora do projeto, seja por docker run ou como a sua própria stack, não consegue resolver um nome como jellyfin. Esta é a primeira verificação a fazer quando um frontend Halcyon para a sua biblioteca Jellyfin não consegue alcançar o servidor configurado. O restante modelo é explicado em como funcionam as redes do Compose e o DNS dos serviços.

port web 80 mostra o endereço e a porta do host onde a porta de um contentor foi publicada. Isto evita ter de adivinhar quando o mapeamento veio de uma variável. A publicação de uma porta também cria uma regra de firewall que o Docker gere diretamente. Essa regra fica à frente das suas regras. Por isso, um serviço que considerava privado pode ficar exposto à Internet. Esse caso é explicado em por que motivo as portas Docker publicadas ignoram o ufw. Manter essas portas não publicadas e colocar à frente dos serviços um único proxy com autenticação na rede do projeto é uma configuração mais segura. É isso que executar o Authentik como camada de início de sessão único proporciona.

Volumes e dados

docker compose config --volumes
docker compose cp db:/etc/postgresql/pg_hba.conf ./pg_hba.conf
docker compose down -v

config --volumes lista os volumes nomeados declarados pelo projeto, um por linha. Essa lista é o que precisa de ser incluído na cópia de segurança. Quando os volumes contêm dados insubstituíveis, o comando exato de cópia de segurança é tão importante como a lista. Por isso, a comparação entre PhotoPrism e Immich especifica os comandos de dump e cópia necessários para cada servidor de fotografias. cp copia um ficheiro para dentro ou para fora de um contentor sem abrir uma shell, usando a forma service:path no lado que corresponde ao contentor.

down -v remove esses volumes nomeados juntamente com os contentores. É o comando correto para desmontar uma stack de teste e o comando errado para qualquer stack que contenha dados importantes, porque não existe confirmação nem possibilidade de desfazer a operação. Os bind mounts sobrevivem a esta operação, porque ficam no sistema de ficheiros do host. Essa diferença no alcance do impacto é uma das razões para escolher deliberadamente entre bind mounts e volumes nomeados.

Limpeza que liberta espaço em disco sem perder dados

docker compose down --remove-orphans
docker system df
docker image prune -a
docker builder prune

--remove-orphans elimina os contentores que pertencem ao projeto, mas que já não aparecem no ficheiro. É exatamente o que acontece depois de mudar o nome de um serviço. Sem esta opção, esses contentores continuam em execução e ficam invisíveis para docker compose ps.

docker system df mostra onde o espaço em disco está a ser utilizado antes de eliminar qualquer coisa. Separa as imagens, os contentores, os volumes locais e a cache de compilação, com um valor recuperável para cada categoria. image prune -a remove todas as imagens para as quais nenhuma tag aponta. Num servidor que tenha obtido várias versões de uma imagem grande, esta operação costuma libertar mais espaço. builder prune limpa a cache de compilação, que cresce silenciosamente em qualquer servidor que compile as próprias imagens.

Nenhum desses comandos afeta um volume nomeado. Apenas docker volume prune e docker compose down -v o fazem.

Verificando o ficheiro antes que cause problemas

docker compose config --quiet
docker compose config --services
docker compose --dry-run up -d

config --quiet valida o ficheiro e não imprime nada quando a validação é bem-sucedida, por isso deve ser usado numa etapa de pré-implantação ou num hook do git. config simples imprime o ficheiro totalmente combinado e interpolado. É assim que confirma que uma variável foi resolvida e que um ficheiro de override foi aplicado conforme esperado. Uma variável não definida aparece como um valor vazio, acompanhada do aviso The "X" variable is not set. Defaulting to a blank string.

--dry-run é uma flag global, não uma flag de subcomando, por isso fica antes de up. Imprime todas as ações que o Compose executaria e não altera nada. São trinta segundos bem aproveitados antes de um down numa stack importante.

Trabalhar com ficheiros, perfis e projetos

docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose --profile debug up -d
docker compose -p staging up -d

Vários sinalizadores -f são combinados pela ordem apresentada, e os ficheiros posteriores substituem as chaves dos ficheiros anteriores. Esta é a forma padrão de manter um ficheiro base com uma pequena substituição para produção. No entanto, as regras diferem para listas e mapas. Leia como o Compose combina vários ficheiros antes de investigar um resultado inesperado.

--profile inicia os serviços associados a esse perfil juntamente com os serviços sem perfil, mantendo as ferramentas de depuração fora de um up normal. -p define o nome do projeto, permitindo executar lado a lado duas cópias da mesma stack, com redes e nomes de volumes separados. Recuperar a stack depois de um reboot não é algo que se faça introduzindo um comando. É uma unidade que executa esse comando por si, conforme descrito em iniciar stacks do Compose no boot.

FAQ

O que substituiu docker-compose com um hífen?

O Compose V2, invocado como docker compose com um espaço. É um plugin incluído no Docker Engine, e a ferramenta Python V1 já não é instalada pelos pacotes atuais. Se a forma com espaço não produzir saída, instale o pacote docker-compose-plugin da sua distribuição. Atualize os scripts antigos para usarem a forma com espaço em vez de adicionar um alias, porque a V2 tem flags que a V1 nunca teve.

Por que docker compose restart não aplica a alteração à minha configuração?

restart para e inicia o container existente com a configuração usada na sua criação e nunca volta a ler compose.yaml. Qualquer alteração a variáveis de ambiente, portas, volumes ou à tag da imagem exige docker compose up -d, que compara cada serviço com o respetivo container em execução e recria os que forem diferentes. Adicione --force-recreate quando quiser forçar a substituição, mesmo que nada no ficheiro tenha mudado.

Como atualizo um serviço para uma imagem mais recente?

Execute docker compose pull e depois docker compose up -d. O pull obtém a imagem atual para cada tag presente no ficheiro, e up -d recria qualquer serviço cujo ID da imagem já não corresponda ao do seu container. Executar up -d isoladamente reutiliza a imagem já existente no disco. É assim que uma stack fixada em latest pode continuar a usar uma build com meses sem apresentar qualquer erro.

Quais comandos de limpeza são seguros num servidor em produção?

docker system df, docker image prune -a e docker builder prune removem apenas imagens e cache. Os serviços em execução continuam a funcionar e os volumes nomeados não são alterados. O par perigoso é docker compose down -v e docker volume prune, que elimina volumes nomeados sem pedir confirmação. Execute primeiro docker compose config --volumes para saber o que está em risco.

Posso executar um comando sem iniciar a stack inteira?

Sim. docker compose run --rm --no-deps web sh inicia um único container a partir da definição do serviço web, ignora as dependências e remove o container quando sair. Use exec quando o container já estiver em execução, porque exec se liga ao processo ativo e mostra o estado real do serviço.