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

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

Para cada aplicativo, Tenho um script de início. Um contêiner WordPress se parece com isso:

#!/bin/bash# Get the host IP addressexport 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:

Opções conflitantes: -- restart e -- rm

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

Então, eu pensei que deveria largar o --restart sinalize e, em seguida, use um gerenciador de processos para interromper e iniciar contêineres do Docker. Posso 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 assim não encontrará algo que corresponda à 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 o Supervisor um pouco pesado, mas se isso for mais capaz de trabalhar com o Docker, estou disposto a usá-lo.

Esclarecimento sobre -- rm

A razão pela qual eu quero --rm é que durante o processo de Dockerização, paro 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 um restart política 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 aconteça, mas quando meu contêiner para, fico com ele por perto e logo o faço excluir automaticamente. Eu poderia limpar periodicamente os antigos usando algum tipo de trabalho cron, 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 examinar o Minikube, que aparentemente simplifica a configuração do Kubernetes, mesmo que um indivíduo adequadamente qualificado possa estar instalado e funcionando em cinco minutos.

Eu ainda gostaria de ver soluções mais leves propostas, então tenho uma série de respostas 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 para um arquivo a cada cinco segundos por um minuto e, em seguida, execute-o em um Cron a cada minuto. Eu poderia então verificar esse arquivo usando grep e o Monit CHECK PROGRAM verificação do sistema. Isso é um pouco hacky, mas é algo que eu posso entender facilmente se houver um problema com ele. Algum avanço nessa sugestão?

Tenho uma resposta adequada ao meu entendimento atual do Docker. Fui aconselhado nos comentários a experimentar o Minikube e, embora, sem dúvida, isso possa ser girado rapidamente, temi que fosse uma toca de coelho de aprendizado que me deixasse preso no alcatrão por semanas. Um dos meus princípios de engenharia é saber quando se atingiu um limite cognitivo para encher novas informações!

Assim, me propus a 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 processo Monit seria bom de usar, em parte porque é leve e em parte porque estou familiarizado com isso. No entanto, começou a parecer a solução errada, já que eu estaria trabalhando em torno do problema principal de que ele não pode obter uma lista de processos de contêiner do Docker.

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

# Docker build script for Docker TidyFROM alpine:3.6RUN apk updateRUN apk add docker# See this for BusyBox cron schedules# https://gist.github.com/andyshinn/3ae01fa13cb64c9d36e7COPY bin/docker-tidy.sh /etc/periodic/daily/RUN chmod +x /etc/periodic/daily/docker-tidy.sh# Start Cron in the foregroundENTRYPOINT ["crond", "-l", "2", "-f"]

E aqui está 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)

Finalmente, uma desvantagem da minha solução é que, se o host for reinicializado antes de uma limpeza de contêiner interrompida, esses contêineres também parecerão reiniciar. Portanto, redefino a Política de reinicialização nesses contêineres antes de iniciar novos.

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

#!/bin/bash# Removes the restart policy from previous containersCONTAINER_LABEL=docker-tidy-instancedocker ps --all --filter label=$CONTAINER_LABEL --quiet | xargs --no-run-if-empty docker update --restart nodocker run \    --label $CONTAINER_LABEL \    --volume /var/run/docker.sock:/var/run/docker.sock \    --detach \    --restart always \    docker-tidy

Vá jogar com Minikube você pode ter isso em cerca de cinco minutos.

É justo, @Michael. Posso fazer isso com Monit (com base em que estou um pouco familiarizado com isso)? Eu olhei para a página do Homem, mas isso é um monstro de uma leitura, e eu perdi a vontade de viver quando vadear através disso. Eu me pergunto, a partir dos documentos, se a verificação do programa funcionaria - se eu pudesse inserir um parâmetro no caminho executável, ele pode retornar sucesso / falha dependendo se o contêiner nomeado está em execução.

Provavelmente existe uma maneira mais orientada para o Docker de fazer isso, mas meu search-fu não está aparecendo nada particularmente interessante.

Honestamente, se você está reconstruindo contêineres com frequência, deve usar algo como o Kubernetes para gerenciar as coisas.

Você está certo @Michael, e eu vou me aprofundar nisso quando tiver tempo. Sou informado pelo Docker sub no Reddit que o Kube é um empreendimento (embora valioso). Vou procurar algo mais fácil por enquanto, que eu tenho uma chance de grokking.

(Um comentário aqui há cinco minutos, agora excluído, disse que só preciso de ‘reiniciar’. Sim, isso funcionaria, mas eu teria que renunciar --rm - posso ter um ou outro, mas não ambos, dado o erro que mostrei na pergunta. Veja a edição de esclarecimento sobre por que eu acho que` --rm ’ é necessário).

Não há uma boa maneira de diferenciar entre as circunstâncias em que você deseja que o contêiner seja reiniciado e as circunstâncias em que deseja que o contêiner seja excluído. Isso é algo que você precisa lidar fora do Docker.