Как автоматически обновлять ваши док-контейнеры, если обновляются базовые образы

206

Скажем, у меня есть тривиальный контейнер на основе ubuntu:latest. Теперь есть обновление безопасности и ubuntu:latestоно обновляется в репозитории Docker.

  1. Откуда мне знать, что мой локальный образ и его контейнеры работают позади?

  2. Есть ли некоторые рекомендации по автоматическому обновлению локальных образов и контейнеров в соответствии с обновлениями хранилища Docker, которые на практике дадут вам те же тонкости, что и автоматические обновления, запущенные на обычной машине с Ubuntu?

hbogert
источник
11
Я ищу ответ на это с самого начала докера. Это даже немного сложнее. Если я устанавливаю apache (например) и он обновляется, базовый образ не меняется, так как я установил его позже. Я все еще хотел бы иметь автообновления для Apache. На самом деле я спросил об этом в IRC и получил «следить за обновлениями и перестраивать обновления» в качестве ответа ...
Матиас
8
Рад, что я не единственный, кому интересно. Кажется, что разработка и воспроизводимость более важны для разработчиков докеров, чем разумных механизмов обновления, которые мы использовали уже много лет.
hbogert
Проблема в том, что докер - это просто технология для контейнеров. Я думаю, что для развития экосистемы требуется некоторое время. Существуют и другие проблемы, которые Docker не решает, например, регистрация.
Матиас
3
Спасибо всем, кто ответил. Извините, я не смог разделить награду. Несмотря на то, что не было окончательного решения моей проблемы, все вы получили хороший вклад.
Матиас
1
Для @Mathias в только что добавленном решении есть скрипт, который будет проверять наличие обновлений безопасности для пакетов, установленных в контейнере post-pull. Также имеется отдельный скрипт для проверки базового изображения.
Fmstrat

Ответы:

9

Один из способов сделать это - провести через систему CI / CD. Как только ваше родительское изображение будет создано, сделайте что-то, что сканирует ваши git-репозитории на изображения с использованием этого родителя. Если он найден, вы бы отправили запрос на удаление новых версий изображения. Запрос на включение, если все тесты пройдены, будет объединен, и у вас будет новое дочернее изображение на основе обновленного родительского. Пример инструмента, который использует этот подход, можно найти здесь: https://engineering.salesforce.com/open-sourcing-dockerfile-image-update-6400121c1a75 .

Если вы не управляете своим родительским изображением, как в случае, если вы зависите от официального ubuntuизображения, вы можете написать некоторые инструменты, которые обнаруживают изменения в теге родительского изображения или контрольной сумме (не то же самое, теги являются изменяемыми) и вызвать детей образы строит соответственно.

Ma3oxuct
источник
Вау, это большой молоток, который сказал: со времени, когда я задал этот вопрос, я также пришел к выводу, что сервер сборки является местом для решения этой проблемы. Я рад видеть некоторые инструменты. Если вы объясните свой подход в общих понятиях (а не в точном инструменте / реализации) и включите его в ответ, я, вероятно, приму его.
hbogert
Спасибо @hbogert. Я отредактировал вышеприведенное, а также включил идею о том, что делать, если вы имеете дело с общедоступными изображениями
Ma3oxuct
124

Мы используем скрипт, который проверяет, запущен ли запущенный контейнер с самым последним образом. Мы также используем сценарии инициализации upstart для запуска образа докера.

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

И init выглядит так

docker run -t -i --name $NAME $im /bin/bash
bsuttor
источник
1
Большое спасибо за этот ценный вклад. Это похоже на хороший способ обновить базовое изображение. Остается вопрос, как обновить приложение (например, apache), которое было установлено дистрибутивом в файле dockerfile? Или вы используете только готовые базовые изображения, для которых нужен только код приложения (например, веб-сайт)?
Матиас
Мы используем упаковщик и марионетку для настройки наших изображений. Наши изображения готовы к производству после их создания
bsuttor
@Mathias, посмотрите мой отредактированный ответ. У меня есть крошечный инструмент для запуска Docker, который я использую для обновления пакетов linux (в настоящее время debian / ubuntu) во всех запущенных контейнерах.
iTech
3
Если изображение имеет то же имя, что и контейнер (например redis), LATEST=`docker inspect --format "{{.Id}}" $IMAGE`получит информацию о контейнере. Добавьте, --type imageчтобы исправить это.
Патрик Фишер
1
Спасибо за ваш пост. Я изменил его, чтобы обернуть все это внутри цикла для получения изображений из докера: for IMAGE in $(docker ps --format {{.Image}} -q | sort -u)
Armand
25

