Comment mettre à jour automatiquement vos conteneurs Docker, si les images de base sont mises à jour

206

Disons que j'ai un conteneur trivial basé sur le ubuntu:latest. Il y a maintenant une mise à jour de sécurité et ubuntu:latestest mise à jour dans le dépôt Docker.

  1. Comment pourrais-je savoir que mon image locale et ses conteneurs sont en retard?

  2. Existe-t-il une meilleure pratique pour la mise à jour automatique des images et des conteneurs locaux pour suivre les mises à jour du référentiel docker, ce qui, dans la pratique, vous donnerait les mêmes avantages d'avoir des mises à niveau sans assistance exécutées sur une machine ubuntu conventionnelle

hbogert
la source
11
Je cherche une réponse à cela depuis le début du docker. C'est encore un peu plus compliqué. Si j'installe apache (par exemple) et que cela est mis à jour, l'image de base ne change pas, car je l'ai installée par la suite. Je voudrais toujours avoir des mises à jour automatiques pour apache. En fait, j'ai demandé à l'IRC à ce sujet et obtenu "suivre en amont et reconstruire sur les mises à jour" comme réponse ...
Mathias
8
Heureux, je ne suis pas le seul à me demander. Il semble que le développement et la reproductibilité soient plus importants pour les développeurs Docker que les mécanismes de mise à jour raisonnables que nous avons depuis des années.
hbogert
Le problème est que le docker n'est que la technologie des conteneurs. Je pense qu'il faut du temps pour qu'un écosystème évolue autour de cela. Il existe d'autres problèmes que Docker ne résout pas, comme la journalisation.
Mathias
3
Merci à tous ceux qui ont répondu. Je suis désolé de ne pas avoir pu partager la prime. Même s'il n'y avait pas de solution définitive à mon problème, vous avez tous été bien informés.
Mathias
1
Pour @Mathias, la solution que je viens d'ajouter a un script qui vérifiera les mises à jour de sécurité pour les packages installés dans le conteneur post-pull. Il dispose également d'un script distinct pour vérifier l'image de base.
Fmstrat

Réponses:

9

Une des façons de le faire est de le piloter via vos systèmes CI / CD. Une fois que votre image parent est construite, ayez quelque chose qui scanne votre dépôt git pour les images utilisant ce parent. S'il était trouvé, vous enverriez alors une demande d'extraction pour passer à de nouvelles versions de l'image. La demande d'extraction, si tous les tests réussissent, serait fusionnée et vous auriez une nouvelle image enfant basée sur le parent mis à jour. Un exemple d'un outil qui adopte cette approche peut être trouvé ici: https://engineering.salesforce.com/open-sourcing-dockerfile-image-update-6400121c1a75 .

