SSD Nodes Learn 8GB de RAM — $66/ano
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-02

Como iniciar o Docker Compose automaticamente no boot

Faça os serviços do Docker Compose voltarem após o reboot: use restart: unless-stopped, entenda por que on-failure não persiste e quando usar systemd.

A resposta curta

Os serviços do Docker Compose iniciam na inicialização quando duas condições são atendidas ao mesmo tempo. O daemon do Docker precisa estar habilitado como serviço do sistema, e cada serviço no arquivo precisa ter uma política de reinicialização unless-stopped ou always. Adicione restart: unless-stopped a cada serviço, execute docker compose up -d uma vez, e os contêineres voltarão a iniciar sozinhos após uma reinicialização. Nada mais é necessário no caso comum.

Você precisa de uma unidade do systemd somente quando a ordem é importante: por exemplo, uma stack que depende de um disco montado, de uma interface VPN ou de um compartilhamento de rede que ainda não esteja pronto quando o daemon do Docker iniciar. Esse caso é real, e a segunda metade deste guia o aborda. Se ainda estiver se familiarizando com definições de serviços e volumes, comece por os conceitos básicos do Docker Compose em um VPS e depois volte.

Defina a política de reinicialização em compose.yaml

A política é definida uma vez para cada serviço. Não há uma opção global. Portanto, um serviço que você esquecer permanecerá parado após a reinicialização, enquanto o restante da stack será iniciado.

services:
  app:
    image: nginx:1.27
    restart: unless-stopped
    ports:
      - "8080:80"
  db:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: change-me
    volumes:
      - dbdata:/var/lib/postgresql/data

volumes:
  dbdata:

Aplique a alteração e leia a política do container em execução:

docker compose up -d
docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' $(docker compose ps -q app)

Isso exibe unless-stopped. Se exibir no, o arquivo foi editado, mas o container nunca foi recriado.

Essa é a falha mais comum. A política de reinicialização é armazenada no container, não no arquivo YAML. Editar compose.yaml não altera um container que já existe. docker compose restart também não resolve, porque para e inicia o mesmo objeto de container sem alterar a configuração. Somente docker compose up -d compara o arquivo com os containers em execução, detecta que a política foi alterada e recria os containers.

Para um container que você não quer recriar agora, altere a política diretamente:

docker update --restart unless-stopped my-container

Edite também o arquivo YAML. docker update altera o container em execução, e o próximo docker compose up -d lerá o arquivo e restaurará o valor anterior.

O que cada valor de reinicialização realmente faz

O Docker define quatro valores, e a diferença entre eles só aparece quando a máquina é reinicializada ou o daemon é reiniciado.

  • no é o padrão. O contêiner nunca é reiniciado automaticamente, em nenhuma circunstância.
  • always reinicia o contêiner sempre que ele é interrompido. Se você o interromper manualmente, ele voltará a ser executado na próxima inicialização do daemon do Docker. Isso costuma ser inesperado: um contêiner que você interrompeu deliberadamente na semana passada volta a ser executado após uma reinicialização.
  • unless-stopped funciona como always, exceto que um contêiner interrompido manualmente permanece parado após a reinicialização do daemon. Esse é o valor adequado para um serviço que você interrompe ocasionalmente durante a manutenção.
  • on-failure reinicia o contêiner somente quando ele termina com um código de saída diferente de zero. Você pode limitar as tentativas, como em restart: on-failure:3.

Para uma stack que deve simplesmente estar em execução sempre que o servidor estiver ativo, unless-stopped é o padrão correto. Escolha always somente quando quiser um contêiner que não permaneça parado por muito tempo.

Por que restart: on-failure não sobrevive a uma reinicialização

Muitas pessoas escolhem on-failure porque parece uma opção cuidadosa, mas depois encontram todos os contêineres parados após a primeira reinicialização. O motivo está na definição. on-failure reage a uma única situação: o processo do contêiner termina com um código de erro.

Uma reinicialização não é um erro. Quando o host é desligado, o systemd interrompe docker.service, e o daemon para cada contêiner deliberadamente. O contêiner não falhou, portanto a política não tem nada a que reagir. Durante a inicialização seguinte, o daemon verifica os contêineres que precisa retomar, e um contêiner on-failure que foi parado normalmente não está entre eles. Ele permanece no estado exited.

Você pode verificar isso diretamente. Defina restart: on-failure em um serviço, execute docker compose up -d, reinicie o sistema e execute:

