Como atualizar automaticamente os contêineres do Docker, se as imagens de base forem atualizadas

205

Digamos que eu tenha um contêiner trivial baseado no ubuntu:latest. Agora, há uma atualização de segurança e ubuntu:latesté atualizada no repositório de encaixe.

  1. Como saberia se minha imagem local e seus contêineres estão atrasados?

  2. Existe alguma prática recomendada para atualizar automaticamente imagens e contêineres locais para seguir as atualizações de repositório do docker, que na prática dariam as mesmas vantagens de ter atualizações autônomas em execução em uma máquina ubuntu convencional

hbogert
fonte
11
Estou procurando uma resposta para isso desde o início do docker. É ainda um pouco mais complicado. Se eu instalar o apache (por exemplo) e isso for atualizado, a imagem base não muda, pois eu o instalei depois. Eu ainda gostaria de ter atualizações automáticas para o apache. Na verdade, eu perguntei no IRC sobre isso e tem "siga a montante e reconstruir as atualizações" como uma resposta ...
Mathias
8
Ainda bem que não sou o único a pensar. Parece que o desenvolvimento e a reprodutibilidade são mais importantes para os desenvolvedores do docker do que os mecanismos de atualização que temos há anos.
Hbogert 20/10
O problema é que o docker é apenas a tecnologia para os contêineres. Eu acho que precisa de algum tempo para um ecossistema evoluir em torno disso. Existem outros problemas que o docker não soluciona, como o log.
Mathias
3
Obrigado a todos que responderam. Me desculpe, eu não poderia dividir a recompensa. Embora não houvesse uma solução final para o meu problema, houve boas contribuições de todos vocês.
Mathias
1
Para o @Mathias, a solução que acabei de adicionar possui um script que verifica se há atualizações de segurança para pacotes instalados no contêiner após a extração. Ele também possui um script separado para verificar a imagem base.
Fmstrat

Respostas:

9

Uma das maneiras de fazer isso é direcionar isso pelos sistemas de CI / CD. Depois que sua imagem pai for criada, tenha algo que varre seus repositórios git em busca de imagens usando esse pai. Se encontrado, você enviaria uma solicitação de recebimento para encontrar novas versões da imagem. A solicitação de recebimento, se todos os testes forem aprovados, seria mesclada e você teria uma nova imagem filha com base no pai atualizado. Um exemplo de ferramenta que adota essa abordagem pode ser encontrado aqui: https://engineering.salesforce.com/open-sourcing-dockerfile-image-update-6400121c1a75 .

Se você não controlar sua imagem pai, como seria o caso, dependendo da ubuntuimagem oficial , poderá escrever algumas ferramentas que detectam alterações na tag ou na soma de verificação da imagem pai (não é a mesma coisa, as tags são mutáveis) e invocar filhos que a imagem cria de acordo.

Ma3oxuct
fonte
Uau, este é um grande martelo, que disse: desde o momento em que fiz essa pergunta, também percebi que o servidor de compilação é o lugar para resolver esse problema. Fico feliz em ver algumas ferramentas. Se você explicar sua abordagem em conceitos genéricos (e não sua ferramenta / implementação exata) e incluí-la na resposta, provavelmente a aceitarei.
Hbogert 18/08/19
Graças @hbogert eu editei o exposto, e também incluem uma idéia sobre o que fazer se você está lidando com imagens públicas
Ma3oxuct
123

Usamos um script que verifica se um contêiner em execução é iniciado com a imagem mais recente. Também usamos scripts init iniciados para iniciar a imagem do docker.

#!/usr/bin/env bash
set -e
BASE_IMAGE="registry"
REGISTRY="registry.hub.docker.com"
IMAGE="$REGISTRY/$BASE_IMAGE"
CID=$(docker ps | grep $IMAGE | awk '{print $1}')
docker pull $IMAGE

for im in $CID
do
    LATEST=`docker inspect --format "{{.Id}}" $IMAGE`
    RUNNING=`docker inspect --format "{{.Image}}" $im`
    NAME=`docker inspect --format '{{.Name}}' $im | sed "s/\///g"`
    echo "Latest:" $LATEST
    echo "Running:" $RUNNING
    if [ "$RUNNING" != "$LATEST" ];then
        echo "upgrading $NAME"
        stop docker-$NAME
        docker rm -f $NAME
        start docker-$NAME
    else
        echo "$NAME up to date"
    fi
done

E init parece