Si vous ne contrôlez pas votre image parent, comme ce serait le cas si vous dépendez de l' ubuntuimage officielle , vous pouvez écrire des outils qui détectent les changements dans la balise ou la somme de contrôle de l'image parent (ce n'est pas la même chose, les balises sont mutables) et invoquer les builds d'image enfants en conséquence.

Ma3oxuct
la source
Wow, c'est un gros marteau, qui a dit: depuis le moment où j'ai posé cette question, je me suis également rendu compte que le serveur de build était l'endroit idéal pour résoudre ce problème. Je suis content de voir des outils. Si vous expliquez votre approche dans des concepts génériques (et non votre outil / implémentation exact) et que vous l'incluez dans la réponse, je l'accepterai probablement.
hbogert
Merci @hbogert J'ai édité ce qui précède et j'ai également inclus une idée de ce qu'il faut faire si vous avez affaire à des images publiques
Ma3oxuct
124

Nous utilisons un script qui vérifie si un conteneur en cours d'exécution est démarré avec la dernière image. Nous utilisons également des scripts d'init pour le démarrage de l'image 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

Et init ressemble

docker run -t -i --name $NAME $im /bin/bash
bsuttor
la source
1
Merci beaucoup pour cette précieuse contribution. Cela semble être un bon moyen de mettre à jour l'image de base. La question restante est, comment mettez-vous à jour une application (comme apache) qui a été installée par la distribution dans le dockerfile? Ou utilisez-vous uniquement des images de base prêtes à l'emploi qui n'ont besoin que de votre code d'application (comme un site Web)?
Mathias
Nous utilisons packer et marionnette pour configurer nos images. Nos images sont prêtes à être
mises
@Mathias, voir ma réponse modifiée J'ai un minuscule outil docker-run que j'utilise pour mettre à jour les paquets linux (actuellement debian / ubuntu) dans tous les conteneurs en cours d'exécution.
iTech
3
Si une image a le même nom qu'un conteneur (par exemple redis), LATEST=`docker inspect --format "{{.Id}}" $IMAGE`obtiendra les informations du conteneur. Ajoutez --type imagepour résoudre ce problème.
Patrick Fisher
1
Merci pour votre message. Je l'ai modifié pour envelopper le tout dans une boucle pour obtenir des images de docker: for IMAGE in $(docker ps --format {{.Image}} -q | sort -u)
Armand
25

Une `` méthode de docker '' consisterait à utiliser les versions automatisées de Docker Hub . La fonctionnalité Liens de référentiel reconstruira votre conteneur lorsqu'un conteneur en amont est reconstruit, et la fonctionnalité Webhooks vous enverra une notification.

Il semble que les webhooks soient limités aux appels HTTP POST. Vous devez configurer un service pour les attraper, ou peut-être utiliser l'un des POST pour envoyer des services par courrier électronique.

Je ne l'ai pas examiné, mais le nouveau plan de contrôle universel Docker pourrait avoir une fonctionnalité pour détecter les conteneurs mis à jour et redéployer.

TAXI
la source
J'ai dû créer un webhook au service AMQP: github.com/goliatone/rabbithook
goliatone
Malheureusement, les déclencheurs en amont ne sont plus disponibles: github.com/docker/hub-feedback/issues/1717 .
Julien Chastang
23

Vous pouvez utiliser Watchtower pour surveiller les mises à jour de l'image à partir de laquelle un conteneur est instancié et extraire automatiquement la mise à jour et redémarrer le conteneur à l'aide de l'image mise à jour. Cependant, cela ne résout pas le problème de la reconstruction de vos propres images personnalisées en cas de modification de l'image en amont sur laquelle elle est basée. Vous pouvez voir cela comme un problème en deux parties: (1) savoir quand une image en amont a été mise à jour et (2) faire la reconstruction réelle de l'image. (1) peut être résolu assez facilement, mais (2) dépend beaucoup de votre environnement / pratiques de construction local, il est donc probablement beaucoup plus difficile de créer une solution généralisée pour cela.

Si vous pouvez utiliser les versions automatisées de Docker Hub , tout le problème peut être résolu de manière relativement propre à l'aide de la fonctionnalité de liens de référentiel , qui vous permet de déclencher une reconstruction automatiquement lorsqu'un référentiel lié (probablement un en amont) est mis à jour. Vous pouvez également configurer un webhook pour vous avertir lorsqu'une génération automatisée se produit. Si vous souhaitez recevoir une notification par e-mail ou SMS, vous pouvez connecter le webhook à IFTTT Maker . J'ai trouvé que l'interface utilisateur IFTTT était un peu déroutante, mais vous configureriez le webhook Docker pour qu'il s'affiche sur https://maker.ifttt.com/trigger/docker_xyz_image_built / avec / key / your_key.

Si vous devez créer localement, vous pouvez au moins résoudre le problème d'obtention de notifications lorsqu'une image en amont est mise à jour en créant un référentiel factice dans Docker Hub lié à votre ou vos référentiels d'intérêt. Le seul objectif du dépôt factice serait de déclencher un webhook lors de sa reconstruction (ce qui implique que l'un de ses dépôts liés a été mis à jour). Si vous pouvez recevoir ce webhook, vous pouvez même l'utiliser pour déclencher une reconstruction de votre côté.

