Programing

기본 이미지가 업데이트 된 경우 도커 컨테이너를 자동으로 업데이트하는 방법

lottogame 2020. 5. 18. 08:04
반응형

기본 이미지가 업데이트 된 경우 도커 컨테이너를 자동으로 업데이트하는 방법


에 근거한 간단한 컨테이너가 있다고 가정 해보십시오 ubuntu:latest. 이제 보안 업데이트 ubuntu:latest가 있으며 docker repo에서 업데이트되었습니다.

  1. 로컬 이미지와 컨테이너가 뒤에서 실행되고 있는지 어떻게 알 수 있습니까?

  2. 도커 저장소 업데이트를 따르기 위해 로컬 이미지 및 컨테이너를 자동으로 업데이트하는 모범 사례가 있습니까? 실제로 기존 우분투 시스템에서 무인 업그레이드를 실행하는 것과 동일한 이점을 제공합니다.


이를 수행하는 방법 중 하나는 CI / CD 시스템을 통해이를 수행하는 것입니다. 부모 이미지가 만들어지면 해당 부모를 사용하여 이미지를 검색 할 수있는 무언가를 준비하십시오. 발견되면 새 버전의 이미지에 충돌하기 위해 풀 요청을 보냅니다. 모든 테스트가 통과되면 풀 요청이 병합되고 업데이트 된 부모를 기반으로 새 자식 이미지가 생깁니다. 이 방법을 사용하는 도구의 예는 https://engineering.salesforce.com/open-sourcing-dockerfile-image-update-6400121c1a75 에서 찾을 수 있습니다 .

공식 ubuntu이미지 에 의존하는 경우처럼 부모 이미지를 제어하지 않으면 부모 이미지 태그의 변경을 감지하고 이에 따라 자식 이미지 빌드를 호출하는 도구를 작성할 수 있습니다.


실행중인 컨테이너가 최신 이미지로 시작되었는지 확인하는 스크립트를 사용합니다. 또한 docker 이미지를 시작하기 위해 upstart init 스크립트를 사용합니다.

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

그리고 초기화는

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

'도커 방식'은 도커 허브 자동화 빌드 를 사용하는 것 입니다. 저장소 링크 업스트림 용기가 재건 될 때 기능은 컨테이너를 다시 것이고, Webhooks 기능을 사용하면 알림을 보내드립니다.

웹 후크가 HTTP POST 호출로 제한되어있는 것 같습니다. 이를 잡으려면 서비스를 설정하거나 POST 중 하나를 사용하여 서비스를 이메일로 보내야합니다.

나는 그것을 보지 않았지만 새로운 Docker Universal Control Plane 에는 업데이트 된 컨테이너를 감지하고 다시 배포하는 기능이있을 수 있습니다.


망루사용 하여 컨테이너가 인스턴스화 된 이미지의 업데이트를보고 업데이트를 자동으로 가져 와서 업데이트 된 이미지를 사용하여 컨테이너를 다시 시작할 수 있습니다. 그러나 기반이되는 업스트림 이미지가 변경 될 때 사용자 지정 이미지를 다시 작성하는 문제는 해결되지 않습니다. 이것을 (1) 업스트림 이미지가 업데이트 된시기를 알고 (2) 실제 이미지를 재구성하는 두 부분으로 된 문제로 볼 수 있습니다. (1) 상당히 쉽게 해결할 수 있지만 (2) 로컬 빌드 환경 / 연습에 많이 의존하므로 일반화 된 솔루션을 만드는 것이 훨씬 더 어려울 수 있습니다.

Docker Hub의 자동 빌드 를 사용할 수있는 경우 리포지토리 링크 기능을 사용하여 전체 문제를 비교적 깔끔하게 해결할 수 있습니다. 이렇게하면 연결된 리포지토리 (아마 업스트림)가 업데이트 될 때 자동으로 재 빌드를 트리거 할 수 있습니다. 자동화 된 빌드가 발생할 때 알리도록 웹 후크구성 할 수도 있습니다 . 이메일 또는 SMS 알림을 원하는 경우 webhook을 IFTTT Maker에 연결할 수 있습니다 . IFTTT 사용자 인터페이스가 다소 혼란 스럽지만 Docker webhook을 https://maker.ifttt.com/trigger/docker_xyz_image_built / with / key / 에 게시하도록 구성했습니다 your_key.

로컬로 빌드해야하는 경우, 관심있는 리포지토리에 연결된 Docker Hub에서 더미 리포지토리를 만들어 업스트림 이미지가 업데이트 될 때 알림을받는 문제를 해결할 수 있습니다. 더미 리포지토리의 유일한 목적은 다시 빌드 될 때 웹 후크를 트리거하는 것입니다 (링크 된 리포지토리 중 하나가 업데이트되었음을 ​​의미). 이 웹 후크를 수신 할 수 있다면,이를 사용하여 다시 빌드를 시작할 수도 있습니다.


