Cómo actualizar automáticamente sus contenedores acoplables, si las imágenes base se actualizan


206

Digamos que tengo un contenedor trivial basado en el ubuntu:latest. Ahora hay una actualización de seguridad y ubuntu:latestse actualiza en el repositorio de Docker.

  1. ¿Cómo sabría si mi imagen local y sus contenedores se están quedando atrás?

  2. ¿Existe alguna práctica recomendada para actualizar automáticamente las imágenes y los contenedores locales para seguir las actualizaciones del repositorio de Docker, que en la práctica le brindarían las mismas ventajas de tener actualizaciones desatendidas ejecutándose en una máquina ubuntu convencional?


11
Estoy buscando una respuesta a esto desde el comienzo de Docker. Es incluso un poco más complicado. Si instalo apache (por ejemplo) y eso se actualiza, la imagen base no cambia, ya que la instalé después. Todavía me gustaría tener actualizaciones automáticas para apache. De hecho, me pregunté en el IRC de esto y tengo "seguir aguas arriba y reconstruir sobre las actualizaciones" como una respuesta ...
Mathias

8
Me alegro de no ser el único que se pregunta. Parece que el desarrollo y la reproducibilidad son más importantes para los desarrolladores de Docker que los mecanismos de actualización sensibles que hemos tenido durante años.
hbogert

El problema es que Docker es solo la tecnología para los contenedores. Creo que se necesita algo de tiempo para que un ecosistema evolucione en torno a eso. Hay otros problemas que Docker no aborda como el registro.
Mathias

3
Gracias a todos los que contestaron. Lo siento, no pude dividir la recompensa. Aunque no hubo una solución final a mi problema, hubo una buena aportación de todos ustedes.
Mathias

1
Para @Mathias, la solución que acabo de agregar tiene un script que buscará actualizaciones de seguridad para los paquetes instalados en el contenedor después de la extracción. También tiene un script separado para verificar la imagen base.
Fmstrat

Respuestas:


9

Una de las formas de hacerlo es conducir esto a través de sus sistemas CI / CD. Una vez que se construye su imagen principal, tenga algo que escanee sus repositorios de git en busca de imágenes usando ese padre. Si se encuentra, enviaría una solicitud de extracción para pasar a nuevas versiones de la imagen. La solicitud de extracción, si se superan todas las pruebas, se fusionaría y tendría una nueva imagen secundaria basada en el elemento primario actualizado. Un ejemplo de una herramienta que adopta este enfoque se puede encontrar aquí: https://engineering.salesforce.com/open-sourcing-dockerfile-image-update-6400121c1a75 .

Si no controla su imagen principal, como sería el caso si depende de la ubuntuimagen oficial , puede escribir algunas herramientas que detecten cambios en la etiqueta o suma de verificación de la imagen principal (no es lo mismo, las etiquetas son mutables) y invocar compilaciones de imágenes secundarias en consecuencia.


Wow, este es un gran martillo, dicho eso: desde el momento en que hice esta pregunta, también me di cuenta de que el servidor de compilación es el lugar para abordar este problema. Me alegra ver algunas herramientas. Si explica su enfoque en conceptos genéricos (y no su herramienta / implementación exacta) y lo incluye en la respuesta, probablemente lo acepte.
hbogert

Gracias @hbogert Edité lo anterior y también incluyo una idea sobre qué hacer si se trata de imágenes públicas
Ma3oxuct

124

Usamos un script que verifica si un contenedor en ejecución se inicia con la última imagen. También utilizamos secuencias de comandos de inicio para iniciar la imagen del acoplador.

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

Y init parece

docker run -t -i --name $NAME $im /bin/bash

1
Muchas gracias por esta valiosa contribución. Esta parece ser una buena manera de actualizar la imagen base. La pregunta restante es, ¿cómo actualiza una aplicación (como apache) que fue instalada por la distribución en el dockerfile? ¿O solo usa imágenes base listas para usar que solo necesitan su código de aplicación (como un sitio web)?
Mathias

Utilizamos packer y puppet para configurar nuestras imágenes. Nuestras imágenes están listas para ser producidas después de su creación
bsuttor

@Mathias, vea mi respuesta editada Tengo una pequeña herramienta acoplable que estoy usando para actualizar los paquetes de Linux (actualmente debian / ubuntu) en todos los contenedores en ejecución.
iTech

3
Si una imagen tiene el mismo nombre que un contenedor (por ejemplo redis), LATEST=`docker inspect --format "{{.Id}}" $IMAGE`obtendrá la información del contenedor. Añadir --type imagepara arreglar esto.
Patrick Fisher