docker compose ps -a

O serviço será listado com um estado Exited e um status semelhante a Exited (0) 2 minutes ago. Nada está quebrado e nada é registrado como erro, o que dificulta o diagnóstico. A política fez exatamente o que especifica.

on-failure ainda é útil. Ela se aplica a um contêiner que executa um job e pode falhar, quando você quer um número limitado de tentativas e nenhum loop de reinicialização. Ela é a ferramenta errada para manter um serviço de execução contínua ativo após reinicializações.

As políticas de reinicialização só funcionam se o serviço Docker iniciar na inicialização do sistema

As políticas de reinicialização são aplicadas pelo daemon do Docker. Se o daemon não iniciar, nada aplicará essas políticas. Verifique:

systemctl is-enabled docker
systemctl is-enabled containerd

Ambos devem exibir enabled. Os pacotes do repositório oficial do Docker habilitam essas unidades durante a instalação. Portanto, em um servidor novo, essa verificação normalmente passa. Se algum deles exibir disabled, corrija:

sudo systemctl enable --now docker containerd

Há uma armadilha que vale a pena entender. O Ubuntu também fornece docker.socket, que inicia o daemon sob demanda na primeira vez que algo se comunica com a API do Docker. As pessoas veem docker.socket habilitado, presumem que o daemon está coberto e desabilitam docker.service para economizar memória. Na inicialização do sistema, nada chama a API. Portanto, o socket nunca é acessado, o daemon nunca inicia e nenhum container é iniciado até que você digite o primeiro comando docker. A ativação por socket não substitui a habilitação de docker.service.

Quando uma unidade do systemd é a melhor opção

As políticas de reinicialização não têm nenhum conceito de ordenação em relação ao restante do sistema. O daemon é iniciado e sobe seus containers assim que pode. Se sua stack usa bind mount de um diretório em um volume separado, em um compartilhamento NFS (sistema de arquivos de rede) ou em um disco criptografado, os containers podem ser iniciados antes que esse caminho exista. O Docker cria automaticamente um diretório vazio no ponto de montagem e inicia o container usando esse diretório, e seu banco de dados é iniciado sem dados.

Escreva uma unidade do systemd quando qualquer uma destas condições se aplicar. A stack precisa que uma montagem, uma interface VPN ou outra unidade esteja pronta primeiro. Você quer que systemctl stop myapp e systemctl start myapp funcionem como funcionam para todos os outros serviços do servidor. Ou quer que a stack seja encerrada corretamente durante o desligamento, em vez de ser finalizada junto com o daemon. Se as unidades do systemd forem novas para você, como escrever um serviço e um timer do systemd explica o formato do arquivo em mais detalhes.

Escrevendo a unidade systemd

Coloque a stack em um caminho fixo fora de um diretório pessoal. /srv/myapp é uma boa escolha, porque uma unidade executada antes de qualquer login não deve ler /home.

Crie /etc/systemd/system/myapp.service:

[Unit]
Description=myapp docker compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
RequiresMountsFor=/srv/myapp/data

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/srv/myapp
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target

Habilite e inicie a unidade:

sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
systemctl status myapp.service

Uma unidade saudável mostra Active: active (exited). Isso parece errado na primeira vez que você vê. Está correto: Type=oneshot com RemainAfterExit=yes significa que a unidade executou o comando, o comando terminou e o systemd mantém a unidade marcada como ativa para que ExecStop seja executado no desligamento.

Cada linha tem uma função. Requires=docker.service faz a unidade falhar rapidamente, em vez de executar docker compose em um socket inativo. After= define a ordem, porque Requires= sozinho não faz isso. RequiresMountsFor= faz o systemd incluir a unidade de montagem desse caminho e aguardar por ela. Esse é o motivo principal para usar uma unidade em vez de uma política de reinicialização. TimeoutStartSec=0 impede que o systemd encerre o job de inicialização enquanto uma imagem grande ainda está sendo baixada.

Uma observação sobre a combinação dos dois mecanismos. A documentação do Docker recomenda não combinar políticas de reinicialização com um gerenciador de processos do host. Esse aviso se refere a um gerenciador de processos que supervisiona diretamente o processo do container e o reinicia enquanto o daemon tenta fazer o mesmo. Uma unidade Type=oneshot não supervisiona nada. Portanto, manter restart: unless-stopped no arquivo compose junto com esta unidade é correto e é o que você precisa. O systemd gerencia a ordem durante a inicialização, e o daemon gerencia um container que falha às três da manhã.