나는 같은 문제가 있었고 unattended-upgrade매일 전화하는 cron 작업으로 간단히 해결할 수 있다고 생각했습니다 .

내 의도는 이미지를 업데이트하고 최신 보안 업데이트로 새 도커 이미지를 배포하는 데 시간이 걸릴 수 있기 때문에 프로덕션 컨테이너의 보안 및 업데이트를 보장하는 자동 및 빠른 솔루션으로 사용하는 것입니다.

Github 후크를 사용 하여 이미지 빌드 및 배포를 자동화 할 수도 있습니다

보안 업데이트를 매일 자동으로 확인하고 설치 하는 기본 도커 이미지만들었습니다 (에서 직접 실행할 수 있음 docker run itech/docker-unattended-upgrade).

또한 컨테이너에 업데이트가 필요한지 확인하기 위해 다른 접근 방식 을 발견했습니다.

내 완전한 구현 :

도커 파일

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 컨테이너로 실행 되는 작은 도구 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실행중인 모든 용기에


docker pull 을 실행하지 않고 컨테이너가 뒤에 있다는 것을 알 수 없습니다 . 그런 다음 이미지 다시 작성 하거나 재구성 해야합니다.

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

적절한 컨테이너에는 추가 작업이 필요하지 않지만 업그레이드를 완료하는 데 필요한 다른 작업과 함께 명령을 스크립트에 넣을 수 있습니다.


프로덕션에서 무인 업데이트를 원하는지 아닌지에 대한 모든 질문에 답하지는 않습니다. 누군가가 유용하다고 생각하는 경우 참조를 위해 여기에 남겨 둡니다. 터미널에서 다음 명령을 사용하여 모든 도커 이미지를 최신 버전으로 업데이트하십시오.

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


Docker 이미지의 종속성 관리는 실제 문제입니다. 컨테이너 이미지를 모니터링하고 메타 데이터를 검사하여이를 지원하는 MicroBadger 도구를 구축 한 팀의 일원입니다 . 그 기능 중 하나는 관심있는 이미지 (예 : 기본 이미지)가 변경 될 때 호출되는 알림 웹 후크를 설정하는 것입니다.


여기에는 많은 답변이 있지만 그 중 어느 것도 내 요구에 적합한 것은 아닙니다. 나는 asker의 # 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상단 변수 를 변경하고 필요에 따라 마지막에 전자 메일 알림 명령을 변경하려고합니다. 나를 위해 SMTP가있는 다른 네트워크의 서버에 SSH로 연결했습니다. 그러나 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

또 다른 방법은 기본 이미지가 매우 빠르게 뒤떨어져 있다고 가정하고 (예 : 매주) 주기적으로 (예 : 매주) 애플리케이션의 다른 이미지 빌드를 강제 실행 한 다음 변경되면 다시 배치하는 것입니다.

내가 알 수있는 한, 공식 데비안이나 자바와 같은 인기있는 기본 이미지는 보안 수정을 위해 태그를 업데이트하므로 태그를 변경할 수 없습니다 (더 강력한 보증을 원한다면 참조 [image : @digest ], 최신 Docker 버전에서 사용 가능). 따라서를 사용하여 이미지를 빌드하는 경우 docker build --pull응용 프로그램은 참조하는 기본 이미지 태그 중 가장 최신의 가장 큰 이미지를 가져와야합니다.

변경 가능한 태그는 혼란 스러울 수 있으므로, 이렇게 할 때마다 응용 프로그램의 버전 번호를 늘려서 최소한 측면에서 더 깨끗하게하는 것이 가장 좋습니다.

따라서 이전 답변 중 하나에서 제안 된 스크립트가 응용 프로그램의 이미지를 다시 작성하지 않기 때문에 작업을 수행하는지 확실하지 않습니다. 기본 이미지 태그 만 업데이트 한 다음 컨테이너를 다시 시작하지만 새 컨테이너는 여전히 참조합니다 이전 기본 이미지 해시

컨테이너 당 cron 유형 작업을 실행하는 것을 옹호하지 않을 것입니다 (또는 실제로 필요한 경우를 제외하고는 다른 프로세스). 컨테이너 당 하나의 프로세스 만 실행하는 방식에 반하기 때문에 (이 이유가 더 좋은 이유에 대한 다양한 주장이 있으므로) 여기에 들어 가지 않을 것입니다).


내 대답 전제 :

  1. 컨테이너는 태그로 실행됩니다.
  2. 우리가 적절하다고 느끼는 것처럼 동일한 태그가 다른 이미지 UUID를 가리킬 수 있습니다.
  3. 이미지에 대한 업데이트는 새로운 이미지 레이어로 커밋 될 수 있습니다