docker run -t -i --name $NAME $im /bin/bash
bsuttor
fonte
1
Muito obrigado por esta valiosa contribuição. Esta parece ser uma boa maneira de atualizar a imagem base. A questão restante é: como você atualiza um aplicativo (como o apache) instalado pela distribuição no dockerfile? Ou você usa apenas imagens de base prontas que precisam apenas do código do seu aplicativo (como um site)?
Mathias
Usamos empacotador e fantoche para configurar nossas imagens. Nossas imagens estão prontos para ir para a produção após a sua criação
bsuttor
@ Matias, veja minha resposta editada Eu tenho uma pequena ferramenta docker-run que estou usando para atualizar pacotes linux (atualmente debian / ubuntu) em todos os contêineres em execução.
589 iTech #
3
Se uma imagem tiver o mesmo nome que um contêiner (por exemplo redis), LATEST=`docker inspect --format "{{.Id}}" $IMAGE`obterá as informações do contêiner. Adicione --type imagepara corrigir isso.
Patrick Fisher
1
Obrigado pela sua postagem. Eu modifiquei para embrulhar a coisa toda dentro de um loop para obter imagens da janela de encaixe: for IMAGE in $(docker ps --format {{.Image}} -q | sort -u)
Armand
25

Uma 'maneira do docker' seria usar as compilações automatizadas do hub do docker . O recurso Links de Repositório reconstruirá seu contêiner quando um contêiner upstream for reconstruído, e o recurso Webhooks enviará uma notificação.

Parece que os webhooks estão limitados a chamadas HTTP POST. Você precisaria configurar um serviço para capturá-los ou talvez usar um dos POST para enviar serviços por e-mail.

Ainda não examinei, mas o novo Docker Universal Control Plane pode ter um recurso para detectar contêineres atualizados e reimplementar.

TÁXI
fonte
Eu tive que construir uma webhook ao serviço AMQP: github.com/goliatone/rabbithook
goliatone
Infelizmente, os gatilhos upstream não estão mais disponíveis: github.com/docker/hub-feedback/issues/1717 .
Julien Chastang
23

Você pode usar a Torre de Vigia para procurar atualizações na imagem da qual um contêiner é instanciado, puxar automaticamente a atualização e reiniciar o contêiner usando a imagem atualizada. No entanto, isso não resolve o problema de reconstruir suas próprias imagens personalizadas quando há uma alteração na imagem upstream em que ela se baseia. Você pode ver isso como um problema de duas partes: (1) saber quando uma imagem upstream foi atualizada e (2) fazer a reconstrução real da imagem. (1) pode ser resolvido com bastante facilidade, mas (2) depende muito do seu ambiente / práticas de construção local, por isso é provavelmente muito mais difícil criar uma solução generalizada para isso.

Se você puder usar as compilações automatizadas do Docker Hub , todo o problema poderá ser resolvido de forma relativamente limpa usando o recurso de links do repositório , que permite ativar uma reconstrução automaticamente quando um repositório vinculado (provavelmente um upstream) é atualizado. Você também pode configurar um webhook para notificá-lo quando ocorrer uma compilação automatizada. Se desejar uma notificação por email ou SMS, você poderá conectar o webhook ao IFTTT Maker . Achei a interface do usuário IFTTT um pouco confusa, mas você configuraria o webhook do Docker para postar em https://maker.ifttt.com/trigger/docker_xyz_image_built / com / key / your_key.

Se precisar criar localmente, você pode pelo menos resolver o problema de receber notificações quando uma imagem upstream for atualizada criando um repositório fictício no Docker Hub vinculado aos seus repositórios de interesse. O único objetivo do repositório fictício seria acionar um webhook quando ele fosse reconstruído (o que implica que um de seus repositórios vinculados foi atualizado). Se você conseguir receber esse webhook, poderá usá-lo para desencadear uma reconstrução do seu lado.

jjlin
fonte
1
A Sentinela usa o soquete do docker. De uma perspectiva de segurança que está dando acesso root à máquina host.
JOEG
1
Além disso, a Watchtower não parece capaz de atualizar imagens de repositórios particulares que não sejam o Docker Hub. Que chatice para nós que usamos o Azure.
Thomas Eyde
1
Você pode usar registros privados usando variáveis ​​de ambiente REPO_USERe REPO_PASS. Dê uma olhada no readme.md da Torre de Vigia para obter mais informações: github.com/v2tec/watchtower#usage
Alejandro Nortes
2
Como aviso, a torre de vigia é abandonada pelo mantenedor e a imagem no DockerHub nem está atualizada com a do github.
XandStrike #
O repositório da Torre de Vigia parece ter sido migrado para conterrrr / torre de vigia . E há alguns problemas com as compilações automatizadas vinculadas no Dockerhub, conforme apontado por esta resposta em uma pergunta semelhante .
chrki 26/04
10

Eu tive o mesmo problema e pensei que ele pode ser simplesmente resolvido por um trabalho cron ligando unattended-upgradediariamente.

Minha intenção é ter isso como uma solução automática e rápida para garantir que o contêiner de produção seja seguro e atualizado, pois pode levar algum tempo para atualizar minhas imagens e implantar uma nova imagem de janela de encaixe com as atualizações de segurança mais recentes.