1
Gracias por tu publicación Lo modifiqué para envolver todo dentro de un bucle para obtener imágenes de la ventana acoplable: for IMAGE in $(docker ps --format {{.Image}} -q | sort -u)
Armand

25

Una 'forma de docker' sería utilizar las compilaciones automatizadas de docker hub . La función Enlaces de repositorio reconstruirá su contenedor cuando se reconstruya un contenedor ascendente, y la función Webhooks le enviará una notificación.

Parece que los webhooks están limitados a llamadas HTTP POST. Tendría que configurar un servicio para atraparlos, o tal vez usar uno de los servicios POST para enviar por correo electrónico.

No lo he investigado, pero el nuevo Docker Universal Control Plane podría tener una función para detectar contenedores actualizados y volver a implementarlos.


Tuve que crear un webhook para el servicio AMQP: github.com/goliatone/rabbithook
goliatone

Lamentablemente, los activadores ascendentes ya no están disponibles: github.com/docker/hub-feedback/issues/1717 .
Julien Chastang

23

Puede usar Watchtower para ver las actualizaciones de la imagen de la que se crea una instancia de un contenedor y extraer automáticamente la actualización y reiniciar el contenedor utilizando la imagen actualizada. Sin embargo, eso no resuelve el problema de reconstruir sus propias imágenes personalizadas cuando hay un cambio en la imagen ascendente en la que se basa. Podría ver esto como un problema de dos partes: (1) saber cuándo se ha actualizado una imagen ascendente y (2) hacer la reconstrucción de la imagen real. (1) se puede resolver con bastante facilidad, pero (2) depende mucho de su entorno de construcción local / prácticas, por lo que probablemente sea mucho más difícil crear una solución generalizada para eso.

Si puede usar las compilaciones automatizadas de Docker Hub , todo el problema se puede resolver de manera relativamente limpia utilizando la función de enlaces del repositorio , que le permite activar una reconstrucción automáticamente cuando se actualiza un repositorio vinculado (probablemente uno ascendente). También puede configurar un webhook para que le notifique cuando se produce una compilación automática. Si desea una notificación por correo electrónico o SMS, puede conectar el webhook a IFTTT Maker . Encontré que la interfaz de usuario de IFTTT es un poco confusa, pero configuraría el webhook de Docker para publicar en https://maker.ifttt.com/trigger/docker_xyz_image_built / with / key / your_key.

Si necesita construir localmente, al menos puede resolver el problema de recibir notificaciones cuando se actualiza una imagen ascendente creando un repositorio ficticio en Docker Hub vinculado a su (s) repositorio (s) de interés. El único propósito del repositorio ficticio sería activar un webhook cuando se reconstruya (lo que implica que se actualizó uno de sus repositorios vinculados). Si puede recibir este webhook, incluso podría usarlo para activar una reconstrucción de su lado.


1
Sin embargo, la Watchtower usa el zócalo del acoplador. Desde una perspectiva de seguridad que está dando acceso de root a la máquina host.
JoeG

1
Además, Watchtower no parece poder actualizar imágenes de repositorios privados que no sean Docker Hub. Un fastidio para nosotros que usamos Azure.
Thomas Eyde

1
Puede usar registros privados usando REPO_USERy REPO_PASSvariables de entorno. Eche un vistazo a readme.md de Watchtower para obtener más información: github.com/v2tec/watchtower#usage
Alejandro Nortes

2
Aviso: la torre de vigilancia es abandonada por su responsable y la imagen en DockerHub ni siquiera está actualizada con la de github.
XanderStrike

El repositorio de la Watchtower parece haberse migrado a containerrrr / watchtower . Y hay algunos problemas con las compilaciones automatizadas vinculadas en Dockerhub, como lo señala esta respuesta en una pregunta similar .
chrki

10

Tuve el mismo problema y pensé que puede resolverse simplemente con un trabajo cron que llama unattended-upgradediariamente.

Mi intención es tener esto como una solución automática y rápida para garantizar que el contenedor de producción sea seguro y actualizado porque me puede llevar algún tiempo actualizar mis imágenes e implementar una nueva imagen acoplable con las últimas actualizaciones de seguridad.

También es posible automatizar la creación e implementación de imágenes con ganchos Github

He creado una imagen básica de docker con la que comprueba e instala automáticamente actualizaciones de seguridad a diario (puede ejecutarse directamente docker run itech/docker-unattended-upgrade).

También me encontré con otro enfoque diferente para verificar si el contenedor necesita una actualización.