접근하다

  1. 보안 패치 업데이트 스크립트를 사용하여 모든 컨테이너를 먼저 빌드하십시오.
  2. 다음을위한 자동화 된 프로세스 구축
    • 보안 패치 스크립트를 명령으로 사용하여 기존 이미지를 새 컨테이너에 실행
    • 다음과 같이 변경 사항을 이미지에 커밋
      • 기존 태그-> 컨테이너를 하나씩 다시 시작
      • 새 버전 태그-> 몇 개의 컨테이너를 새 태그로 교체-> 확인-> 모든 컨테이너를 새 태그로 이동

또한 기본 이미지를 업그레이드 할 수 있습니다. 관리자가 필요하다고 느끼면 정기적으로 새로운 기본 이미지로 컨테이너를 정기적으로 만들 수 있습니다.

장점

  1. 새로운 보안 패치 이미지를 만드는 동안 이미지의 이전 버전을 유지하므로 필요한 경우 이전 실행 이미지로 롤백 할 수 있습니다
  2. 우리는 도커 캐시를 보존하므로 네트워크 전송이 줄어 듭니다 (변경된 레이어 만 유선으로 연결됨)
  3. prod로 이동하기 전에 스테이징에서 업그레이드 프로세스를 검증 할 수 있습니다.
  4. 이것은 통제 된 프로세스 일 수 있으므로, 필요 / 고려 될 때만 보안 패치를 적용 할 수 있습니다.

UPDATE : 사용 Dependabot - https://dependabot.com/docker/

BLUF : 컨테이너 변경 사항을 모니터링하기위한 올바른 삽입 지점을 찾는 것이 쉽지 않습니다. DockerHub가 이것을 해결하면 좋을 것입니다. (DockerHub에 그들을 설정할 때 저장소 링크는 언급하지만 참고있다 - ". 트리거 빌드를 기본 이미지가 도커 허브에 업데이트 될 때마다이 저장소에 만이 아닌 공식 이미지에 적용됩니다." )

이 문제를 직접 해결하려고 시도하면서 webhook에 대한 몇 가지 권장 사항을 보았으므로 사용한 몇 가지 솔루션에 대해 자세히 설명하고 싶었습니다.

  1. microbadger.com을 사용하여 컨테이너의 변경 사항을 추적하고 알림 웹 후크 기능을 사용하여 작업을 트리거하십시오. 나는 zapier.com으로 설정했지만 (사용자 정의 가능한 웹 후크 서비스를 사용할 수는 있지만) Alpine을 기본 이미지로 사용하는 github 저장소에서 새로운 문제를 만듭니다.

    • 장점 : 조치를 취하기 전에 github에서 microbadger가보고 한 변경 사항을 검토 할 수 있습니다.
    • 단점 : Microbadger를 사용하면 특정 태그를 추적 할 수 없습니다. '최신'만 추적하는 것 같습니다.
  2. 업스트림 컨테이너에 대한 git 커밋에 대한 RSS 피드를 추적하십시오. 전의. https://github.com/gliderlabs/docker-alpine/commits/rootfs/library-3.8/x86_64 . zapier.com을 사용하여이 피드를 모니터링하고 무언가가 커밋 될 때마다 Travis-CI에서 컨테이너 자동 빌드를 시작했습니다. 이것은 약간 극단적이지만 수동 개입을 위해 자식 저장소에서 문제를 여는 것과 같은 다른 작업을 수행하도록 트리거를 변경할 수 있습니다.

    • 장점 : 자동화 된 파이프 라인에 더 가깝습니다. Travis-CI 빌드는 컨테이너에 기본 이미지 리포지토리에 커밋 된 문제가 있는지 확인합니다. CI 서비스가 추가 조치를 취하는 경우 귀하의 책임입니다.
    • 단점 : 커밋 피드를 추적하는 것은 완벽하지 않습니다. 기본 이미지 빌드에 영향을 미치지 않는 많은 것들이 저장소에 투입됩니다. 커밋 횟수 / 커밋 횟수 및 API 조절 문제를 고려하지 않습니다.

위의 답변도 정확합니다

두 가지 접근법이 있습니다

  1. 웹 후크 사용
  2. 매 1 분마다 스크립트를 실행하여 도커 이미지를 새로 가져옵니다.

스크립트를 공유하는 것이 도움이 될 수 있습니다! 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

도커 컨테이너를 자동으로 업데이트하는 가장 간단한 방법은 다음과 같습니다.

작업을 통해 $ crontab -e:

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

~/.docker파일로 dir 만듭니다 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

간단하고 훌륭한 해결책은 목자입니다


https://github.com/v2tec/watchtower 을 사용해 보셨습니까 ? Docker 컨테이너에서 실행되는 간단한 도구로 다른 컨테이너를보고 기본 이미지가 변경되면 끌어서 재배치합니다.

참고 URL : https://stackoverflow.com/questions/26423515/how-to-automatically-update-your-docker-containers-if-base-images-are-updated

반응형