jjlin
la source
1
Watchtower utilise cependant la prise Docker. Du point de vue de la sécurité qui donne un accès root à la machine hôte.
JoeG
1
En outre, Watchtower ne semble pas être en mesure de mettre à jour les images à partir de référentiels privés autres que Docker Hub. Une déception pour nous qui utilisons Azure.
Thomas Eyde
1
Vous pouvez utiliser des registres privés à l'aide des variables d'environnement REPO_USERet REPO_PASS. Jetez un œil à readme.md de Watchtower pour plus d'informations: github.com/v2tec/watchtower#usage
Alejandro Nortes
2
Un mot d'avertissement, la tour de guet est abandonnée par son responsable, et l'image dans DockerHub n'est même pas à jour avec celle de github.
XanderStrike
Le dépôt Watchtower semble avoir été migré vers containrrr / watchtower . Et il y a quelques problèmes avec les builds automatisés liés sur Dockerhub, comme souligné par cette réponse sur une question similaire .
chrki
10

J'ai eu le même problème et j'ai pensé qu'il peut être simplement résolu par un travail cron appelant unattended-upgradequotidiennement.

Mon intention est d'avoir cela comme une solution automatique et rapide pour garantir que le conteneur de production est sécurisé et mis à jour car cela peut me prendre un certain temps pour mettre à jour mes images et déployer une nouvelle image docker avec les dernières mises à jour de sécurité.

Il est également possible d'automatiser la création et le déploiement d'images avec des hooks Github

J'ai créé une image de docker de base avec laquelle vérifie et installe automatiquement les mises à jour de sécurité quotidiennement (peut être exécutée directement par docker run itech/docker-unattended-upgrade).

Je suis également tombé sur une autre approche différente pour vérifier si le conteneur a besoin d'une mise à jour.

Ma mise en œuvre complète:

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 d'assistance

installer

#!/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"]

début

#!/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

Éditer

J'ai développé un petit outil docker-run qui fonctionne comme conteneur docker et peut être utilisé pour mettre à jour des packages à l'intérieur de tous les conteneurs en cours ou sélectionnés, il peut également être utilisé pour exécuter des commandes arbitraires.

Peut être facilement testé avec la commande suivante:

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

qui par défaut exécutera la datecommande dans tous les conteneurs en cours d'exécution et affichera les résultats. Si vous passez à la updateplace, execil s'exécutera apt-get updatesuivi de apt-get upgrade -ytous les conteneurs en cours d'exécution

iTech
la source
ma référence à la mise à niveau sans assistance n'était que pour montrer l'analogie dans un environnement non docker. Mon intention est de résoudre ce problème de manière docker (si cela existe.) Avoir un processus supplémentaire dans un conteneur bat le but de docker imo. Il corrige le problème du délai entre la mise à jour en amont de leur image et vous, l'utilisateur, en train de la transférer sur votre conteneur actuel. Bien que cela puisse prendre jusqu'à 1 jour avec des mises à niveau sans assistance également, alors .. La référence github n'est pas non plus satisfaisante, car le mécanisme de mise à jour dépend désormais fortement du système d'exploitation hôte.
hbogert
La «méthode du docker» ne vous empêche pas d'exécuter d'autres processus sur le même conteneur s'ils sont étroitement liés et ne créent pas de goulot d'étranglement d'évolutivité. Et ce cas d'utilisation particulier est un bon exemple de cas où vous pouvez avoir un conteneur avec un autre processus en cours d'exécution. (voir par exemple l'image de gitlab car il exécute plusieurs processus obligatoires sur le même conteneur).
iTech
Je n'appellerais pas un mécanisme de mise à jour étroitement lié à la fonction principale d'une image. Cette solution revient à donner à chaque application sur une machine conventionnelle son propre mécanisme de mise à jour au lieu de placer la charge sur un gestionnaire de packages. Bien qu'il s'agisse d'une solution, elle ne répond pas à ma question, à savoir la mise à jour automatique des images locales, puis les conteneurs doivent être réexécutés. Avec la mise à jour dans les conteneurs eux-mêmes, nous introduisons à nouveau beaucoup d'état dont nous n'avons aucune idée, ce qui est contraire à la manière de docker (encore une fois).
hbogert
1
Vous pourriez avoir besoin de quelque chose de plus haut niveau que docker, comme celui Kubernetesqui est utile pour le déploiement d'une grande infrastructure, mais il est toujours en cours de développement intensif par Google. Pour le moment, vous pouvez automatiser cela avec un outil d'approvisionnement comme Ansible d'une manière assez simple.
iTech
Votre "approche différente" citée pourrait être ce que je recherchais. Votre propre contribution ressemble à une alternative viable pour les «conteneurs de graisse». Je vais certainement examiner les deux un peu plus loin, merci pour votre réponse.
Mathias
7