Mi implementación 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

Guiones de ayuda

Instalar en pc

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

comienzo

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

Desarrollé una pequeña herramienta docker-run que se ejecuta como contenedor de docker y se puede usar para actualizar paquetes dentro de todos o contenedores de ejecución seleccionados, también se puede usar para ejecutar comandos arbitrarios.

Se puede probar fácilmente con el siguiente comando:

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

que por defecto se ejecutará datecomandos en todos los contenedores que se ejecutan y mostrar los resultados. Si pasa en su updatelugar exec, se ejecutará apt-get updateseguido de apt-get upgrade -ytodos los contenedores en ejecución


mi referencia a la actualización desatendida fue solo para mostrar la analogía en un entorno no acoplable. Mi intención es resolver esto de la manera acoplable (si existe). Tener un proceso adicional en un contenedor supera el propósito de Docker IMO. Resuelve el problema de la demora entre la actualización de su imagen y usted, el usuario, en realidad la despoja sobre su contenedor actual. Aunque esto también puede llevar hasta 1 día con actualizaciones desatendidas, así que ... La referencia de github no es satisfactoria, porque el mecanismo de actualización ahora depende en gran medida del sistema operativo host.
hbogert

El "modo acoplable" no le impide ejecutar otros procesos en el mismo contenedor si están estrechamente relacionados y no crearán un cuello de botella de escalabilidad. Y este caso de uso en particular es un buen ejemplo de cuándo puede tener un contenedor con otro proceso en ejecución. (por ejemplo, vea la imagen de gitlab ya que ejecuta múltiples procesos obligatorios en el mismo contenedor).
iTech

No llamaría a un mecanismo de actualización estrechamente relacionado con la función principal de una imagen. Esta solución es como dar a cada aplicación en una máquina convencional su propio mecanismo de actualización en lugar de colocar la carga en un administrador de paquetes. Aunque es una solución, no responde a mi pregunta que es, actualizar automáticamente las imágenes locales y luego, los contenedores deben volverse a ejecutar. Con la actualización en los contenedores mismos, estamos introduciendo nuevamente una gran cantidad de estados de los que no tenemos idea, lo cual está en contra de la forma de la ventana acoplable (nuevamente en mi humilde opinión).
hbogert

1
Es posible que necesite algo de más alto nivel que Docker, como lo Kubernetesque es útil para la implementación de grandes infraestructuras, pero Google todavía lo está desarrollando intensamente. Por el momento, puede automatizar esto con una herramienta de aprovisionamiento como Ansible de una manera bastante simple.
iTech

Su "enfoque diferente" citado podría ser lo que estaba buscando. Su propia contribución parece una alternativa viable para "contenedores de grasa". Definitivamente voy a investigar un poco más, gracias por su respuesta.
Mathias

7

No sabría que su contenedor está detrás sin ejecutar la extracción de la ventana acoplable . Entonces necesitarías reconstruir o recomponer tu imagen.

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

Los comandos se pueden colocar en un script junto con cualquier otra cosa necesaria para completar la actualización, aunque un contenedor adecuado no necesitaría nada adicional.


1: ok, pero luego tendría que mirar todas mis imágenes locales, obtener sus imágenes base, extraerlas. Luego reconstruya las imágenes cuyas imágenes base han cambiado. Luego detenga los contenedores cuya imagen se cambia y vuelva a crear los contenedores con 'docker run' y los parámetros necesarios. Esto parece demasiado manual. Pero si este es el status quo, entonces aceptaré la respuesta.
hbogert

Por favor espere antes de aceptar. Tal vez hay algo por ahí. He estado usando Docker durante 6 meses, pero no he estado al día con los últimos desarrollos.
seanmcl

De alguna manera, internamente, Docker puede comparar imágenes para realizar su capacidad de "almacenamiento en caché". Quizás pueda encontrar una manera de aprovechar ESO. En otras palabras, verifique si las imágenes subyacentes (hasta la base) han cambiado y luego active un proceso de reconstrucción. Desafortunadamente, el almacenamiento en caché no lo ayudará en ese caso: la imagen completa se reconstruirá porque la imagen base ha cambiado.
Thom Parkin

5

La gestión de dependencias para las imágenes de Docker es un problema real. Soy parte de un equipo que creó una herramienta, MicroBadger , para ayudar con esto al monitorear las imágenes del contenedor e inspeccionar los metadatos. Una de sus características es permitirle configurar un webhook de notificación que se llama cuando cambia una imagen que le interesa (por ejemplo, una imagen base).


5