«Способ docker» - использовать автоматические сборки Docker Hub . Функция Repository Links перестроит ваш контейнер при перестроении вышестоящего контейнера, а функция Webhooks отправит вам уведомление.

Похоже, что веб-хуки ограничены вызовами HTTP POST. Вам нужно настроить службу, чтобы поймать их, или, возможно, использовать один из POST для отправки услуг электронной почты там.

Я не рассматривал это, но новая универсальная плоскость управления Docker может иметь функцию обнаружения обновленных контейнеров и повторного развертывания.

ТАКСИ
источник
Мне пришлось создать веб-крючок для службы AMQP: github.com/goliatone/rabbithook
goliatone
К сожалению, вышестоящие триггеры больше не доступны: github.com/docker/hub-feedback/issues/1717 .
Жюльен Частанг
23

Вы можете использовать Сторожевую башню, чтобы следить за обновлениями образа, из которого создается контейнер, и автоматически извлекать обновление и перезапускать контейнер, используя обновленное изображение. Однако это не решает проблему перестройки ваших собственных пользовательских изображений, когда есть изменения в исходном изображении, на котором оно основано. Вы можете рассматривать это как проблему, состоящую из двух частей: (1) знание того, когда вышестоящий образ был обновлен, и (2) выполнение фактического восстановления образа. (1) может быть решено довольно легко, но (2) во многом зависит от вашей локальной среды / практики сборки, поэтому, вероятно, гораздо сложнее создать обобщенное решение для этого.

Если вы можете использовать автоматические сборки Docker Hub , вся проблема может быть решена относительно чисто с помощью функции ссылок на репозиторий , которая позволяет автоматически запускать перестройку при обновлении связанного репозитория (возможно, вышестоящего). Вы также можете настроить webhook, чтобы уведомлять вас, когда происходит автоматическая сборка. Если вам нужно уведомление по электронной почте или SMS, вы можете подключить веб-крючок к IFTTT Maker . Я нахожу, что пользовательский интерфейс IFTTT немного сбивает с толку, но вы должны настроить веб-крючок Docker для публикации на https://maker.ifttt.com/trigger/docker_xyz_image_built / с / key / your_key.

Если вам необходимо выполнить локальную сборку, вы можете, по крайней мере, решить проблему получения уведомлений при обновлении исходного изображения, создав фиктивное репо в Docker Hub, связанное с интересующими вас репозиториями. Единственная цель фиктивного репо состоит в том, чтобы вызвать веб-крючок, когда он будет перестроен (что означает, что одно из связанных с ним репо было обновлено). Если вы можете получить этот веб-крючок, вы можете даже использовать его, чтобы вызвать перестройку на своей стороне.

jjlin
источник
1
Сторожевая башня использует док-разъем, хотя. С точки зрения безопасности, который предоставляет корневой доступ к хост-машине.
JoeG
1
Кроме того, Сторожевая башня не может обновлять изображения из частных репозиториев, кроме Docker Hub. Облом для нас, кто использует Azure.
Томас Эйд
1
Вы можете использовать частные реестры, используя REPO_USERи REPO_PASSпеременные окружения. Посмотрите readme.md из Сторожевой башни для получения дополнительной информации: github.com/v2tec/watchtower#usage
Алехандро Нортес
2
Слухи о предупреждении, сторожевая башня заброшена сопровождающим, а изображение в DockerHub даже не совпадает с изображением в github.
XanderStrike
Похоже, что репозиторий Сторожевой башни перенесен в containerrr / watchtower . И есть некоторые проблемы со связанными автоматическими сборками на Dockerhub, как указано в этом ответе на аналогичный вопрос .
чрки
10

У меня возникла та же проблема, и я подумал, что ее можно просто решить, unattended-upgradeежедневно звоня на работу cron .

Я намерен использовать это в качестве автоматического и быстрого решения для обеспечения безопасности и обновления производственного контейнера, поскольку мне может потребоваться некоторое время, чтобы обновить мои образы и развернуть новый образ докера с последними обновлениями безопасности.

Также возможно автоматизировать сборку и развертывание образа с помощью хитов Github.

Я создал базовый образ докера, который автоматически проверяет и устанавливает обновления безопасности ежедневно (может запускаться напрямую docker run itech/docker-unattended-upgrade).

Я также столкнулся с другим подходом, чтобы проверить, нуждается ли контейнер в обновлении.

Моя полная реализация:

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