Vous ne sauriez pas que votre conteneur est derrière sans exécuter la traction de docker . Ensuite, vous devrez reconstruire ou recomposer votre image.

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

Les commandes peuvent être placées dans un script avec tout autre élément nécessaire pour terminer la mise à niveau, bien qu'un conteneur approprié n'ait besoin de rien de plus.

seanmcl
la source
1: ok, mais alors je devrais regarder toutes mes images locales, obtenir leurs images de base, les extraire. Reconstruisez ensuite les images dont les images de base ont changé. Ensuite, arrêtez les conteneurs dont l'image a changé et recréez les conteneurs avec «Docker Run» et les paramètres nécessaires. Cela semble trop manuel. Mais si c'est le statu quo, alors j'accepterai la réponse.
hbogert
Veuillez patienter avant d'accepter. Il y a peut-être quelque chose là-bas. J'utilise Docker depuis 6 mois, mais je n'ai pas suivi les derniers développements.
seanmcl
D'une manière ou d'une autre, en interne, Docker est capable de comparer des images afin de réaliser sa capacité de «mise en cache». Vous pouvez peut-être trouver un moyen de tirer parti de CELA. En d'autres termes, vérifiez si les images sous-jacentes (jusqu'à la base) ont changé, puis déclenchez un processus de reconstruction. Malheureusement, la mise en cache ne vous aidera pas dans ce cas: l'image entière sera reconstruite car l'image de base a changé.
Thom Parkin
5

La gestion des dépendances pour les images Docker est un vrai problème. Je fais partie d'une équipe qui a construit un outil, MicroBadger , pour aider à cela en surveillant les images des conteneurs et en inspectant les métadonnées. L'une de ses fonctionnalités est de vous permettre de configurer un webhook de notification qui est appelé lorsqu'une image qui vous intéresse (par exemple une image de base) change.

Liz Rice
la source
5

Il y a beaucoup de réponses ici, mais aucune ne correspond à mes besoins. Je voulais une réponse réelle à la question n ° 1 du demandeur. Comment savoir quand une image est mise à jour sur hub.docker.com?

Le script ci-dessous peut être exécuté quotidiennement. Lors de la première exécution, il obtient une base de référence des balises et des dates de mise à jour à partir du registre HUB et les enregistre localement. À partir de là, chaque fois qu'il est exécuté, il recherche dans le registre de nouvelles balises et des dates de mise à jour. Étant donné que cela change chaque fois qu'une nouvelle image existe, cela nous indique si l'image de base a changé. Voici le 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;

Vous souhaiterez modifier la DATAPATHvariable en haut et modifier la commande de notification par e-mail à la fin pour répondre à vos besoins. Pour moi, je l'ai SSH dans un serveur sur un autre réseau où se trouve mon SMTP. Mais vous pouvez aussi facilement utiliser la mailcommande.

Maintenant, vous voulez également vérifier les packages mis à jour à l'intérieur des conteneurs eux-mêmes. C'est en fait probablement plus efficace que de faire un "pull" une fois que vos conteneurs fonctionnent. Voici le script pour le retirer:

#!/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
la source
1
mkdir dans le premier script devrait probablement être: mkdir -p De plus, le premier script compare VAR1 à VAR2, supposons qu'il devrait comparer OLD et NEW. Si cela est vrai, cela signifie que ce script ne fera pas vraiment ce que OP souhaite, À MOINS qu'il n'ait été exécuté pour la première fois au moment de l'installation. Autrement dit, cela ne détermine pas vraiment quoi que ce soit installé, juste si les résultats diffèrent des exécutions précédentes ...
JoeG
5