Aquí hay muchas respuestas, pero ninguna de ellas satisfizo mis necesidades. Quería una respuesta real a la pregunta número 1 del autor de la pregunta. ¿Cómo sé cuándo se actualiza una imagen en hub.docker.com?

El siguiente script se puede ejecutar a diario. En la primera ejecución, obtiene una línea base de las etiquetas y las fechas de actualización del registro HUB y las guarda localmente. A partir de ese momento, cada vez que se ejecuta, comprueba el registro en busca de nuevas etiquetas y fechas de actualización. Como esto cambia cada vez que existe una nueva imagen, nos dice si la imagen base ha cambiado. Aquí está el guión:

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

Deberá modificar la DATAPATHvariable en la parte superior y modificar el comando de notificación por correo electrónico al final para satisfacer sus necesidades. Para mí, lo tengo SSH en un servidor en otra red donde se encuentra mi SMTP. Pero también podría usar el mailcomando fácilmente .

Ahora, también desea verificar si hay paquetes actualizados dentro de los contenedores. En realidad, esto es probablemente más efectivo que hacer una "extracción" una vez que sus contenedores están funcionando. Aquí está el guión para lograrlo:

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

1
mkdir en el primer script probablemente debería ser: mkdir -p Además, el primer script compara VAR1 con VAR2, suponga que debería comparar OLD con NEW. Sin embargo, si es cierto, esto significa que este script realmente no hará lo que OP quiere, A MENOS QUE se haya ejecutado por primera vez en el momento de la instalación. Eso es, en realidad no es nada acerca de la determinación de lo que está instalado, solo si los resultados difieren de ejecuciones anteriores ...
JoeG

5

Otro enfoque podría ser asumir que su imagen base se queda atrás bastante rápido (y es muy probable que eso suceda), y forzar periódicamente la creación de otra imagen de su aplicación (por ejemplo, cada semana) y luego volver a implementarla si ha cambiado.

Por lo que puedo decir, las imágenes base populares como Debian o Java oficiales actualizan sus etiquetas para satisfacer las correcciones de seguridad, por lo que las etiquetas no son inmutables (si desea una garantía más sólida de eso, debe usar la referencia [imagen: @digest ], disponible en versiones más recientes de Docker). Por lo tanto, si tuviera que construir su imagen con docker build --pull , entonces su aplicación debería obtener la última y mejor etiqueta de imagen base a la que hace referencia.

Dado que las etiquetas mutables pueden ser confusas, es mejor incrementar el número de versión de su aplicación cada vez que lo hace para que al menos las cosas estén más limpias.

Por lo tanto, no estoy seguro de que el script sugerido en una de las respuestas anteriores haga el trabajo, ya que no reconstruye la imagen de su aplicación, solo actualiza la etiqueta de la imagen base y luego reinicia el contenedor, pero el nuevo contenedor aún hace referencia el viejo hash de imagen base.