Вспомогательные скрипты

устанавливать

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

Начало

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

редактировать

Я разработал небольшой инструмент docker-run, который запускается как докер-контейнер и может использоваться для обновления пакетов внутри всех или выбранных запущенных контейнеров, а также для запуска любых произвольных команд.

Может быть легко проверено с помощью следующей команды:

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

который по умолчанию выполнит dateкоманду во всех запущенных контейнерах и отобразит результаты. Если вы передадите updateвместо execнего, будет выполняться apt-get updateпосле apt-get upgrade -yво всех запущенных контейнерах

ITech
источник
моя ссылка на unattended-upgrade состояла лишь в том, чтобы показать аналогию в среде без докера. Мое намерение состоит в том, чтобы решить эту проблему способом докера (если таковой существует). Наличие дополнительного процесса в контейнере превосходит цель докера imo. Это исправляет проблему задержки между обновлением своего образа в восходящем направлении и тем, что вы, пользователь, фактически размещаете его поверх текущего контейнера. Хотя это может занять до 1 дня с автоматическим обновлением, так что ... Также ссылка на github не является удовлетворительной, потому что механизм обновления теперь сильно зависит от операционной системы хоста.
hbogert
«Путь к докеру» не мешает запускать другие процессы в том же контейнере, если они тесно связаны, и не создает узких мест для масштабируемости. И этот конкретный пример использования является хорошим примером того, когда у вас может быть контейнер с другим запущенным процессом. (например, смотрите изображение для gitlab, так как он запускает несколько обязательных процессов в одном и том же контейнере).
iTech
Я бы не назвал механизм обновления тесно связанным с основной функцией изображения. Это решение похоже на предоставление каждому приложению на обычной машине собственного механизма обновления вместо того, чтобы обременять менеджера пакетов. Хотя это решение, оно не отвечает на мой вопрос, который заключается в автоматическом обновлении локальных образов, а затем следует повторно запускать контейнеры. С обновлением в самих контейнерах мы снова вводим много состояний, о которых мы понятия не имеем, что противоречит способу докера (опять же imho).
hbogert
1
Вам может понадобиться что-то более высокого уровня, чем докер, например, Kubernetesчто полезно для развертывания крупных инфраструктур, но Google все еще находится в стадии интенсивной разработки. На данный момент вы можете автоматизировать это с помощью инструмента обеспечения, такого как Ansible, довольно простым способом.
iTech
Ваш цитируемый «другой подход» может быть тем, что я искал. Ваш собственный вклад выглядит как жизнеспособная альтернатива "жировым контейнерам". Я определенно рассмотрю оба вопроса, спасибо за ваш ответ.
Матиас
7

Вы не знали бы, что ваш контейнер позади без запуска Docker Pull . Тогда вам нужно будет восстановить или перекомпоновать ваше изображение.

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

Команды могут быть помещены в сценарий вместе со всем, что необходимо для завершения обновления, хотя для правильного контейнера не потребуется ничего дополнительного.

seanmcl
источник
1: хорошо, но тогда я должен был бы посмотреть на все мои локальные изображения, получить их базовые изображения, вытащить их. Затем восстановите изображения, базовые изображения которых были изменены. Затем остановите контейнеры, изображение которых изменено, и заново создайте контейнеры с «запуском докера» и необходимыми параметрами. Это кажется чрезмерно ручным. Но если это статус-кво, то я приму ответ.
hbogert
Пожалуйста, подождите, прежде чем принять. Может быть, там что-то есть. Я использую докер в течение 6 месяцев, но не следил за последними разработками.
seanmcl
Каким-то образом, внутри Docker может сравнивать изображения для выполнения функции «кэширования». Возможно, вы можете найти способ использовать это. Другими словами, проверьте, изменились ли базовые образы (вплоть до базового), и затем запустите процесс для перестройки. К сожалению, кэширование не поможет вам в этом случае: все изображение будет перестроено, потому что базовое изображение изменилось.
Том Паркин
5

Управление зависимостями для образов Docker является реальной проблемой. Я являюсь частью команды, которая создала инструмент MicroBadger , который поможет с этим, отслеживая изображения контейнеров и проверяя метаданные. Одна из его функций - позволить вам настроить веб-крючок уведомлений, который вызывается при изменении интересующего вас изображения (например, базового изображения).

Лиз Райс
источник
5

Здесь много ответов, но ни один из них не отвечал моим потребностям. Я хотел получить реальный ответ на вопрос аскера № 1. Как узнать, когда изображение обновляется на hub.docker.com?