Une autre approche pourrait être de supposer que votre image de base prend du retard assez rapidement (et cela est très susceptible de se produire), et de forcer une autre génération d'image de votre application périodiquement (par exemple chaque semaine), puis de la redéployer si elle a changé.

Pour autant que je sache, les images de base populaires comme Debian ou Java mettent à jour leurs balises pour prendre en compte les correctifs de sécurité, de sorte que les balises ne sont pas immuables (si vous voulez une meilleure garantie de cela, vous devez utiliser la référence [image: @digest ], disponible dans les versions Docker les plus récentes). Par conséquent, si vous deviez construire votre image avec docker build --pull , votre application devrait obtenir la dernière et la plus grande balise d'image de base à laquelle vous faites référence.

Étant donné que les balises mutables peuvent prêter à confusion, il est préférable d'incrémenter le numéro de version de votre application chaque fois que vous faites cela afin qu'au moins de votre côté les choses soient plus propres.

Je ne suis donc pas sûr que le script suggéré dans l'une des réponses précédentes fasse l'affaire, car il ne reconstruit pas l'image de votre application - il met simplement à jour la balise d'image de base, puis redémarre le conteneur, mais le nouveau conteneur fait toujours référence l'ancien hachage de l'image de base.

Je ne recommanderais pas d'exécuter des travaux de type cron dans des conteneurs (ou tout autre processus, sauf si cela est vraiment nécessaire) car cela va à l'encontre du mantra de l'exécution d'un seul processus par conteneur (il existe divers arguments pour expliquer pourquoi c'est mieux, donc je '' je ne vais pas y entrer ici).

Bogdan
la source
4

Je ne vais pas entrer dans toute la question de savoir si vous voulez ou non des mises à jour sans surveillance en production (je pense que non). Je laisse juste ceci ici pour référence au cas où quelqu'un le trouverait utile. Mettez à jour toutes vos images de docker vers la dernière version avec la commande suivante dans votre terminal:

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

Meferdati
la source
1
La commande est utile pour mettre à jour toutes les images, mais elle ne change rien en cours d'exécution en production. Les conteneurs proviennent encore des anciennes images, qui ne sont plus marquées.
Aucun
Vrai. Et voici un de plus pour les livres ... Utilisez # docker system prune -a --volumes -fpour nettoyer les anciennes images (pendantes), les volumes, etc.
Meferdati
4

MISE À JOUR: utilisez Dependabot - https://dependabot.com/docker/

BLUF: trouver le bon point d'insertion pour surveiller les modifications apportées à un conteneur est le défi. Ce serait formidable si DockerHub pouvait résoudre ce problème. (Les liens de référentiel ont été mentionnés mais notez lors de leur configuration sur DockerHub - "Déclenchez une génération dans ce référentiel chaque fois que l'image de base est mise à jour sur Docker Hub. Ne fonctionne que pour les images non officielles." )

En essayant de résoudre ce problème moi-même, j'ai vu plusieurs recommandations pour les webhooks, je voulais donc élaborer sur quelques solutions que j'ai utilisées.

  1. Utilisez microbadger.com pour suivre les changements dans un conteneur et utilisez sa fonction de webhook de notification pour déclencher une action. J'ai configuré cela avec zapier.com (mais vous pouvez utiliser n'importe quel service de webhook personnalisable) pour créer un nouveau problème dans mon référentiel github qui utilise Alpine comme image de base.

    • Avantages: Vous pouvez consulter les modifications signalées par microbadger dans github avant de prendre des mesures.
    • Inconvénients: Microbadger ne vous permet pas de suivre une balise spécifique. On dirait qu'il ne suit que les «derniers».
  2. Suivez le flux RSS pour que git s'engage dans un conteneur en amont. ex. https://github.com/gliderlabs/docker-alpine/commits/rootfs/library-3.8/x86_64 . J'ai utilisé zapier.com pour surveiller ce flux et pour déclencher une construction automatique de mon conteneur dans Travis-CI chaque fois que quelque chose est commis. C'est un peu extrême mais vous pouvez changer le déclencheur pour faire d'autres choses comme ouvrir un problème dans votre référentiel git pour une intervention manuelle.

    • Avantages: Plus proche d'une ligne automatisée. La construction Travis-CI vérifie simplement si votre conteneur a des problèmes avec tout ce qui a été validé dans le référentiel d'images de base. C'est à vous de décider si votre service CI prend d'autres mesures.
    • Inconvénients: le suivi du flux de validation n'est pas parfait. Beaucoup de choses sont validées dans le référentiel qui n'affectent pas la construction de l'image de base. Ne prend pas en compte les problèmes de fréquence / nombre de validations et de limitation de l'API.