Também é possível automatizar a criação e implantação da imagem com ganchos do Github

Criei uma imagem básica do Docker, que verifica e instala automaticamente atualizações de segurança diariamente (pode ser executada diretamente por docker run itech/docker-unattended-upgrade).

Também deparei com outra abordagem diferente para verificar se o contêiner precisa de uma atualização.

Minha implementação completa:

Dockerfile

FROM ubuntu:14.04   

RUN apt-get update \
&& apt-get install -y supervisor unattended-upgrades \
&& rm -rf /var/lib/apt/lists/*

COPY install /install
RUN chmod 755 install
RUN /install

COPY start /start
RUN chmod 755 /start

Scripts auxiliares

instalar

#!/bin/bash
set -e

cat > /etc/supervisor/conf.d/cron.conf <<EOF
[program:cron]
priority=20
directory=/tmp
command=/usr/sbin/cron -f
user=root
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
EOF

rm -rf /var/lib/apt/lists/*

ENTRYPOINT ["/start"]

começar

#!/bin/bash

set -e

echo "Adding crontab for unattended-upgrade ..."
echo "0 0 * * * root /usr/bin/unattended-upgrade" >> /etc/crontab

# can also use @daily syntax or use /etc/cron.daily

echo "Starting supervisord ..."
exec /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf

Editar

Desenvolvi uma pequena ferramenta docker-run que é executada como contêiner de docker e pode ser usada para atualizar pacotes dentro de todos ou em contêineres em execução selecionados; também pode ser usada para executar qualquer comando arbitrário.

Pode ser facilmente testado com o seguinte comando:

docker run --rm -v /var/run/docker.sock:/tmp/docker.sock itech/docker-run exec

que por padrão executará o datecomando em todos os contêineres em execução e exibirá os resultados. Se você passar em updatevez execdele, será executado apt-get updateseguido por apt-get upgrade -ytodos os contêineres em execução

iTech
fonte
minha referência à atualização autônoma foi apenas para mostrar a analogia em um ambiente não docker. Minha intenção é resolver isso da maneira do docker (se houver, oc.) Ter um processo extra em um contêiner supera o objetivo do docker imo. Ele corrige o problema do atraso entre a atualização de sua imagem e você, o usuário, na verdade, a coloca no seu contêiner atual. Embora isso possa levar até 1 dia com atualizações autônomas, também .. A referência do github também não é satisfatória, porque o mecanismo de atualização agora depende muito do sistema operacional host.
Hbogert # 24/14
O "modo docker" não impede a execução de outros processos no mesmo contêiner, se eles estiverem intimamente relacionados e não criarão gargalo de escalabilidade. E esse caso de uso específico é um bom exemplo de quando você pode ter um contêiner com outro processo em execução. (por exemplo, veja a imagem do gitlab, pois ele executa vários processos obrigatórios no mesmo contêiner).
iTech
Eu não chamaria um mecanismo de atualização fortemente relacionado à função principal de uma imagem. Essa solução é como fornecer a cada aplicativo em uma máquina convencional seu próprio mecanismo de atualização, em vez de sobrecarregar o gerenciador de pacotes. Embora seja uma solução, ela não responde à minha pergunta, atualizando automaticamente as imagens locais e, em seguida, os contêineres devem ser executados novamente. Com a atualização nos próprios contêineres, estamos introduzindo muitos estados novamente, dos quais não temos ideia, o que é contrário à janela de encaixe (novamente imho).
Hbogert # 24/14
1
Você pode precisar de algo de nível superior ao docker, como o Kubernetesque é útil para a implantação de grandes infraestruturas, mas ainda está em desenvolvimento pesado pelo Google. No momento, você pode automatizar isso com uma ferramenta de provisionamento como o Ansible de uma maneira bastante simples.
iTech
Sua "abordagem diferente" citada pode ser o que eu estava procurando. Sua própria contribuição parece uma alternativa viável para "recipientes de gordura". Definitivamente analisarei um pouco mais as duas coisas, obrigado por sua resposta.
Mathias
7

Você não saberia que seu contêiner está atrasado sem executar o docker pull . Você precisará reconstruir ou recompor sua imagem.

docker pull image:tag
docker-compose -f docker-compose.yml -f production.yml up -d --build

Os comandos podem ser colocados em um script junto com qualquer outra coisa necessária para concluir a atualização, embora um contêiner adequado não precise de mais nada.

seanmcl
fonte
1: ok, mas então eu teria que olhar para todas as minhas imagens locais, obter suas imagens de base, puxá-las. Em seguida, recrie as imagens cujas imagens básicas foram alteradas. Em seguida, pare os contêineres cuja imagem foi alterada e recrie os contêineres com 'docker run' e os parâmetros necessários. Isso parece excessivamente manual. Mas se esse é o status quo, aceitarei a resposta.
Hbogert 17/10/2014
Aguarde antes de aceitar. Talvez haja algo por aí. Uso o docker há 6 meses, mas não acompanho os desenvolvimentos mais recentes.
seanmcl
De alguma forma, internamente, o Docker pode comparar imagens para executar seu recurso de 'cache'. Talvez você possa encontrar uma maneira de aproveitar isso. Em outras palavras, verifique se as imagens subjacentes (desde a base) foram alteradas e, em seguida, inicie um processo de reconstrução. Infelizmente, o armazenamento em cache não ajudará nesse caso: a imagem inteira será reconstruída porque a imagem base foi alterada.
Thom Parkin
5

O gerenciamento de dependências para imagens do Docker é um problema real. Faço parte de uma equipe que construiu uma ferramenta, o MicroBadger , para ajudar com isso, monitorando imagens de contêineres e inspecionando metadados. Um de seus recursos é permitir que você configure um webhook de notificação chamado quando uma imagem em que você está interessado (por exemplo, uma imagem de base) é alterada.

Liz Rice
fonte
5

Há muitas respostas aqui, mas nenhuma delas atendeu às minhas necessidades. Eu queria uma resposta real para a pergunta nº 1 do autor. Como sei quando uma imagem é atualizada no hub.docker.com?

O script abaixo pode ser executado diariamente. Na primeira execução, ele obtém uma linha de base das tags e atualiza as datas do registro do HUB e as salva localmente. Desde então, toda vez que é executado, ele verifica o registro em busca de novas tags e datas de atualização. Como isso muda toda vez que uma nova imagem existe, informa se a imagem base foi alterada. Aqui está o script:

#!/bin/bash

DATAPATH='/data/docker/updater/data'

if [ ! -d "${DATAPATH}" ]; then
        mkdir "${DATAPATH}";
fi
IMAGES=$(docker ps --format "{{.Image}}")
for IMAGE in $IMAGES; do
        ORIGIMAGE=${IMAGE}
        if [[ "$IMAGE" != *\/* ]]; then
                IMAGE=library/${IMAGE}
        fi
        IMAGE=${IMAGE%%:*}
        echo "Checking ${IMAGE}"
        PARSED=${IMAGE//\//.}
        if [ ! -f "${DATAPATH}/${PARSED}" ]; then
                # File doesn't exist yet, make baseline
                echo "Setting baseline for ${IMAGE}"
                curl -s "https://registry.hub.docker.com/v2/repositories/${IMAGE}/tags/" > "${DATAPATH}/${PARSED}"
        else
                # File does exist, do a compare
                NEW=$(curl -s "https://registry.hub.docker.com/v2/repositories/${IMAGE}/tags/")
                OLD=$(cat "${DATAPATH}/${PARSED}")
                if [[ "${VAR1}" == "${VAR2}" ]]; then
                        echo "Image ${IMAGE} is up to date";
                else
                        echo ${NEW} > "${DATAPATH}/${PARSED}"
                        echo "Image ${IMAGE} needs to be updated";
                        H=`hostname`
                        ssh -i /data/keys/<KEYFILE> <USER>@<REMOTEHOST>.com "{ echo \"MAIL FROM: root@${H}\"; echo \"RCPT TO: <USER>@<EMAILHOST>.com\"; echo \"DATA\"; echo \"Subject: ${H} - ${IMAGE} needs update\"; echo \"\"; echo -e \"\n${IMAGE} needs update.\n\ndocker pull ${ORIGIMAGE}\"; echo \"\"; echo \".\"; echo \"quit\"; sleep 1; } | telnet <SMTPHOST> 25"
                fi

        fi
done;

Você deseja alterar a DATAPATHvariável na parte superior e o comando de notificação por email no final para atender às suas necessidades. Para mim, eu tenho o SSH em um servidor em outra rede onde meu SMTP está localizado. Mas você também pode usar o mailcomando facilmente .

Agora, você também deseja verificar os pacotes atualizados dentro dos próprios contêineres. Isso é provavelmente mais eficaz do que fazer um "puxão" quando seus contêineres estiverem funcionando. Aqui está o script para fazer isso:

#!/bin/bash


function needsUpdates() {
        RESULT=$(docker exec ${1} bash -c ' \
                if [[ -f /etc/apt/sources.list ]]; then \
                grep security /etc/apt/sources.list > /tmp/security.list; \
                apt-get update > /dev/null; \
                apt-get upgrade -oDir::Etc::Sourcelist=/tmp/security.list -s; \
                fi; \
                ')
        RESULT=$(echo $RESULT)
        GOODRESULT="Reading package lists... Building dependency tree... Reading state information... Calculating upgrade... 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded."
        if [[ "${RESULT}" != "" ]] && [[ "${RESULT}" != "${GOODRESULT}" ]]; then
                return 0
        else
                return 1
        fi
}

function sendEmail() {
        echo "Container ${1} needs security updates";
        H=`hostname`
        ssh -i /data/keys/<KEYFILE> <USRER>@<REMOTEHOST>.com "{ echo \"MAIL FROM: root@${H}\"; echo \"RCPT TO: <USER>@<EMAILHOST>.com\"; echo \"DATA\"; echo \"Subject: ${H} - ${1} container needs security update\"; echo \"\"; echo -e \"\n${1} container needs update.\n\n\"; echo -e \"docker exec ${1} bash -c 'grep security /etc/apt/sources.list > /tmp/security.list; apt-get update > /dev/null; apt-get upgrade -oDir::Etc::Sourcelist=/tmp/security.list -s'\n\n\"; echo \"Remove the -s to run the update\"; echo \"\"; echo \".\"; echo \"quit\"; sleep 1; } | telnet <SMTPHOST> 25"
}

CONTAINERS=$(docker ps --format "{{.Names}}")
for CONTAINER in $CONTAINERS; do
        echo "Checking ${CONTAINER}"
        if needsUpdates $CONTAINER; then
                sendEmail $CONTAINER
        fi
done
Fmstrat
fonte
1
mkdir no primeiro script provavelmente deve ser: mkdir -p Além disso, o primeiro script compara VAR1 com VAR2, suponha que ele deva comparar OLD com NEW. Se for verdade, porém, isso significa que esse script não fará realmente o que o OP deseja, a menos que tenha sido executado pela primeira vez no momento da instalação. Ou seja, ele não é realmente determinar nada sobre o que está instalado, apenas se os resultados diferem das execuções anteriores ...
JOEG
5

Outra abordagem pode ser assumir que sua imagem de base fica para trás rapidamente (e é muito provável que isso aconteça) e forçar outra compilação de imagem de seu aplicativo periodicamente (por exemplo, toda semana) e depois reimplantá-lo se ele tiver sido alterado.

Até onde eu sei, imagens de base populares como o Debian ou Java oficial atualizam suas tags para atender a correções de segurança, para que as tags não sejam imutáveis ​​(se você quiser uma garantia mais forte de que precisa usar a referência [image: @digest ], disponível nas versões mais recentes do Docker). Portanto, se você construir sua imagem docker build --pull, seu aplicativo deverá obter a melhor e mais recente etiqueta de imagem básica à qual você está referenciando.

Como as tags mutáveis ​​podem ser confusas, é melhor aumentar o número da versão do seu aplicativo toda vez que você fizer isso, para que pelo menos do seu lado tudo fique mais limpo.

Portanto, não tenho certeza de que o script sugerido em uma das respostas anteriores funcione, pois ele não reconstrói a imagem do aplicativo - apenas atualiza a tag da imagem base e reinicia o contêiner, mas o novo contêiner ainda faz referência o antigo hash da imagem base.

Eu não recomendaria a execução de tarefas do tipo cron em contêineres (ou qualquer outro processo, a menos que seja realmente necessário), pois isso contraria o mantra de executar apenas um processo por contêiner (existem vários argumentos sobre por que isso é melhor, então eu ' não vou entrar aqui).

Bogdan
fonte
4

Não vou entrar na questão de saber se você deseja ou não atualizações autônomas na produção (acho que não). Só estou deixando isso aqui para referência, caso alguém ache útil. Atualize todas as imagens do docker para a versão mais recente com o seguinte comando no seu terminal:

# docker images | awk '(NR>1) && ($2!~/none/) {print $1":"$2}' | xargs -L1 docker pull

Meferdati
fonte
1
O comando é útil para atualizar todas as imagens, mas não altera nada em execução na produção. Os contêineres ainda se originam das imagens antigas, que agora estão sem marcação.
Nenhum
Verdade. E aqui está mais um para os livros ... Use # docker system prune -a --volumes -fpara limpar antigos (pendurados) imagens, volumes etc.
Meferdati
4

ATUALIZAÇÃO: Use Dependabot - https://dependabot.com/docker/

BLUF: encontrar o ponto de inserção correto para monitorar alterações em um contêiner é o desafio. Seria ótimo se o DockerHub resolvesse isso. (Os links do repositório foram mencionados, mas observe ao configurá-los no DockerHub - " Acione uma compilação neste repositório sempre que a imagem base for atualizada no Docker Hub. Funciona apenas para imagens não oficiais." )

Enquanto tentava resolver isso sozinho, vi várias recomendações para webhooks, por isso queria elaborar algumas soluções que usei.

  1. Use o microbadger.com para rastrear alterações em um contêiner e use o recurso de webhook de notificação para acionar uma ação. Configurei isso com o zapier.com (mas você pode usar qualquer serviço personalizável de webhook) para criar um novo problema no meu repositório do github que usa o Alpine como imagem de base.

    • Prós: Você pode revisar as alterações relatadas pelo microbadger no github antes de tomar uma ação.
    • Contras: O Microbadger não permite rastrear uma tag específica. Parece que apenas rastreia 'mais recentes'.
  2. Acompanhe o feed RSS para as confirmações do git em um contêiner upstream. ex. https://github.com/gliderlabs/docker-alpine/commits/rootfs/library-3.8/x86_64 . Usei o zapier.com para monitorar este feed e acionar uma compilação automática do meu contêiner no Travis-CI sempre que algo for confirmado. Isso é um pouco extremo, mas você pode alterar o gatilho para fazer outras coisas, como abrir um problema no seu repositório git para intervenção manual.

    • Prós: Mais perto de um pipline automatizado. A construção do Travis-CI apenas verifica se o seu contêiner tem problemas com o que foi confirmado no repositório de imagens base. Depende de você se o seu serviço de IC tomar outra ação.
    • Contras: acompanhar o feed de confirmação não é perfeito. Muitas coisas são comprometidas com o repositório que não afetam a construção da imagem base. Não leva em consideração nenhum problema com a frequência / número de confirmações e qualquer otimização da API.
2stacks
fonte
3

Premissa para a minha resposta:

  1. Os contêineres são executados com tags.
  2. A mesma tag pode ser apontada para UUID de imagem diferente, conforme desejamos.
  3. As atualizações feitas em uma imagem podem ser confirmadas em uma nova camada de imagem

Abordagem

  1. Crie todos os contêineres em primeiro lugar com um script de atualização de patch de segurança
  2. Crie um processo automatizado para os seguintes
    • Execute uma imagem existente para um novo contêiner com script de patch de segurança como o comando
    • Confirme as alterações na imagem como
      • tag existente -> seguida pela reinicialização dos contêineres, um por um
      • nova tag de versão -> substitua alguns contêineres por uma nova tag -> validar -> mova todos os contêineres para a nova tag

Além disso, a imagem de base pode ser atualizada / o contêiner com uma nova imagem de base completa pode ser construído em intervalos regulares, conforme o mantenedor achar necessário

Vantagens

  1. Estamos preservando a versão antiga da imagem enquanto criamos a nova imagem corrigida de segurança; portanto, podemos reverter para a imagem em execução anterior, se necessário
  2. Estamos preservando o cache do docker, portanto, menos transferência de rede (somente a camada alterada entra em ação)
  3. O processo de atualização pode ser validado na preparação antes de passar para prod
  4. Este pode ser um processo controlado, portanto, os patches de segurança somente quando necessários / considerados importantes podem ser enviados.
Phani
fonte
Em um ambiente de produção, embora sejam atualizações de segurança, duvido que você queira ter atualizações autônomas! Se precisar de atualizações autônomas, o processo poderá ser executado em intervalos regulares (conforme apropriado) como uma tarefa cron.
Phani
1
Minha premissa é que as atualizações de segurança devem vir de imagens upstream / base.
Hbogert
@ hbogert Prefiro dizer que há uma linha tênue de diferenciação entre teoria e prática. Quando as coisas entrarem em prática, haverá muitos aspectos externos que precisam ser levados em consideração, como: custo (não apenas valor em dólar, mas também tempo) associado à implementação.
Phani
3

As respostas acima também estão corretas

Existem duas abordagens

  1. Use webhooks
  2. Execute o script a cada minuto específico para obter novas imagens das janelas de encaixe

Estou apenas compartilhando script, pode ser que seja útil para você! Você pode usá-lo com cronjob, tentei com sucesso no OSX

#!/bin/bash
##You can use below commented line for setting cron tab for running cron job and to store its O/P in one .txt file  
#* * * * * /usr/bin/sudo -u admin -i bash -c /Users/Swapnil/Documents/checkimg.sh > /Users/Swapnil/Documents/cron_output.log 2>&1
# Example for the Docker Hub V2 API
# Returns all images and tags associated with a Docker Hub organization account.
# Requires 'jq': https://stedolan.github.io/jq/

# set username, password, and organization
# Filepath where your docker-compose file is present
FILEPATH="/Users/Swapnil/Documents/lamp-alpine"
# Your Docker hub user name
UNAME="ur username"
# Your Docker hub user password
UPASS="ur pwd"
# e.g organisation_name/image_name:image_tag
ORG="ur org name"
IMGNAME="ur img name"
IMGTAG="ur img tag"
# Container name
CONTNAME="ur container name"
# Expected built mins
BUILDMINS="5"
#Generally cronjob frequency
CHECKTIME="5"
NETWORKNAME="${IMGNAME}_private-network"
#After Image pulling, need to bring up all docker services?
DO_DOCKER_COMPOSE_UP=true
# -------
echo "Eecuting Script @ date and time in YmdHMS: $(date +%Y%m%d%H%M%S)"
set -e
PIDFILE=/Users/Swapnil/Documents/$IMGNAME/forever.pid
if [ -f $PIDFILE ]
then
  PID=$(cat $PIDFILE)
  ps -p $PID > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
    echo "Process already running"
    exit 1
  else
    ## Process not found assume not running
    echo $$
    echo $$ > $PIDFILE
    if [ $? -ne 0 ]
    then
      echo "Could not create PID file"
      exit 1
    fi
  fi
else
  echo $$ > $PIDFILE
  if [ $? -ne 0 ]
  then
    echo "Could not create PID file"
    exit 1
  fi
fi

# Check Docker is running or not; If not runing then exit
if docker info|grep Containers ; then
    echo "Docker is running"
else
    echo "Docker is not running"
    rm $PIDFILE
    exit 1
fi

# Check Container is running or not; and set variable
CONT_INFO=$(docker ps -f "name=$CONTNAME" --format "{{.Names}}")
if [ "$CONT_INFO" = "$CONTNAME" ]; then
    echo "Container is running"
    IS_CONTAINER_RUNNING=true
else
    echo "Container is not running"
    IS_CONTAINER_RUNNING=false
fi


# get token
echo "Retrieving token ..."
TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${UNAME}'", "password": "'${UPASS}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token)

# get list of repositories
echo "Retrieving repository list ..."
REPO_LIST=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/?page_size=100 | jq -r '.results|.[]|.name')

# output images & tags
echo "Images and tags for organization: ${ORG}"
echo
for i in ${REPO_LIST}
do
  echo "${i}:"
  # tags
  IMAGE_TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${i}/tags/?page_size=100 | jq -r '.results|.[]|.name')
  for j in ${IMAGE_TAGS}
  do
    echo "  - ${j}"
  done
  #echo
done

# Check Perticular image is the latest or not
#imm=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${IMGNAME}/tags/?page_size=100)
echo "-----------------"
echo "Last built date details about Image ${IMGNAME} : ${IMGTAG} for organization: ${ORG}"
IMAGE_UPDATED_DATE=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${IMGNAME}/tags/?page_size=100 | jq -r '.results|.[]|select(.name | contains("'${IMGTAG}'")).last_updated')
echo "On Docker Hub IMAGE_UPDATED_DATE---$IMAGE_UPDATED_DATE"
echo "-----------------"

IMAGE_CREATED_DATE=$(docker image inspect ${ORG}/${IMGNAME}:${IMGTAG} | jq -r '.[]|.Created')
echo "Locally IMAGE_CREATED_DATE---$IMAGE_CREATED_DATE"

updatedDate=$(date -jf '%Y-%m-%dT%H:%M' "${IMAGE_UPDATED_DATE:0:16}" +%Y%m%d%H%M%S) 
createdDate=$(date -jf '%Y-%m-%dT%H:%M' "${IMAGE_CREATED_DATE:0:16}" +%Y%m%d%H%M%S)
currentDate=$(date +%Y%m%d%H%M%S)

start_date=$(date -jf "%Y%m%d%H%M%S" "$currentDate" "+%s")
end_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s")
updiffMins=$(( ($start_date - $end_date) / (60) ))
if [[ "$updiffMins" -lt $(($CHECKTIME+1)) ]]; then
        if [ ! -d "${FILEPATH}" ]; then
            mkdir "${FILEPATH}";
        fi
        cd "${FILEPATH}"
        pwd
        echo "updatedDate---$updatedDate" > "ScriptOutput_${currentDate}.txt"
        echo "createdDate---$createdDate" >> "ScriptOutput_${currentDate}.txt"
        echo "currentDate---$currentDate" >> "ScriptOutput_${currentDate}.txt"
        echo "Found after regular checking time -> Docker hub's latest updated image is new; Diff ${updiffMins} mins" >> "ScriptOutput_${currentDate}.txt"
        echo "Script is checking for latest updates after every ${CHECKTIME} mins" >> "ScriptOutput_${currentDate}.txt"
        echo "Fetching all new"
        echo "---------------------------"
        if $IS_CONTAINER_RUNNING ; then
            echo "Container is running"         
        else
            docker-compose down
            echo "Container stopped and removed; Network removed" >> "ScriptOutput_${currentDate}.txt"
        fi
        echo "Image_Created_Date=$currentDate" > ".env"
        echo "ORG=$ORG" >> ".env"
        echo "IMGNAME=$IMGNAME" >> ".env"
        echo "IMGTAG=$IMGTAG" >> ".env"
        echo "CONTNAME=$CONTNAME" >> ".env"
        echo "NETWORKNAME=$NETWORKNAME" >> ".env"
        docker-compose build --no-cache
        echo "Docker Compose built" >> "ScriptOutput_${currentDate}.txt"
        if $DO_DOCKER_COMPOSE_UP ; then
            docker-compose up -d
            echo "Docker services are up now, checked in" >> "ScriptOutput_${currentDate}.txt"  
        else
            echo "Docker services are down, checked in" >> "ScriptOutput_${currentDate}.txt"
        fi
elif [[ "$updatedDate" -gt "$createdDate" ]]; then 
    echo "Updated is latest"
    start_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s")
    end_date=$(date -jf "%Y%m%d%H%M%S" "$createdDate" "+%s")
    diffMins=$(( ($start_date - $end_date) / (60) ))
    if [[ "$BUILDMINS" -lt "$diffMins" ]]; then
        if [ ! -d "${FILEPATH}" ]; then
            mkdir "${FILEPATH}";
        fi
        cd "${FILEPATH}"
        pwd
        echo "updatedDate---$updatedDate" > "ScriptOutput_${currentDate}.txt"
        echo "createdDate---$createdDate" >> "ScriptOutput_${currentDate}.txt"
        echo "currentDate---$currentDate" >> "ScriptOutput_${currentDate}.txt"
        echo "Found after comparing times -> Docker hub's latest updated image is new; Diff ${diffMins} mins" >> "ScriptOutput_${currentDate}.txt"
        echo "Actual image built time is less i.e. ${diffMins} mins than MAX expexted BUILD TIME i.e. ${BUILDMINS} mins" >> "ScriptOutput_${currentDate}.txt"
        echo "Fetching all new" >> "ScriptOutput_${currentDate}.txt"
        echo "-----------------------------"
        if $IS_CONTAINER_RUNNING ; then
            echo "Container is running"         
        else
            docker-compose down
            echo "Container stopped and removed; Network removed" >> "ScriptOutput_${currentDate}.txt"
        fi
        echo "Image_Created_Date=$currentDate" > ".env"
        echo "ORG=$ORG" >> ".env"
        echo "IMGNAME=$IMGNAME" >> ".env"
        echo "IMGTAG=$IMGTAG" >> ".env"
        echo "CONTNAME=$CONTNAME" >> ".env"
        echo "NETWORKNAME=$NETWORKNAME" >> ".env"
        docker-compose build --no-cache
        echo "Docker Compose built" >> "ScriptOutput_${currentDate}.txt"
        if $DO_DOCKER_COMPOSE_UP ; then
            docker-compose up -d
            echo "Docker services are up now" >> "ScriptOutput_${currentDate}.txt"  
        else
            echo "Docker services are down" >> "ScriptOutput_${currentDate}.txt"
        fi
    elif [[ "$BUILDMINS" -gt "$diffMins" ]]; then
        echo "Docker hub's latest updated image is NOT new; Diff ${diffMins} mins"
        echo "Docker images not fetched"
    else
        echo "Docker hub's latest updated image is NOT new; Diff ${diffMins} mins"
        echo "Docker images not fetched"
    fi
elif [[ "$createdDate" -gt "$updatedDate" ]]; then 
    echo "Created is latest"
    start_date=$(date -jf "%Y%m%d%H%M%S" "$createdDate" "+%s")
    end_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s")
    echo "Docker hub has older docker image than local; Older than $(( ($start_date - $end_date) / (60) ))mins"
fi
echo 
echo "------------end---------------"
rm $PIDFILE

Aqui está o meu arquivo docker-compose

version:  "3.2"
services:
  lamp-alpine:
    build:
      context: .
    container_name: "${CONTNAME}"
    image: "${ORG}/${IMGNAME}:${IMGTAG}"
    ports:
      - "127.0.0.1:80:80"
    networks:
      - private-network 

networks:
  private-network:
    driver: bridge
Akshay Shikre
fonte
3

Aqui está uma maneira mais simples de atualizar o contêiner do docker automaticamente

Coloque o trabalho via $ crontab -e:

0 * * * * sh ~/.docker/cron.sh

Crie o diretório ~/.dockercom o arquivo cron.sh:

#!/bin/sh
if grep -Fqe "Image is up to date" << EOF
`docker pull ubuntu:latest`
EOF
then
    echo "no update, just do cleaning"
    docker system prune --force
else
    echo "newest exist, recompose!"
    cd /path/to/your/compose/file
    docker-compose down --volumes
    docker-compose up -d
fi
Chetabahana
fonte
0

você já tentou isso: https://github.com/v2tec/watchtower . é uma ferramenta simples em execução no contêiner do docker que observa outros contêineres; se a imagem base for alterada, ela será puxada e reimplantada.

linehrr
fonte
-1

Uma solução simples e ótima é pastor

user672009
fonte
iiuc, isso não ajuda no sentido geral, porque isso é acoplado ao Swarm e apenas reinicia o upstream, enquanto que queremos reagir, reconstruir etc. em alterações do upstream e não simplesmente reiniciar.
Hbogert 12/11/19
Isso soa como algo que você deve fazer em um oleoduto CI
user672009