Verifique com uma reinicialização real

Não há substituto para o teste real. systemctl restart docker não testa a ordem de montagem, e docker compose down seguido por docker compose up -d não testa nada relacionado à inicialização.

sudo reboot

Aguarde, reconecte-se e verifique nesta ordem:

uptime
systemctl is-active docker
docker compose ps

uptime confirma que você está em uma máquina que realmente foi reinicializada. docker compose ps, executado no diretório da stack, deve listar todos os serviços como running, com um uptime próximo ao da máquina. O serviço que aparecer como Exited é o que deve ser analisado.

Se algo não foi iniciado, o log do daemon cobre o período da inicialização:

journalctl -u docker.service -b --no-pager | tail -50

Para uma stack gerenciada por uma unit, journalctl -u myapp.service -b --no-pager mostra a saída exata de docker compose desde a inicialização, incluindo uma falha ao baixar uma imagem ou a ausência de um arquivo .env.

O que interrompe silenciosamente a inicialização automática

Os containers criados com docker compose run nunca recebem a política de reinicialização definida no arquivo. O Compose trata esses containers como containers avulsos. Se um serviço parece ignorar sua política, verifique se ele foi iniciado com run em vez de up.

Um caminho relativo em um volume ou em uma entrada env_file é resolvido em relação ao diretório do arquivo de compose. Isso funciona no seu shell e também funciona em uma unit que define WorkingDirectory. Falha em uma unit sem essa definição, porque o diretório de trabalho passa a ser /.

O Docker rootless é um caso separado. O daemon é executado como um serviço do usuário, e um serviço do usuário é interrompido quando termina a última sessão desse usuário. Habilite-o para o usuário e permita que continue em execução sem nenhum usuário conectado:

systemctl --user enable docker
sudo loginctl enable-linger $USER

Sem enable-linger, o daemon rootless é encerrado quando você termina a sessão, e os containers também são interrompidos. Isso parece exatamente uma política de reinicialização com problema.

Mais uma coisa. As atualizações automáticas de segurança podem reiniciar um servidor em um horário fixo. Isso só é positivo se sua stack voltar a funcionar sozinha. Configurar isso em uma máquina nova faz parte do restante do trabalho da primeira hora em os primeiros dez minutos em um novo VPS.

FAQ

Qual é a diferença entre restart: always e restart: unless-stopped?

Ambos reiniciam o container quando ele para sozinho. A diferença ocorre depois que você para um container manualmente. Com always, o container é iniciado novamente na próxima inicialização do daemon do Docker, portanto uma reinicialização desfaz a parada manual. Com unless-stopped, o daemon lembra que o container foi parado deliberadamente e o mantém parado. Use unless-stopped, a menos que você queira especificamente um container que permaneça parado.

Adicionei restart: unless-stopped, mas o container ainda não inicia após uma reinicialização. Por quê?

A política fica no container, não no arquivo, e editar o YAML não atualiza um container que já existe. Execute docker compose up -d para que o Compose o recrie e confirme com docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' $(docker compose ps -q app). Se isso exibir no, o container foi criado antes da sua edição. A outra causa comum é docker.service não estar habilitado, o que você pode verificar com systemctl is-enabled docker.

Preciso de uma unidade do systemd se já uso políticas de reinicialização?

Geralmente, não. Uma política de reinicialização é suficiente para uma stack que depende apenas da rede, o que se aplica à maioria das stacks. Adicione uma unidade quando os containers dependerem de algo que não esteja pronto quando o daemon do Docker iniciar, como um disco externo, um volume criptografado, um compartilhamento NFS ou uma interface VPN. A unidade permite definir a ordem por meio de After= e RequiresMountsFor=, algo que uma política de reinicialização não consegue expressar.

Como paro uma stack permanentemente sem que ela volte na próxima reinicialização?

Com unless-stopped, docker compose stop é suficiente, porque um container parado manualmente não é retomado quando o daemon reinicia. Com always, parar o container não é suficiente, e ele volta após uma reinicialização. Execute docker compose down, que remove os containers, ou altere primeiro a política com docker update --restart no my-container. Se uma unidade do systemd gerenciar a stack, execute sudo systemctl disable myapp.service também; caso contrário, a unidade a iniciará novamente.