SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor

Docker Compose: guia rápido para servidores reais

Consulte os comandos Docker Compose V2 mais usados no servidor, com ciclo de vida, mudanças, logs, shells, redes, volumes e limpeza segura. Evite erros comuns.

Os comandos do Compose que você realmente utiliza

O Docker Compose disponibiliza dezenas de subcomandos. O trabalho diário num servidor utiliza cerca de uma dúzia. Esta página agrupa esses comandos pela tarefa que está a realizar, fornece uma razão simples para cada um e indica onde encontrar uma análise detalhada caso o comando esconda alguma armadilha.

Tudo aqui utiliza o Compose V2 ou V5: docker compose com um espaço, não o antigo script docker-compose. Ambos são plugins em Go; no Linux, o plugin Compose é instalado separadamente do Docker Engine. O Ubuntu 24.04 LTS ainda oferece a ferramenta legada em Python V1 como docker-compose na versão 1.29.2-6ubuntu1 no seu repositório universe. Verifique com docker compose version. Se o comando não estiver disponível, configure o repositório do Docker e instale o pacote docker-compose-plugin.

Cada comando abaixo é executado a partir do diretório que contém o seu compose.yaml; o Compose utiliza o nome desse diretório como o nome do projeto por padrão, a menos que o substitua. Sem -f ou COMPOSE_FILE, o Compose procura o diretório de trabalho e os seus pais por um ficheiro de configuração; portanto, executar um nível acima só encontrará a sua stack se o ficheiro ainda estiver nesse caminho de pesquisa. Se o formato do ficheiro for novo para si, comece por um primeiro ficheiro Compose num VPS e regresse aqui para os comandos.

Ciclo de vida: os quatro comandos que você digita e aquele que remove os containers

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 containers, inicia-os e retorna. Ele retorna após iniciar os containers sem aguardar que a aplicação esteja pronta, razão pela qual um script de deploy que o segue com uma verificação curl frequentemente falha na primeira tentativa. up -d --wait aguarda que serviços com healthchecks fiquem saudáveis e que serviços sem eles estejam em execução; um serviço não saudável ou um --wait-timeout expirado causa uma saída com código diferente de zero. A flag é tão eficaz quanto a verificação por trás dela, portanto, escreva um healthcheck em que o Compose possa confiar antes de depender dele na automação.

stop interrompe os containers e os mantém, de modo que start traz os mesmos containers de volta com a mesma camada de escrita. down para os containers e, em seguida, remove-os e a rede do projeto. Qualquer coisa escrita dentro do container e fora de um volume é perdida. Esse é o mal-entendido mais custoso no Compose, e a diferença completa entre down e stop aborda onde isso causa problemas.

restart não é um recarregamento. Ele para e inicia o mesmo container com a configuração que ele já possui, portanto, uma variável de ambiente alterada, uma nova tag de imagem ou um mapeamento de porta editado não têm efeito algum. Para aplicar uma alteração de arquivo, você executa up -d novamente. O Compose compara cada serviço com seu container em execução e recria aqueles cuja configuração ou imagem foi alterada.

Aplicando uma alteração: recriar, baixar 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

O up -d reutiliza contentores em execução quando a sua configuração e imagem permanecem inalteradas; o download e a compilação de imagens seguem a política de pull do serviço. O --force-recreate ignora essa comparação e substitui todos os contentores, mesmo quando a configuração é idêntica, sendo a forma mais rápida de limpar estados anómalos dentro de um contentor.

A rotina explícita de atualização de imagem utiliza dois comandos porque executam funções distintas. O pull descarrega a imagem atual para cada tag especificada no ficheiro. O up -d deteta então que o ID da imagem do serviço já não coincide com o do seu contentor em execução e recria-o. Com a política de pull padrão missing, as tags em cache são reutilizadas, exceto a latest, que é sempre descarregada. O risco oposto surge num stack com múltiplos serviços, onde descarregar a latest para todos os serviços simultaneamente pode quebrar uma aplicação que funcionava dez segundos antes; é por isso que um workspace AFFiNE auto-alojado recomenda fixar a aplicação e a imagem de migração ao mesmo digest. Fixar a versão também transforma uma atualização numa edição deliberada da tag, seguida pelo mesmo processo de pull e recriação. Num stack que migra a base de dados durante o arranque, deve ter um dump à mão antes de qualquer um dos comandos, que é a rotina que um suporte técnico Chatwoot auto-alojado segue para cada atualização de versão.

