Como posso reiniciar automaticamente os contêineres do Docker com a exclusão automática do contêiner?

4

Eu tenho um VPS de uso geral e estou Dockerizando os aplicativos nele. Haverá cerca de 5-6 contêineres, e muito pouco mais, então a caixa pode ser reconstruída trivialmente, conforme necessário.

Para cada aplicativo, tenho um script de início. Um contêiner do WordPress tem esta aparência:

#!/bin/bash

# Get the host IP address
export DOCKER_HOSTIP='ifconfig docker0 | grep "inet addr" | cut -d ':' -f 2 | cut -d ' ' -f 1'
echo "Connecting to database on Docker host ${DOCKER_HOSTIP}"

docker run \
    --add-host=docker:${DOCKER_HOSTIP} \
    --network dockernet \
    --network-alias jonblog \
    --detach \
    --restart always \
    --rm \
    jonblog

No entanto, isso retorna um erro:

Conflicting options: --restart and --rm

Existem vários tickets do Docker que dizem que isso é sensato, mas eu não entendo isso. Acho que meu significado é claro: se um contêiner não estiver em exibição (por exemplo, na inicialização), quero iniciá-lo. Se ele morrer, espero que o contêiner seja removido e um novo novo seja criado a partir da imagem base. Os contêineres devem ser imutáveis de qualquer maneira - qualquer estado que eu queira preservar, como arquivos de mídia e logs, será gravado em volumes.

Então, achei que deveria descartar o sinalizador --restart e usar um gerenciador de processos para parar e iniciar contêineres do Docker. Eu poderia usar o Monit aqui? Eu esperava poder fazer algo como:

CHECK PROCESS jonblog MATCHING jonblog
  START PROGRAM = "/root/docker/jonblog/host-start.sh"
  STOP PROGRAM = "docker stop jon-blog"

No entanto, isso verifica a tabela de processos do sistema, e não docker ps , e, portanto, não encontrará algo correspondente à string especificada. Posso obtê-lo para exec docker ps periodicamente e combinar linhas na saída?

Eu ficaria feliz em usar outra ferramenta se ela se mostrar robusta. Por exemplo, acho que o Supervisor é um pouco pesado, mas se for mais capaz de trabalhar com o Docker, estou disposto a usá-lo.

Esclarecimento em --rm

O motivo pelo qual eu quero --rm é que, durante o processo de Dockerization, eu pare o contêiner atualmente em execução, load uma nova versão da imagem e execute novamente o script acima. Isso significa que o Docker está sendo notificado de uma política restart para cada contêiner. Descobri que depois de reiniciar a caixa, eu teria 15 ou mais versões ligeiramente diferentes do aplicativo em execução simultaneamente, o que não é a intenção.

Suponho que eu poderia usar docker update --restart never em contêineres antigos para evitar que isso acontecesse, mas quando meu contêiner é interrompido, fico com ele por aí, e eu teria que excluir automaticamente. Eu poderia limpar periodicamente os antigos usando algum tipo de cron job, mas isso parece um pouco hacky, já que o Docker pode fazer isso por mim.

Buscando uma gama de respostas

Um comentário muito útil sugeriu que eu deveria olhar para o Minikube, que aparentemente simplifica a configuração do Kubernetes, até o grau em que um indivíduo devidamente qualificado possa estar pronto em cinco minutos.

Eu ainda gostaria de ver soluções mais leves propostas, por isso tenho várias opções para escolher. Como indicado, gostaria de descobrir a resposta para saber se um supervisor de processo como o Monit funcionaria.

Fora do topo da minha cabeça, eu poderia escrever um loop de shell para escrever docker ps em um arquivo a cada cinco segundos por um minuto, e depois executá-lo em um Cron a cada minuto. Eu poderia, então, verificar esse arquivo usando grep e a verificação do sistema Monit CHECK PROGRAM . Isso é um pouco hacky, mas é algo que eu posso entender facilmente se houver um problema com isso. Quaisquer avanços nessa sugestão?

    
por halfer 04.04.2018 / 17:17

1 resposta

0

Eu tenho uma resposta adequada para meu entendimento atual do Docker. Fui aconselhado nos comentários a experimentar o Minikube e, embora, sem dúvida, isso possa ser resolvido rapidamente, temi que isso fosse uma lição de aprendizado que me deixaria preso no tar durante semanas. Um dos meus princípios de engenharia é saber quando alguém atingiu um limite cognitivo para encher novas informações!

Assim, resolvi resolver esse problema de maneira simples. Eu tinha duas escolhas:

  1. Use o recurso de exclusão automática do contêiner no Docker e configure meu próprio sistema de reinicialização
  2. Use a política de reinicialização do Docker e configure meu próprio sistema de exclusão de contêiner

Comecei no primeiro deles, com a ideia de que o supervisor de processos Monit seria bom de usar, em parte porque é leve, e em parte porque eu estou familiarizado com isso. No entanto, ele começou a parecer a solução errada, já que eu estaria trabalhando em torno do problema principal que não é possível obter uma lista de processos contêineres do Docker.

Na verdade, a segunda opção foi muito mais limpa, e isso foi amplificado pelo fato de que a limpeza do contêiner parado não é realmente uma prioridade - é apenas para manter as coisas arrumadas. Claro, eu usei o Docker para isso; aqui está o Dockerfile :

# Docker build script for Docker Tidy

FROM alpine:3.6

RUN apk update
RUN apk add docker

# See this for BusyBox cron schedules
# https://gist.github.com/andyshinn/3ae01fa13cb64c9d36e7
COPY bin/docker-tidy.sh /etc/periodic/daily/
RUN chmod +x /etc/periodic/daily/docker-tidy.sh

# Start Cron in the foreground
ENTRYPOINT ["crond", "-l", "2", "-f"]

E aqui está o bin/docker-tidy.sh :

#!/bin/sh
#
# With thanks to:
# http://www.doublecloud.org/2015/05/simple-script-to-list-and-remove-all-stopped-docker-containers/

docker rm -v $(docker ps -a -q -f status=exited)

Por fim, uma desvantagem da minha solução é que, se o host for reinicializado antes de uma limpeza do contêiner parado, esses contêineres também parecem reiniciar. Por isso, redefino a política de reinicialização nesses contêineres antes de iniciar novos contêineres.

Por exemplo, aqui está como inicio o próprio contêiner do Docker Tidy, no host. Na prática, eu arrumei o código de mudança de política em seu próprio script, mas isso dará uma ideia geral:

#!/bin/bash

# Removes the restart policy from previous containers
CONTAINER_LABEL=docker-tidy-instance
docker ps --all --filter label=$CONTAINER_LABEL --quiet | xargs --no-run-if-empty docker update --restart no

docker run \
    --label $CONTAINER_LABEL \
    --volume /var/run/docker.sock:/var/run/docker.sock \
    --detach \
    --restart always \
    docker-tidy
    
por 11.04.2018 / 15:05

Tags