Приведенный ниже скрипт можно запускать ежедневно. При первом запуске он получает базовую линию тегов и даты обновления из реестра HUB и сохраняет их локально. После этого каждый раз при запуске он проверяет реестр на наличие новых тегов и дат обновления. Поскольку это меняется каждый раз, когда появляется новое изображение, оно сообщает нам, изменилось ли базовое изображение. Вот сценарий:

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

Вы захотите изменить DATAPATHпеременную в верхней части и изменить команду уведомления по электронной почте в конце, чтобы удовлетворить ваши потребности. Для меня это SSH в сервер в другой сети, где мой SMTP расположен. Но вы также можете легко использовать mailкоманду.

Теперь вы также хотите проверить наличие обновленных пакетов внутри самих контейнеров. На самом деле это, вероятно, более эффективно, чем выполнять «вытягивание», когда ваши контейнеры работают. Вот сценарий для этого:

#!/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
источник
1
Вероятно, mkdir в первом сценарии должен быть следующим: mkdir -p Кроме того, первый сценарий сравнивает VAR1 с VAR2, предположим, что следует сравнивать OLD с NEW. Если это правда, это означает, что этот скрипт не будет действительно делать то, что хочет OP, если он не был впервые запущен во время установки. То есть он ничего не определяет относительно того, что установлено, просто если результаты отличаются от предыдущих запусков ...
JoeG
5

Другой подход может заключаться в том, чтобы предположить, что ваш базовый образ отстает довольно быстро (и это очень вероятно), и периодически запускать сборку вашего приложения (например, каждую неделю), а затем повторно развертывать его, если он изменился.

Насколько я могу судить, популярные базовые образы, такие как официальный Debian или Java, обновляют свои теги для исправления ошибок безопасности, поэтому теги не являются неизменяемыми (если вы хотите более надежную гарантию того, что вам нужно использовать ссылку [image: @digest] ], доступно в более поздних версиях Docker). Поэтому, если вы хотите создать свой образ docker build --pull, то ваше приложение должно получить самый последний и самый лучший из тегов базового изображения, на которые вы ссылаетесь.

Поскольку изменяемые теги могут сбивать с толку, лучше увеличивать номер версии вашего приложения каждый раз, когда вы делаете это, чтобы, по крайней мере, с вашей стороны все было чище.

Поэтому я не уверен, что сценарий, предложенный в одном из предыдущих ответов, выполняет свою работу, поскольку он не перестраивает образ вашего приложения - он просто обновляет тег базового изображения, а затем перезапускает контейнер, но новый контейнер по-прежнему ссылается на старый хэш базового изображения.