2 piles
la source
3

Prémisse à ma réponse:

  1. Les conteneurs sont exécutés avec des balises.
  2. La même balise peut être pointée vers une UUID d'image différente à notre guise.
  3. Les mises à jour effectuées sur une image peuvent être validées dans une nouvelle couche d'image

Approche

  1. Créez tous les conteneurs en premier lieu avec un script de mise à jour des correctifs de sécurité
  2. Créez un processus automatisé pour les éléments suivants
    • Exécuter une image existante vers un nouveau conteneur avec un script de correctif de sécurité comme commande
    • Validez les modifications de l'image comme
      • tag existant -> suivi du redémarrage des conteneurs un par un
      • nouvelle balise de version -> remplacer quelques conteneurs par une nouvelle balise -> valider -> déplacer tous les conteneurs vers une nouvelle balise

De plus, l'image de base peut être mise à niveau / le conteneur avec une nouvelle image de base complète peut être construit à intervalles réguliers, si le responsable le juge nécessaire

Les avantages

  1. Nous conservons l'ancienne version de l'image lors de la création de la nouvelle image corrigée de sécurité, nous pouvons donc revenir à l'image en cours d'exécution si nécessaire
  2. Nous préservons le cache docker, donc moins de transfert réseau (seule la couche modifiée est connectée)
  3. Le processus de mise à niveau peut être validé en staging avant de passer à prod
  4. Cela peut être un processus contrôlé, par conséquent, les correctifs de sécurité ne peuvent être poussés que lorsque cela est nécessaire / jugé important.
Phani
la source
Dans un environnement de production, bien qu'il s'agisse de mises à jour de sécurité, je doute que vous souhaitiez des mises à jour sans surveillance! Si des mises à jour sans assistance sont nécessaires, le processus peut être exécuté à intervalles réguliers (le cas échéant) en tant que tâche cron.
Phani
1
Ma prémisse est que les mises à jour de sécurité doivent provenir d'images en amont / de base.
hbogert
@hbogert Je dirais plutôt qu'il y a une fine ligne de différenciation entre la théorie et la pratique. Lorsque les choses se concrétiseront, de nombreux aspects externes devront être pris en compte, comme: le coût (non seulement la valeur monétaire, mais aussi le temps) associé à la mise en œuvre.
Phani
3

Les réponses ci-dessus sont également correctes

Il existe deux approches

  1. Utiliser des webhooks
  2. Exécutez un script pour chaque minute spécifique pour obtenir une nouvelle image d'images Docker

Je ne fais que partager le script, cela peut vous être utile! Vous pouvez l'utiliser avec cronjob, j'ai essayé avec succès sur 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

Voici mon fichier 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
la source
3

Voici un moyen le plus simple de mettre à jour automatiquement le conteneur Docker

Mettez le travail via $ crontab -e:

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

Créer dir ~/.dockeravec fichier 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
la source
0

avez-vous essayé ceci: https://github.com/v2tec/watchtower . c'est un outil simple fonctionnant dans un conteneur docker en regardant d'autres conteneurs, si leur image de base a changé, il sera tiré et redéployé.

linehrr
la source
-1

Une solution simple et excellente est berger

user672009
la source
iiuc, cela n'aide pas au sens général, car il est couplé à Swarm et ne redémarre qu'en amont, alors que nous voulons réagir, reconstruire, etc. sur les changements en amont et non pas simplement redémarrer.
hbogert du
Cela ressemble à quelque chose que vous devriez faire dans un pipeline CI
user672009