Execute o Docker Compose como um Serviço Linux com systemd
Docker Compose no boot, gerenciado pelo systemd.
O Docker Compose em um servidor Linux deve iniciar na boot, parar limpaamente durante o desligamento e sobreviver a reinicializações sem intervenção manual.
Docker Compose não é Kubernetes, e isso é aceitável para as cargas de trabalho que este guia aborda. Para muitos sistemas reais, um projeto Compose em um único host Linux é a quantidade certa de infraestrutura: simples, legível, fácil de fazer backup e suficiente para ferramentas internas, projetos paralelos, serviços auto-hospedados, ambientes de staging, pequenos aplicativos de produção e infraestrutura de desenvolvedores.

A peça que geralmente falta é o gerenciamento de serviços. Executar isso manualmente não é suficiente:
docker compose up -d
Um único comando inicia a stack, mas não documenta como a stack deve iniciar na boot, parar durante o desligamento, recarregar após mudanças, escrever logs, se recuperar de falhas ou ser atualizada com segurança. É aí que o systemd ajuda.
Este guia percorre a execução de um projeto Docker Compose como um serviço Linux com o systemd — arquivos de unidade, ordem de boot, atualizações, logs e backups. A divisão de responsabilidade é intencional: o Docker executa os containers, o Compose define a stack e o systemd inicia e para o projeto no host. Faz parte de Ferramentas de Desenvolvedor - Um Guia para Fluxos de Trabalho de Desenvolvimento.
Quando Faz Sentido Usar Docker Compose como Serviço
Executar o Compose sob o systemd faz sentido quando você tem:
- Um servidor Linux único
- Um pequeno aplicativo auto-hospedado
- Uma stack de proxy reverso
- Uma stack de monitoramento
- Uma plataforma de desenvolvimento local
- Uma ferramenta interna
- Um ambiente de staging
- Um serviço de produção simples com limites conhecidos
Exemplos:
- Nginx Proxy Manager
- Traefik
- Gitea
- Grafana e Prometheus
- PostgreSQL mais um pequeno aplicativo web
- Uptime Kuma
- Serviços auxiliares do Home Assistant
- Registro privado
- API interna mais worker mais Redis
O Compose é uma boa opção quando o modelo operacional ainda é compreensível por uma pessoa lendo um único diretório.
Quando o Docker Compose Não é Suficiente
Use outra coisa quando você precisar de:
- Agendamento em múltiplos nós
- Reagendamento automático entre hosts
- Descoberta de serviços em nível de cluster
- Escala horizontal automática
- Implantações rolling em muitas máquinas
- Identidade de carga de trabalho granular
- Política de rede complexa
- Operações de plataforma multi-times em larga escala
Nesse ponto, Kubernetes, Nomad, Swarm ou uma plataforma gerenciada podem ser uma melhor opção.
Minha regra prática é evitar usar Kubernetes apenas para não precisar aprender systemd, e evitar usar Compose quando a carga de trabalho claramente precisa de orquestração em múltiplos hosts.
A Arquitetura Básica
Uma configuração limpa separa os arquivos do projeto, a unidade systemd e os dados persistentes no host. O projeto Compose fica em /opt/myapp/ com compose.yaml, .env, data/, backups/ e scripts opcionais como scripts/update.sh. O arquivo de unidade systemd fica em /etc/systemd/system/myapp.service.
Cada camada tem uma tarefa clara: o Docker executa os containers, o Compose define a stack de aplicativos, o systemd inicia e para o projeto Compose na boot e no desligamento, o sistema de arquivos do host armazena dados persistentes, os backups permanecem explícitos e as atualizações passam por etapas scriptadas e revisáveis. Este layout é deliberadamente entediante, porque infraestrutura entediante é mais fácil de consertar quando algo quebra às 2 da manhã.
Preparar o Diretório do Projeto Compose
Crie um diretório em /opt:
sudo mkdir -p /opt/myapp
sudo chown -R "$USER":"$USER" /opt/myapp
cd /opt/myapp
Crie um arquivo Compose:
nano compose.yaml
Exemplo:
services:
web:
image: nginx:stable
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
healthcheck:
test: ["CMD-SHELL", "nginx -t || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes: {}
Crie o diretório de conteúdo:
mkdir -p html
echo "Hello from Docker Compose" > html/index.html
Teste manualmente primeiro:
docker compose up -d
docker compose ps
docker compose logs --tail=50
Em seguida, pare-o antes de entregar o ciclo de vida ao systemd:
docker compose down
Não crie um serviço systemd até que o projeto Compose funcione manualmente. Enquanto você testa, mantenha o Cheat Sheet do Docker Compose por perto para ps, logs, pull e estrutura do projeto.
Usar o Comando Moderno docker compose
O Docker Engine e o plugin Compose devem estar instalados antes que você escreva um arquivo de unidade. No Ubuntu, Instalar Docker no Ubuntu percorre APT, Snap, modo rootless e segurança pós-instalação para que você termine com um comando docker compose funcional.
Use isto:
docker compose version
Não isto:
docker-compose version
O antigo binário docker-compose ainda existe em muitas máquinas, mas o Docker moderno usa o Compose como um plugin do Docker CLI.
Em arquivos de serviço e scripts, prefira:
/usr/bin/docker compose
Você pode encontrar o caminho do Docker com:
command -v docker
Geralmente é:
/usr/bin/docker
Criar um Serviço systemd para Docker Compose
Se arquivos de unidade são novos para você, Executar qualquer Executável como Serviço no Linux explica Type, ExecStart, systemctl e o fluxo de trabalho geral do systemd. Esta seção aplica esses padrões especificamente a uma stack Compose.
Crie o arquivo de serviço:
sudo nano /etc/systemd/system/myapp.service
Use esta unidade:
[Unit]
Description=MyApp Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Recarregue o systemd:
sudo systemctl daemon-reload
Inicie o serviço:
sudo systemctl start myapp.service
Ative-o na boot:
sudo systemctl enable myapp.service
Verifique o status:
systemctl status myapp.service
Verifique os containers:
cd /opt/myapp
docker compose ps
Por que Type=oneshot e RemainAfterExit=yes?
Esta é a parte que muitos guias erram sutilmente.
docker compose up -d inicia os containers em modo detached e sai, então não há um processo Compose em primeiro plano de longa execução para o systemd supervisionar. A unidade systemd não deve fingir que docker compose up -d é um daemon de longa execução.
Use:
Type=oneshot
RemainAfterExit=yes
Isto diz ao systemd:
- Execute o comando de início.
- Considere a unidade ativa após o comando sair com sucesso.
- Execute
ExecStopquando o serviço for parado.
Isso corresponde ao comportamento real do Compose detached, é por isso que Type=oneshot com RemainAfterExit=yes é o padrão correto para a maioria das stacks.
Por que não Type=simple?
Com Type=simple, o systemd espera que o processo ExecStart continue rodando, mas docker compose up -d sai após iniciar os containers. Isso pode fazer o systemd achar que o serviço terminou, então chamar a lógica de parada ou marcar a unidade como inativa dependendo da configuração.
Se você quiser Type=simple, você geralmente executaria o Compose em primeiro plano:
ExecStart=/usr/bin/docker compose up
Isso pode funcionar, mas geralmente não prefiro isso para stacks Compose em servidores. Containers detached mais ExecStop explícito são mais fáceis de operar.
Uma Unidade Mais Amigável para Produção
Para um servidor real, prefiro uma unidade um pouco mais estrita:
[Unit]
Description=MyApp Docker Compose stack
Documentation=https://example.com/docs/myapp
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
EnvironmentFile=-/opt/myapp/.env.systemd
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Detalhes importantes:
WorkingDirectoryaponta para o projeto Compose.ExecStartPrevalida a configuração do Compose.ExecReloadrecria os serviços alterados.ExecStoppara e remove os containers do projeto Compose e a rede padrão.EnvironmentFile=-...significa que o arquivo é opcional.
Crie o arquivo de ambiente systemd opcional:
nano /opt/myapp/.env.systemd
Exemplo:
COMPOSE_PROJECT_NAME=myapp
Em seguida, recarregue o systemd:
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
Compose .env vs EnvironmentFile do systemd
Compose e systemd cada um tem seu próprio mecanismo de ambiente, e misturá-los causa falhas confusas de “variável não definida” na boot.
O Compose lê automaticamente um arquivo .env no diretório do projeto para substituição de variáveis no arquivo Compose.
Exemplo .env:
APP_TAG=1.2.3
WEB_PORT=8080
Exemplo compose.yaml:
services:
web:
image: nginx:${APP_TAG}
ports:
- "${WEB_PORT}:80"
Um EnvironmentFile do systemd define variáveis de ambiente para o próprio comando docker compose.
Exemplo:
EnvironmentFile=-/opt/myapp/.env.systemd
Para muitos projetos, você só precisa do .env do Compose.
Use um arquivo de ambiente systemd quando quiser definir coisas como:
COMPOSE_PROJECT_NAME=myapp
COMPOSE_FILE=compose.yaml
DOCKER_HOST=unix:///var/run/docker.sock
Não use nenhum dos arquivos como um cofre de segredos casual. Se segredos importam, use segredos do Docker, um gerenciador de segredos externo, arquivos criptografados ou, pelo menos, permissões estritas.
Defina permissões restritivas:
chmod 600 /opt/myapp/.env
chmod 600 /opt/myapp/.env.systemd
Políticas de Reinício: Docker vs systemd
Existem duas camadas de reinício — política de reinício do container no Compose e política de reinício do serviço systemd — e elas não devem ser misturadas cegamente.
Para containers de longa execução, defina políticas de reinício no Compose:
services:
web:
image: nginx:stable
restart: unless-stopped
Valores comuns de reinício:
| Política | Significado |
|---|---|
| no | Não reiniciar automaticamente |
| always | Reiniciar após saída e reinício do daemon |
| on-failure | Reiniciar apenas após falha |
| unless-stopped | Reiniciar a menos que seja parado manualmente |
Para a maioria dos serviços persistentes, prefiro:
restart: unless-stopped
É previsível e respeita paradas manuais intencionais.
A própria unidade systemd geralmente não deve reiniciar repetidamente, porque docker compose up -d não é a carga de trabalho em execução. Os containers são.
Então evite isto a menos que você tenha um motivo específico:
Restart=always
Na maioria das unidades Compose-como-serviço, deixe o Docker lidar com os reinícios dos containers.
Verificações de Saúde (Health Checks)
Políticas de reinício reiniciam containers quando processos saem. Elas não consertam magicamente todos os aplicativos não saudáveis.
Adicione verificações de saúde onde forem úteis:
services:
app:
image: example/app:latest
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:8080/health || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
Verifique a saúde:
docker compose ps
Inspecione um container:
docker inspect container-name
Verificações de saúde são especialmente úteis para:
- Aplicativos web
- Proxies reversos
- Bancos de dados
- Filas
- APIs internas
- Workers com um endpoint de saúde
Elas são menos úteis quando verificam apenas que um processo existe, porque um processo que está vivo mas travado ainda parece saudável. Uma verificação de saúde ruim é apenas outra mentira em YAML.
Ordem de Inicialização e depends_on
O Compose pode definir dependências:
services:
app:
image: example/app:latest
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
Isso pode ajudar na ordem de inicialização, mas não confie demais nisso. Os aplicativos ainda devem lidar com retries — bancos de dados reiniciam, redes falham, DNS leva tempo, e um aplicativo resiliente retry connections em vez de assumir uma ordem de inicialização perfeita.
Logs: journalctl e docker compose logs
Duas visualizações de logs cobrem a maioria das depurações: o systemd captura o ciclo de vida da unidade em si, enquanto o Compose captura a saída do aplicativo dos containers em execução.
Logs do serviço systemd:
journalctl -u myapp.service -n 100 --no-pager
Acompanhe logs do systemd:
journalctl -u myapp.service -f
Logs do serviço Compose:
cd /opt/myapp
docker compose logs --tail=100
docker compose logs -f
docker compose logs -f web
Para a maioria das depurações de aplicativos, docker compose logs é mais útil; para depuração de ciclo de vida — falhas de início, crashes de unidade, erros de permissão — journalctl é mais útil. Se systemctl start myapp falhar, verifique journalctl primeiro. Se a stack iniciar mas o aplicativo estiver quebrado, verifique docker compose logs.
Rotação de Logs
Logs do Docker podem crescer para sempre se você não configurá-los.
Para servidores pequenos, configure a rotação de logs do Docker em /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}
Reinicie o Docker:
sudo systemctl restart docker
Em seguida, reinicie a stack Compose:
sudo systemctl restart myapp.service
Isso se aplica a containers recém-criados. Recrie containers se necessário:
cd /opt/myapp
docker compose up -d --force-recreate
Rotação de logs não é glamorosa, mas é uma das maneiras mais fáceis de evitar uma interrupção de disco cheio em um servidor pequeno.
Atualizando um Serviço Compose
Um fluxo de atualização manual simples:
cd /opt/myapp
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
Se gerenciado pelo systemd, você pode usar:
sudo systemctl reload myapp.service
Se sua unidade tiver:
ExecReload=/usr/bin/docker compose up -d --remove-orphans
Mas note: ExecReload não puxa imagens a menos que você inclua essa etapa.
Para atualizações explícitas, crie um script.
mkdir -p /opt/myapp/scripts
nano /opt/myapp/scripts/update.sh
Script:
#!/usr/bin/env bash
set -euo pipefail
cd /opt/myapp
docker compose config --quiet
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
docker compose ps
Torne-o executável:
chmod +x /opt/myapp/scripts/update.sh
Execute-o:
/opt/myapp/scripts/update.sh
Então a unidade de serviço pode permanecer focada no ciclo de vida, enquanto o script de atualização lida com a implantação.
Script de Atualização Mais Seguro com Hook de Backup
Para serviços com estado, atualize apenas após backup.
#!/usr/bin/env bash
set -euo pipefail
APP_DIR="/opt/myapp"
BACKUP_DIR="/opt/myapp/backups"
cd "$APP_DIR"
mkdir -p "$BACKUP_DIR"
echo "Validando arquivo compose"
docker compose config --quiet
echo "Executando hook de backup"
if [ -x "$APP_DIR/scripts/backup.sh" ]; then
"$APP_DIR/scripts/backup.sh"
else
echo "Nenhum hook de backup encontrado"
fi
echo "Puxando imagens"
docker compose pull
echo "Recriando serviços"
docker compose up -d --remove-orphans
echo "Limpando imagens não utilizadas"
docker image prune -f
echo "Status atual"
docker compose ps
Isso ainda é simples, mas agora codifica um hábito operacional: backup antes da mudança.
Parando o Serviço
Pare a stack:
sudo systemctl stop myapp.service
Isso executa:
docker compose down
Por padrão, docker compose down remove:
- Containers para serviços no arquivo Compose
- Redes definidas pelo arquivo Compose
- A rede padrão
Ele não remove volumes nomeados a menos que você peça.
Não use casualmente:
docker compose down -v
Isso remove volumes nomeados declarados no arquivo Compose e volumes anônimos anexados aos containers. Para bancos de dados e aplicativos com estado, isso pode significar excluir dados reais.
Use down -v apenas quando você significa “destruir este ambiente”.
Reiniciando o Serviço
Reinicie a unidade systemd:
sudo systemctl restart myapp.service
Isso executa o comando de parada e então o comando de início.
Para apenas reiniciar containers sem recriá-los:
cd /opt/myapp
docker compose restart
Distinção importante:
docker compose restartreinicia containers existentes.docker compose up -daplica mudanças de configuração ou imagem recriando containers quando necessário.
Se você mudou compose.yaml, use:
docker compose up -d
Não apenas:
docker compose restart
Lidando com Containers Órfãos
Se você renomear ou remover um serviço em compose.yaml, containers antigos podem permanecer como órfãos.
Use:
docker compose up -d --remove-orphans
É por isso que os exemplos de serviço systemd neste guia usam:
ExecStart=/usr/bin/docker compose up -d --remove-orphans
Isso mantém a stack mais próxima do arquivo Compose atual.
Backups
Backups dependem da carga de trabalho, mas os princípios são estáveis.
Para bind mounts:
/opt/myapp/data/
Faça backup desse diretório.
Para volumes nomeados:
docker volume ls
Inspecione um volume:
docker volume inspect volume-name
Para bancos de dados, cópias de sistema de arquivos nem sempre são suficientes. Use backups conscientes do aplicativo:
Exemplo PostgreSQL:
docker compose exec -T db pg_dump -U postgres appdb > backups/appdb.sql
Exemplo MariaDB:
docker compose exec -T db mariadb-dump -u root -p appdb > backups/appdb.sql
Exemplo Redis:
docker compose exec redis redis-cli BGSAVE
Uma stack Compose sem um plano de backup não é um serviço — é um experimento temporário que acontece ter uptime.
Linha de Base de Segurança
Para um pequeno serviço Compose no Linux, comece com esta linha de base:
- Mantenha o projeto Compose em
/opt/appname. - Use tags de imagem explícitas, não apenas
latest, quando a estabilidade importa. - Use bind mounts ou volumes nomeados deliberadamente.
- Não exponha portas que você não precisa.
- Coloque serviços públicos atrás de um proxy reverso.
- Use HTTPS na borda.
- Mantenha segredos fora do Git.
- Restrinja permissões de
.env. - Evite containers privilegiados a menos que realmente necessário.
- Evite montar o socket do Docker em containers.
- Mantenha Docker e imagens atualizados.
- Teste o comportamento do firewall de outra máquina.
Um padrão perigoso:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Isso dá ao container controle sobre o Docker. Na prática, isso pode se tornar controle em nível de host. Use-o apenas quando você entende o risco.
Limites de Recursos
Em servidores pequenos, um container ruim pode consumir o host.
O Compose suporta configurações relacionadas a recursos, mas o comportamento pode depender da versão do Docker Engine e do Compose. Para proteção simples, comece com limites em nível de aplicativo e limites de log do Docker.
Para algumas cargas de trabalho, você pode adicionar limites de memória:
services:
app:
image: example/app:stable
restart: unless-stopped
mem_limit: 512m
Também configure contagens de workers em nível de aplicativo, limites de fila e tamanhos de cache. Limites de container são úteis, mas não são um substituto para entender o aplicativo.
Exemplo: Um Serviço Compose Realista
Diretório:
/opt/whoami/
compose.yaml
.env
Arquivo Compose:
services:
whoami:
image: traefik/whoami:v1.10
restart: unless-stopped
ports:
- "${WHOAMI_PORT}:80"
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost || exit 1"]
interval: 30s
timeout: 5s
retries: 3
Arquivo .env:
WHOAMI_PORT=8080
COMPOSE_PROJECT_NAME=whoami
Unidade systemd:
[Unit]
Description=Whoami Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/whoami
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Instale-o:
sudo systemctl daemon-reload
sudo systemctl enable --now whoami.service
Teste:
curl http://localhost:8080
Verifique o status:
systemctl status whoami.service
cd /opt/whoami
docker compose ps
Solução de Problemas
Serviço Inicia mas Containers Não Estão Rodando
Verifique o systemd:
journalctl -u myapp.service -n 100 --no-pager
Valide o Compose:
cd /opt/myapp
docker compose config
Verifique o Docker:
systemctl status docker
docker info
WorkingDirectory Está Errado
Se o systemd não conseguir encontrar seu arquivo Compose, confirme:
WorkingDirectory=/opt/myapp
Em seguida, verifique:
ls -la /opt/myapp
ls -la /opt/myapp/compose.yaml
O serviço roda a partir de WorkingDirectory, não do diretório atual do seu shell.
Permissão Negada do Docker
Se a unidade roda como root, ela normalmente pode acessar o Docker.
Se você definir User=algumusuario, esse usuário deve ser capaz de acessar o Docker. Geralmente isso significa membro do grupo docker, ou uma configuração Docker rootless.
Verifique:
groups algumusuario
Adicione o usuário se apropriado:
sudo usermod -aG docker algumusuario
Tenha cuidado. O grupo Docker é efetivamente privilegiado.
Comando Compose Não Encontrado
Encontre o Docker:
command -v docker
Use o caminho completo na unidade:
ExecStart=/usr/bin/docker compose up -d --remove-orphans
Se o plugin Compose estiver faltando:
docker compose version
Instale-o usando sua fonte de pacote Docker.
Variáveis de Ambiente Estão Faltando
Verifique a configuração do Compose como o systemd veria:
cd /opt/myapp
docker compose config
Se o systemd precisar de variáveis de ambiente extras, use:
EnvironmentFile=-/opt/myapp/.env.systemd
Se o Compose precisar de variáveis para substituição, use:
/opt/myapp/.env
Estes estão relacionados, mas não são idênticos.
Containers Não Iniciam Após Reinicialização
Verifique se o serviço systemd está habilitado:
systemctl is-enabled myapp.service
Habilite-o:
sudo systemctl enable myapp.service
Verifique o Docker:
systemctl is-enabled docker
systemctl status docker
Verifique logs de boot:
journalctl -u myapp.service -b --no-pager
Aplicativo Inicia Antes do Banco de Dados Estar Pronto
Adicione uma verificação de saúde do banco de dados e depends_on com service_healthy.
Também conserte o aplicativo. Ele deve fazer retry de conexões de banco de dados. A ordenação de início de infraestrutura é útil, mas a lógica de retry do aplicativo é melhor.
Disco Cheio com Logs do Docker
Verifique o uso de disco do Docker:
docker system df
Verifique logs grandes de containers:
sudo du -h /var/lib/docker/containers | sort -h | tail
Configure a rotação de logs do Docker em /etc/docker/daemon.json.
Em seguida, recrie os containers.
Erros Comuns
Erro 1: Executando docker compose up no rc.local
Executar docker compose up de rc.local ou um script de login funciona até que não funcione — use uma unidade systemd adequada em vez disso.
Erro 2: Usando Restart=always no systemd e restart: always no Compose
Geralmente você só precisa de políticas de reinício de container no Compose. Evite dois supervisores lutando entre si.
Erro 3: Esquecendo –remove-orphans
Renomeações e remoções de serviços podem deixar containers antigos para trás. Use:
docker compose up -d --remove-orphans
Erro 4: Usando docker compose restart Após Mudanças de Configuração
restart reinicia containers. Ele não aplica todas as mudanças de configuração.
Use:
docker compose up -d
Erro 5: Executando down -v Sem Pensar
Isso pode excluir volumes. Para serviços com estado, isso pode significar excluir dados.
Erro 6: Sem Backup Antes do Pull
Novas imagens podem quebrar. Bancos de dados podem migrar. Tags podem mover. Faça backup primeiro.
Erro 7: Publicando Toda Porta
Publique apenas o que o host precisa expor. Tráfego interno de serviço para serviço pode permanecer na rede Compose.
Padrão Recomendado Final
Para a maioria dos serviços Linux de host único, use este padrão:
Arquivo Compose:
services:
app:
image: example/app:stable
restart: unless-stopped
ports:
- "8080:8080"
env_file:
- .env
Unidade systemd:
[Unit]
Description=MyApp Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Habilite-o:
sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
Opere-o:
sudo systemctl status myapp.service
sudo systemctl restart myapp.service
journalctl -u myapp.service -f
cd /opt/myapp && docker compose logs -f
Este padrão não é sofisticado, e esse é o ponto. Docker Compose é excelente para sistemas pequenos e compreensíveis, systemd é excelente para iniciar e parar serviços de host, e juntos eles dão a você um modelo de implantação de servidor único confiável sem fingir que cada projeto precisa de um cluster. Para comandos em nível de container fora do Compose — imagens, volumes, redes e limpeza — veja o Cheat Sheet do Docker.