No recomendaría ejecutar trabajos de tipo cron en contenedores (o cualquier otro proceso, a menos que sea realmente necesario), ya que esto va en contra del mantra de ejecutar solo un proceso por contenedor (hay varios argumentos sobre por qué esto es mejor, así que ' No voy a entrar aquí).


4

No voy a entrar en la cuestión de si desea o no actualizaciones desatendidas en producción (creo que no). Solo dejo esto aquí como referencia en caso de que alguien lo encuentre útil. Actualice todas sus imágenes de Docker a la última versión con el siguiente comando en su terminal:

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


1
El comando es útil para actualizar todas las imágenes, pero no cambia nada que se ejecute en producción. Los contenedores aún provienen de las imágenes antiguas, que ahora están sin etiquetar.
Ninguno

Cierto. Y aquí hay uno más para los libros ... Úselo # docker system prune -a --volumes -fpara limpiar imágenes antiguas (colgantes), volúmenes, etc.
Meferdati

4

ACTUALIZACIÓN: Use Dependabot - https://dependabot.com/docker/

BLUF: encontrar el punto de inserción correcto para monitorear los cambios en un contenedor es el desafío. Sería genial si DockerHub resolviera esto. (Se han mencionado enlaces de repositorio, pero tenga en cuenta al configurarlos en DockerHub: " Dispare una compilación en este repositorio siempre que la imagen base se actualice en Docker Hub. Solo funciona para imágenes no oficiales" ).

Mientras intentaba resolver esto por mí mismo, vi varias recomendaciones para webhooks, así que quise elaborar un par de soluciones que he usado.

  1. Use microbadger.com para rastrear los cambios en un contenedor y use su función de notificación de webhook para activar una acción. Configuré esto con zapier.com (pero puedes usar cualquier servicio de webhook personalizable) para crear un nuevo problema en mi repositorio de github que usa Alpine como imagen base.

    • Pros: puede revisar los cambios informados por microbadger en github antes de tomar medidas.
    • Contras: Microbadger no te permite rastrear una etiqueta específica. Parece que solo rastrea 'lo último'.
  2. Rastree la fuente RSS para git commits a un contenedor ascendente. ex. https://github.com/gliderlabs/docker-alpine/commits/rootfs/library-3.8/x86_64 . Utilicé zapier.com para monitorear este feed y activar una compilación automática de mi contenedor en Travis-CI cada vez que algo se confirma. Esto es un poco extremo, pero puede cambiar el gatillo para hacer otras cosas como abrir un problema en su repositorio de git para la intervención manual.

    • Pros: más cerca de una tubería automatizada. La compilación de Travis-CI solo comprueba si su contenedor tiene problemas con lo que se haya comprometido con el repositorio de imágenes base. Depende de usted si su servicio de CI toma alguna medida adicional.
    • Contras: el seguimiento del feed de confirmación no es perfecto. Muchas cosas se comprometen con el repositorio que no afectan la construcción de la imagen base. No tiene en cuenta ningún problema con la frecuencia / número de confirmaciones y cualquier limitación de API.

3

Premisa a mi respuesta:

  1. Los contenedores se ejecutan con etiquetas.
  2. La misma etiqueta puede apuntar a un UUID de imagen diferente, según nos parezca apropiado.
  3. Las actualizaciones realizadas en una imagen pueden confirmarse en una nueva capa de imagen

Acercarse

  1. Cree todos los contenedores en primer lugar con un script de actualización de parche de seguridad
  2. Cree un proceso automatizado para lo siguiente
    • Ejecute una imagen existente en un nuevo contenedor con un script de parche de seguridad como comando
    • Confirmar cambios en la imagen como
      • etiqueta existente -> seguido de reiniciar los contenedores uno por uno
      • nueva etiqueta de versión -> reemplazar algunos contenedores con nueva etiqueta -> validar -> mover todos los contenedores a una nueva etiqueta

Además, la imagen base se puede actualizar / el contenedor con una nueva imagen base completa se puede construir a intervalos regulares, según el mantenedor lo considere necesario

Ventajas

  1. Estamos preservando la versión anterior de la imagen mientras creamos la nueva imagen parcheada de seguridad, por lo tanto, podemos volver a la imagen anterior si es necesario
  2. Estamos preservando el caché de la ventana acoplable, por lo tanto, menos transferencia de red (solo la capa cambiada se conecta al cable)
  3. El proceso de actualización se puede validar en etapas antes de pasar a producción
  4. Este puede ser un proceso controlado, por lo tanto, los parches de seguridad solo cuando son necesarios / se consideran importantes pueden ser empujados.

En un entorno de producción, aunque son actualizaciones de seguridad, ¡dudo que desee tener actualizaciones desatendidas! Si es necesario tener actualizaciones desatendidas, el proceso se puede ejecutar a intervalos regulares (según corresponda) como un trabajo cron.
Phani

1
Mi premisa es que las actualizaciones de seguridad deben provenir de imágenes ascendentes / base.
hbogert

@hbogert Prefiero decir que hay una fina línea de diferenciación entre teoría y práctica. Cuando las cosas entren en práctica, habrá muchos aspectos externos que deben tenerse en cuenta, como: el costo (no solo el valor en dólares, sino también el tiempo) asociados con la implementación.
Phani

3

Las respuestas anteriores también son correctas

Hay dos enfoques

  1. Usa webhooks
  2. Ejecute el script por cada minuto específico para obtener nuevas imágenes de las ventanas acoplables

Solo estoy compartiendo script, ¡puede ser útil para usted! Puedes usarlo con cronjob, lo intenté con éxito en 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

Aquí está mi archivo 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

3

Aquí hay una manera más simple de actualizar el contenedor de Docker automáticamente

Pon el trabajo a través de $ crontab -e:

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

Crear directorio ~/.dockercon archivo 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


-1

Una solución simple y excelente es Shepherd


iiuc, esto no ayuda en el sentido general, porque esto está acoplado a Swarm y solo reinicia en sentido ascendente, mientras que queremos reaccionar, reconstruir, etc. en los cambios en sentido ascendente y no simplemente reiniciar.
hbogert

Eso suena como algo que debería hacer en una tubería de CI
usuario672009
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.