implant docker-limits

Configura o daemon Docker (/etc/docker/daemon.json) com ulimits padrão para os containers — nofile 1048576 e nproc 65535, os mesmos valores do limits para o host — e ajustes de operação do daemon. Quando o daemon.json não configura log nenhum, inclui também o limite de tamanho dos logs dos containers.

Sem isso, cada container herda os limites padrão do daemon e pode estourar file descriptors sob carga. E, sem limite de log, o driver json-file deixa o log de cada container crescer sem teto até encher o disco.

O implant mexe só nas chaves que ele grava e guarda o valor que cada uma tinha antes; as demais opções do arquivo (registry mirrors, data-root, redes etc.) nunca são tocadas, e o revert devolve cada chave ao que era.

Uso

implant docker-limits [OPTIONS] <SUBCOMANDO>

Requer root. As opções do comando (--dry-run) vêm antes do subcomando:

sudo implant docker-limits --dry-run apply

Subcomandos

Subcomando Descrição
apply Acrescenta/atualiza as chaves do implant no daemon.json e reinicia o Docker se o arquivo mudou
revert Devolve cada chave do implant ao valor anterior e reinicia o Docker se o arquivo mudou
status Mostra se o Docker está instalado e se os ulimits estão configurados

Flags

Flag Descrição
--dry-run Simula sem aplicar mudanças: anuncia as escritas, não grava nem reinicia o Docker
-o, --output <FORMATO> human (padrão), json ou yaml
-v, --verbose Mostra os comandos executados
-c, --config <ARQUIVO> Arquivo de configuração (padrão /etc/protocolo-implant/config.toml)
-t, --token <TOKEN> Token de identificação do servidor (ou PROTOCOLO_TOKEN)

Antes de rodar

apply e revert reiniciam o Docker quando alteram o arquivo. Dois cuidados práticos:

  • O dockerd recusa chave desconhecida no daemon.json e não sobe. Desde a 2.55.1 o implant passa o conteúdo novo pelo dockerd --validate (Docker 23+) antes de gravar: se o dockerd recusar — por exemplo, uma chave sua com erro de digitação —, o comando para com o motivo dado pelo dockerd, nada é gravado e o Docker não é reiniciado. Docker sem --validate segue sem essa checagem (com aviso); nesse caso, confira o arquivo antes. Para validar à mão:

    sudo dockerd --validate --config-file /etc/docker/daemon.json
  • Sem live-restore, reiniciar o Docker para os containers. Veja as observações em "Opções gravadas" e o aviso em "Como reverter", abaixo.

O que é aplicado

Quando o `apply` age

  • Docker não instalado (docker fora do PATH): nada é feito.
  • daemon.json com JSON inválido (ou que não é um objeto): o comando termina com erro, o arquivo não é alterado e o Docker não é reiniciado. Corrija o arquivo e rode de novo.
  • Todas as chaves do implant já têm os valores do implant: nada é gravado e o Docker não é reiniciado.
  • Caso contrário, o implant registra os valores anteriores, grava o daemon.json e reinicia o Docker.

O merge é feito pelo próprio implant, sem depender de jq. Uma chave do implant que já existe com outro valor (um default-ulimits próprio, um live-restore: false) é substituída pelo valor do implant; o valor anterior fica registrado e volta no revert. O arquivo é regravado formatado, com indentação de 2 espaços e as chaves em ordem alfabética.

Chaves gravadas

Sempre:

  • default-ulimits (nofile e nproc)
  • live-restore: true
  • userland-proxy: false

Só quando o arquivo não tem log-driver nem log-opts:

  • log-driver: "json-file"
  • log-opts com max-size: "10m" e max-file: "3"

Se você já configurou o log do Docker (qualquer driver ou opção), ele fica como está.

Cenário 1 — `daemon.json` ausente ou sem nenhuma chave

O arquivo fica assim:

{
  "default-ulimits": {
    "nofile": {
      "Hard": 1048576,
      "Name": "nofile",
      "Soft": 1048576
    },
    "nproc": {
      "Hard": 65535,
      "Name": "nproc",
      "Soft": 65535
    }
  },
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": {
    "max-file": "3",
    "max-size": "10m"
  },
  "userland-proxy": false
}

Cenário 2 — `daemon.json` com outras opções, sem configuração de log

As suas chaves são preservadas e entram as cinco chaves acima, inclusive o limite de logs.

Cenário 3 — `daemon.json` com `log-driver` ou `log-opts`

As suas chaves são preservadas e entram só default-ulimits, live-restore e userland-proxy. A configuração de log é sua e não é alterada.

Registro dos valores anteriores

Antes de gravar o daemon.json, o apply grava /var/lib/implant/docker-limits.json com o que cada chave tinha antes (null quando não existia) e o que o implant gravou:

{
  "file_existed": true,
  "keys": {
    "live-restore": {
      "previous": false,
      "written": true
    },
    "userland-proxy": {
      "previous": null,
      "written": false
    }
  }
}

(Resumido: default-ulimits e, quando entram, as chaves de log aparecem da mesma forma.) Rodar o apply de novo não perde o valor original: o "anterior" registrado no primeiro apply prevalece. O revert apaga o registro.

Opções gravadas

Chave Valor Efeito
default-ulimits.nofile 1048576 File descriptors por container
default-ulimits.nproc 65535 Processos/threads por container
log-driver / log-opts json-file, 10 MB × 3 arquivos Teto de ~30 MB de log por container (só sem log configurado)
live-restore true Containers continuam rodando quando o daemon reinicia ou é atualizado
userland-proxy false Portas publicadas tratadas por regras do kernel em vez de um processo docker-proxy por porta

Observações:

  • O reinício do Docker no apply interrompe os containers se o daemon ainda não rodava com live-restore (a opção só passa a valer depois desse reinício); voltam sozinhos apenas os que têm política de restart. Planeje uma janela.
  • default-ulimits e log-opts valem para containers criados depois. Containers existentes precisam ser recriados (docker compose up -d --force-recreate, por exemplo). --ulimit e --log-opt definidos no próprio container têm precedência.

Status

Campo Significado
docker_installed docker encontrado no PATH
daemon_json_exists /etc/docker/daemon.json existe
ulimits_configured O arquivo contém default-ulimits
config_file Caminho do daemon.json

Relação com `check --auto-fix`

O check --auto-fix usa o mesmo merge quando o daemon.json ainda não tem default-ulimits — com as mesmas garantias: só as chaves do implant, valor anterior registrado e JSON inválido recusado sem tocar no arquivo.

À parte, o limite de logs é verificado: hosts com Docker cujo daemon.json não define max-size/max-file dentro do teto (até 100m e 10 arquivos) recebem log-opts com max-size: 10m, max-file: 3 e compress: true, mesclados ao arquivo existente. O docker-limits apply não faz essa verificação: só grava log quando o arquivo não tem nenhum.

Como reverter

sudo implant docker-limits revert

O revert olha cada chave registrada no apply:

Situação da chave O que o revert faz
Ainda tem o valor que o implant gravou Volta ao valor anterior; se ela não existia, é removida
Foi alterada depois do apply Fica como está, com o aviso <chave> mantida: alterada depois do apply
Foi removida depois do apply Nada

As demais chaves do arquivo não são tocadas. Se o arquivo ficar vazio e tiver sido criado pelo implant, ele é removido; se já existia antes do apply, fica como {}. O registro em /var/lib/implant/docker-limits.json é apagado, e o Docker só é reiniciado se o arquivo mudou.

Sem registro — apply feito por uma versão anterior à 2.55.0 — o revert remove apenas as chaves cujo valor é exatamente o que o implant grava (default-ulimits, live-restore: true, userland-proxy: false, log-driver: "json-file" e log-opts com 10m/3). Valores diferentes, mesmo nessas chaves, ficam.

Atenção — live-restore: se a chave tem o valor do implant e não existia antes do apply, o revert a remove (se antes era false, volta a false). A partir do próximo restart do Docker, os containers são parados junto com o daemon, e só voltam sozinhos os que têm política de restart adequada (always, unless-stopped). Confira as políticas antes de reverter, ou mantenha live-restore: true por conta própria depois.

JSON inválido no daemon.json dá erro sem alterar nada. Com o Docker ausente, o revert não faz nada. implant reset --docker-limits faz a mesma reversão.

Esta configuração não faz parte do emergency-mode.

Exemplos

# Ver o estado
sudo implant docker-limits status

# Validar o daemon.json antes (Docker com --validate)
sudo dockerd --validate --config-file /etc/docker/daemon.json

# Simular e aplicar
sudo implant docker-limits --dry-run apply
sudo implant docker-limits apply

# Conferir o ulimit dentro de um container novo
docker run --rm alpine sh -c 'ulimit -n'

# Ver os valores anteriores registrados pelo apply
sudo cat /var/lib/implant/docker-limits.json

# Políticas de restart dos containers (antes de um revert)
docker inspect -f '{{.Name}} {{.HostConfig.RestartPolicy.Name}}' $(docker ps -q)

Saída JSON do status (resumida):

{
  "success": true,
  "command": "docker-limits",
  "data": {
    "action": "status",
    "target": "docker-limits",
    "result": "completed",
    "dry_run": false,
    "state": {
      "docker_installed": true,
      "daemon_json_exists": true,
      "ulimits_configured": true,
      "config_file": "/etc/docker/daemon.json"
    }
  }
}

Veja também

  • limits — os mesmos limites para o host
  • logrotate — rotação dos logs do sistema
  • check — aplica ulimits e limite de logs do Docker no --auto-fix
  • reset — --docker-limits