O build aplica-se a serviços que declaram uma secção build:, incluindo serviços que também declaram uma image:. O up -d --build compila e inicia num único passo, o que constitui o ciclo normal enquanto altera código. Recorra ao --no-cache apenas quando uma camada em cache estiver claramente obsoleta, pois este reconstrói todas as camadas do zero. Alguns projetos disponibilizam ambos os caminhos a partir de um repositório clonado; nestes casos, os dois ciclos são caminhos de atualização alternativos: um rastreador de treinos openGym auto-alojado utiliza o docker compose up -d --build para compilar o seu checkout fixado, uma vez que descarregar as suas imagens latest pode executar uma versão mais recente do que a do checkout.

Verificando 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 fica invisível aí até adicionar -a, portanto, um contentor que não aparece em ps enquanto o ps -a o mostra como Exited (1) é o comportamento normal de uma falha de arranque. Leia o código de saída e, em seguida, leia os logs.

logs -f acompanha todos os serviços simultaneamente e prefixa cada linha com o nome do serviço, que é a vista necessária quando os serviços comunicam entre si e a ordem dos eventos é importante. Indique um serviço para restringir a saída. --tail=100 é importante num contentor que está ativo há um mês, porque a predefinição imprime todo o histórico e inunda o terminal. --since 15m responde à pergunta que normalmente tem, que é o que aconteceu durante o reinício que acabou de efetuar.

top lista os processos dentro de cada contentor, o que separa "o contentor está em execução" de "o processo dentro dele está em execução". ls sai do diretório atual e lista os projetos Compose em execução no host com o respetivo estado; adicione -a para incluir projetos parados.

Obtendo 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 container que já está em execução. run inicia um novo container a partir da mesma definição de serviço, o que é necessário quando o serviço não permanece ativo tempo suficiente para realizar o exec. Sempre utilize run em conjunto com --rm, pois, sem isso, cada invocação deixa um container parado para trás, e eles acumulam-se até que docker compose ps -a se torne ilegível.

Tente sh antes de bash. Algumas imagens baseadas em Alpine incluem bash, incluindo a imagem oficial do PostgreSQL Alpine; quando ele está ausente, a falha é exibida como exec: "bash": executable file not found in $PATH. Adicionar --no-deps ao run ignora as dependências do serviço, o que evita que uma verificação rápida de configuração inicie todo o seu banco de dados.

run --rm web env é a forma mais rápida de visualizar o ambiente que um serviço realmente recebeu, após cada ficheiro .env, bloco environment: e variável de shell terem sido mesclados. Quando um valor está incorreto, a ordem de mesclagem é geralmente o motivo, e como o Compose resolve ficheiros env e segredos detalha qual fonte prevalece.

Redes, portas e resolução de nomes

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

Por padrão, o Compose coloca cada serviço numa rede de projeto, e cada nome de serviço é um nome DNS nessa rede. Executar getent hosts db dentro de web, quando a imagem inclui getent, verifica a resolução de nomes; isso não testa se o db aceita conexões. Se o nome for resolvido mas a conexão for recusada, verifique se o servidor está em execução e a escutar no endereço e porta solicitados; vincular apenas a 127.0.0.1 é uma causa possível. O mesmo limite explica por que um contentor iniciado fora do projeto, seja pelo docker run ou como a sua própria stack, precisa de uma rede partilhada para resolver um nome de serviço como jellyfin, que é a primeira coisa a verificar quando um front end Halcyon para a sua biblioteca Jellyfin não consegue alcançar o servidor para o qual aponta. O restante desse modelo está em como funcionam as redes do Compose e o DNS de serviço.

O port web 80 imprime o endereço do host e a porta na qual a porta de um contentor está publicada, o que evita suposições quando o mapeamento vem de uma variável. Publicar uma porta também escreve uma regra de firewall que o Docker gere por conta própria, e essa regra fica à frente das suas, portanto, um serviço que você acreditava ser privado pode estar aberto à internet. Esse caso é abordado em por que as portas publicadas do Docker ignoram o ufw. Deixar essas portas não publicadas e colocar um proxy de autenticação na rede do projeto à frente dos serviços é a configuração mais segura, que é o que executar o Authentik como uma camada de início de sessão único lhe 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 é apenas parte de um inventário de backup: bind mounts e ficheiros de configuração também precisam de verificação. Quando os volumes contêm dados insubstituíveis, o comando de backup exato é tão importante quanto a lista, e é por isso que a comparação entre PhotoPrism e Immich detalha os comandos de dump e cópia que cada servidor de fotos necessita. cp copia um ficheiro para dentro ou para fora de um contentor sem abrir uma shell, utilizando o formato service:path no lado que for o contentor.