Я бы не рекомендовал запускать задания типа cron в контейнерах (или любых других процессах, если это действительно не нужно), поскольку это противоречит мантре запуска только одного процесса на контейнер (есть разные аргументы о том, почему это лучше, поэтому я ' Я не собираюсь вдаваться в это здесь).

Богдан
источник
4

Я не буду вдаваться в подробности того, хотите ли вы автоматических обновлений или нет (я думаю, что нет). Я просто оставляю это здесь для справки на случай, если кто-нибудь найдет это полезным. Обновите все ваши образы докеров до последней версии с помощью следующей команды в вашем терминале:

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

Meferdati
источник
1
Команда полезна для обновления всех изображений, но она ничего не меняет, запущенная в производстве. Контейнеры все еще происходят из старых изображений, которые теперь не имеют тегов.
Ни
Правда. И вот еще один для книг ... Используйте # docker system prune -a --volumes -fдля очистки старых (висячих) изображений, томов и т. Д.
Meferdati
4

ОБНОВЛЕНИЕ: используйте Dependabot - https://dependabot.com/docker/

BLUF: найти правильную точку вставки для отслеживания изменений в контейнере - это непростая задача. Было бы здорово, если бы DockerHub решил эту проблему. (Ссылки на репозиторий были упомянуты, но обратите внимание при их настройке в DockerHub - « Запускать сборку в этом репозитории всякий раз, когда базовый образ обновляется в Docker Hub. Работает только для неофициальных образов». )

Пытаясь решить эту проблему самостоятельно, я увидел несколько рекомендаций для веб-зацепок, поэтому я хотел бы остановиться на нескольких решениях, которые я использовал.

  1. Используйте microbadger.com для отслеживания изменений в контейнере и используйте функцию уведомлений для запуска действия. Я настроил это на zapier.com (но вы можете использовать любой настраиваемый сервис webhook), чтобы создать новую проблему в моем репозитории github, которая использует Alpine в качестве базового образа.

    • Плюсы: вы можете просмотреть изменения, о которых сообщил microbadger в github, прежде чем предпринимать какие-либо действия.
    • Минусы: Microbadger не позволяет отслеживать определенный тег. Похоже, он отслеживает только «последние».
  2. Отслеживайте RSS-канал для git коммитов в верхний контейнер. ех. https://github.com/gliderlabs/docker-alpine/commits/rootfs/library-3.8/x86_64 . Я использовал zapier.com для мониторинга этого канала и запуска автоматической сборки моего контейнера в Travis-CI каждый раз, когда что-то совершается. Это немного экстремально, но вы можете изменить триггер, чтобы делать другие вещи, такие как открытие проблемы в вашем git-репозитории для ручного вмешательства.

    • Плюсы: ближе к автоматизированной линии. Сборка Travis-CI просто проверяет, есть ли у вашего контейнера проблемы с тем, что было зафиксировано в хранилище базовых образов. Это зависит от вас, если ваша служба CI предпримет какие-либо дальнейшие действия.
    • Минусы: отслеживание коммитов не идеально. В хранилище добавляется множество вещей, которые не влияют на сборку базового образа. Не учитывает никаких проблем с частотой / количеством коммитов и регулированием API.
2stacks
источник
3

Предпосылка к моему ответу:

  1. Контейнеры запускаются с тегами.
  2. Один и тот же тег может указывать на другой UUID изображения, как нам удобно.
  3. Обновления, сделанные для изображения, могут быть переданы в новый слой изображения

Подходить

  1. Создайте все контейнеры в первую очередь с помощью скрипта обновления патча безопасности
  2. Создайте автоматизированный процесс для следующего
    • Запустите существующий образ в новый контейнер со скриптом исправления безопасности в качестве команды
    • Внесите изменения в изображение как
      • существующий тег -> с последующим перезапуском контейнеров один за другим
      • тег новой версии -> заменить несколько контейнеров новым тегом -> подтвердить -> переместить все контейнеры в новый тег

Кроме того, базовый образ может быть обновлен / контейнер с полным новым базовым образом может быть построен через регулярные промежутки времени, так как сопровождающий считает необходимым

преимущества

  1. Мы сохраняем старую версию образа при создании нового исправленного образа безопасности, поэтому мы можем откатиться к предыдущему рабочему образу при необходимости
  2. Мы сохраняем кэш докера, следовательно, меньше передачи по сети (только измененный слой подключается к сети)
  3. Процесс обновления может быть проверен в стадии подготовки, прежде чем перейти к продукту.
  4. Это может быть контролируемый процесс, поэтому исправления безопасности могут быть применены только тогда, когда это необходимо / считается важным.
Фани
источник
В производственной среде, хотя они и являются обновлениями безопасности, я сомневаюсь, что вы захотите получать автоматические обновления! Если необходимы автоматические обновления, процесс можно запускать через регулярные промежутки времени (при необходимости) как задание cron.
Фани
1
Моя предпосылка заключается в том, что обновления безопасности должны исходить из исходных / базовых образов.
hbogert
@hbogert Я бы сказал, что между теорией и практикой существует тонкая грань различия. Когда все станет на практике, будет много внешних аспектов, которые необходимо учитывать, например: стоимость (не только стоимость в долларах, но и время), связанная с реализацией.
Фани
3

Выше Ответы также верны

Есть два подхода

  1. Используйте веб-крючки
  2. Запускайте сценарий для каждой конкретной минуты, чтобы получить новые изображения Docker.

Я просто делюсь сценарием, может быть, это будет полезно для вас! Вы можете использовать его с cronjob, я успешно попробовал на 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

Вот мой файл 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

Вот самый простой способ автоматического обновления Docker-контейнера.

Поместите работу через $ crontab -e:

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

Создать ~/.dockerкаталог с файлом 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
источник
0

Вы пробовали это: https://github.com/v2tec/watchtower . это простой инструмент, работающий в докер-контейнере, наблюдающий за другими контейнерами; если их базовое изображение изменилось, он извлечет и повторно развернет.

linehrr
источник
-1

Простое и отличное решение - пастух

user672009
источник
iiuc, это не помогает в общем смысле, потому что это связано с Swarm и только перезапускает апстрим, тогда как мы хотим реагировать, перестраивать и т. д. на изменения апстрима, а не просто перезапускать.
hbogert
Это звучит как то, что вы должны сделать в конвейере CI
user672009