down -v remove volumes nomeados declarados, exceto os externos, além de volumes anónimos ligados aos contentores, juntamente com os próprios contentores. É o comando correto para destruir uma stack de teste e o comando errado para qualquer coisa que contenha dados importantes, pois não há confirmação nem possibilidade de desfazer a ação. Os bind mounts sobrevivem a este comando, uma vez que residem no sistema de ficheiros do host. Essa diferença no raio de impacto é uma das razões para escolher deliberadamente entre bind mounts e volumes nomeados.

Limpeza que libera disco sem perder dados

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

--remove-orphans remove containers que pertencem ao projeto, mas que não aparecem mais no arquivo, o que é exatamente o que ocorre após renomear um serviço. Sem isso, esses containers continuam em execução, e docker compose ps inclui órfãos em execução por padrão.

docker system df mostra para onde o espaço em disco foi antes de excluir qualquer coisa, separando imagens, containers, volumes locais e cache de build com um valor recuperável para cada um. image prune -a remove todas as imagens que nenhum container utiliza, marcadas ou não, e em uma máquina que baixou várias versões de uma imagem grande, esse costuma ser o maior ganho. builder prune remove cache de build órfão por padrão; adicione -a para remover todo o cache de build não utilizado.

Nenhum desses comandos afeta volumes nomeados. docker volume prune --all, docker compose down -v e docker volume rm removem volumes nomeados. O comando docker volume prune simples remove apenas volumes anônimos.

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.

Trabalhando com múltiplos 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

Múltiplas flags -f são combinadas por ordem, e os ficheiros posteriores substituem os anteriores chave a chave. Esta é a forma padrão de manter um ficheiro base com uma pequena sobreposição de produção, embora as regras difiram para listas e mapas; por isso, leia como o Compose combina múltiplos ficheiros antes de depurar um comportamento inesperado.

A flag --profile inicia serviços marcados com esse perfil juntamente com os que não possuem marcação, o que mantém ferramentas de depuração fora de um up normal. A flag -p define o nome do projeto, permitindo que duas cópias da mesma stack corram lado a lado com redes e nomes de volumes separados. Recuperar a stack após um reboot utiliza uma política de reinício ou uma unidade que executa o Compose automaticamente, conforme descrito em iniciando stacks do Compose no boot.

FAQ

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

O Compose V2 e V5, invocados como docker compose com um espaço. No Linux, o Compose é um plugin instalado separadamente; o Ubuntu 24.04 LTS ainda oferece a ferramenta Python V1 no seu repositório universe. Se a forma com espaço não estiver disponível, configure o repositório do Docker e instale o pacote docker-compose-plugin. Atualize scripts antigos para a forma com espaço em vez de adicionar um alias, pois a V2 possui flags que a V1 nunca teve.

Por que o docker compose restart não reconhece a minha alteração de configuração?

O restart para e inicia o contentor existente com a configuração com a qual foi criado, e nunca volta a ler o compose.yaml. Qualquer alteração em variáveis de ambiente, portas, volumes ou na tag da imagem requer o docker compose up -d, que compara cada serviço com o seu contentor em execução e recria aqueles que diferem. Adicione --force-recreate quando pretender que a substituição ocorra mesmo que nada no ficheiro tenha sido alterado.

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

Execute docker compose pull e, em seguida, docker compose up -d. O pull obtém a imagem atual para cada tag no ficheiro, e o up -d recria qualquer serviço cuja ID de imagem já não corresponda à do seu contentor. Executar o up -d isoladamente segue a política de pull: a política padrão missing reutiliza imagens em cache, exceto para a latest, que é sempre descarregada.

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

O docker system df reporta a utilização de disco sem eliminar nada; o docker image prune -a e o docker builder prune removem imagens não utilizadas e a cache de compilação, pelo que os serviços em execução continuam a funcionar e os volumes nomeados permanecem intactos. O par perigoso é o docker compose down -v, que elimina os volumes nomeados não externos declarados no projeto e volumes anónimos anexados sem pedir confirmação, e o docker volume prune --all, que elimina volumes locais não utilizados, incluindo os nomeados, após uma única confirmação y/N, ou sem qualquer confirmação com -f. Execute o docker compose config --volumes primeiro para saber o que está em risco.

Posso executar um comando sem iniciar toda a stack?

Sim. O docker compose run --rm --no-deps web sh inicia um único contentor a partir da definição de serviço web, ignora as suas dependências e remove o contentor quando termina. Utilize o exec em vez disso quando o contentor já estiver em execução, pois o exec executa o seu comando dentro do contentor ativo e mostra-lhe o estado em que o serviço se encontra realmente.

Este artigo foi útil?