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


205

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

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

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


11
도 커가 시작된 이래로 이에 대한 답을 찾고 있습니다. 조금 더 복잡합니다. 아파치 (예 : 아파치)를 설치하고 업데이트하면 기본 이미지는 나중에 설치되므로 변경되지 않습니다. 여전히 아파치에 대한 자동 업데이트를 원합니다. 나는 실제로 IRC에 이것에 대해 물었고 대답으로 "업스트림을 따르고 업데이트에 다시 빌드"를 얻었습니다.
Mathias

8
내가 유일하게 궁금하지 않은 것은 기쁘다. Docker 개발자에게는 현재 몇 년 동안 있었던 합리적인 업데이트 메커니즘보다 개발 및 재현성이 더 중요합니다.
hbogert

문제는 docker는 컨테이너의 기술 일뿐입니다. 생태계가 진화하기 위해서는 시간이 필요하다고 생각합니다. 도 커가 로깅과 같이 해결하지 못하는 다른 문제가 있습니다.
Mathias

3
답변 한 모든 사람에게 감사합니다. 현상금을 분할 할 수 없어서 죄송합니다. 내 문제에 대한 최종 해결책은 없었지만 모든 사람들의 의견이 좋았습니다.
Mathias

1
@Mathias의 경우 방금 추가 한 솔루션에는 컨테이너 포스트 풀에 설치된 패키지의 보안 업데이트를 확인하는 스크립트가 있습니다. 또한 기본 이미지를 확인하기위한 별도의 스크립트가 있습니다.
Fmstrat 2016 년

답변:


8

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

공식 ubuntu이미지 에 의존하는 경우처럼 부모 이미지를 제어하지 않으면 부모 이미지 태그 또는 체크섬의 변화를 감지하는 툴링을 작성할 수 있습니다 (동일한 것은 아니며 태그는 변경 가능). 이에 따라 어린이 이미지 빌드를 호출하십시오.


와우 이것은 큰 망치입니다.이 질문을 할 때부터 빌드 서버 가이 문제를 해결할 수있는 곳이라는 것을 알게되었습니다. 나는 약간의 툴링을 보게되어 기쁘다. 당신의 접근 방식을 일반적인 개념으로 설명하고 (정확한 도구 / 구현이 아님) 대답에 포함 시키면 아마 받아 들일 것입니다.
hbogert

감사합니다 @ hbogert 위의 내용을 편집하고 공개 이미지를 다루는 경우해야 할 일에 대한 아이디어도 포함합니다
Ma3oxuct

123

실행중인 컨테이너가 최신 이미지로 시작되었는지 확인하는 스크립트를 사용합니다. 또한 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

1
이 소중한 기여에 감사드립니다. 이것은 기본 이미지를 업데이트하는 좋은 방법 인 것 같습니다. 나머지 질문은 dockerfile의 배포에 의해 설치된 응용 프로그램 (아파치와 같은)을 어떻게 업데이트합니까? 또는 웹 사이트와 같이 응용 프로그램 코드 만 필요한 기성품 기본 이미지 만 사용합니까?
Mathias

패커와 퍼펫을 사용하여 이미지를 구성합니다. 우리의 이미지는 생성 후 생산에 갈 준비가되어
bsuttor

@Mathias, 편집 된 답변 참조 모든 실행중인 컨테이너에서 Linux (현재 debian / ubuntu) 패키지를 업데이트하는 데 사용 하는 작은 도구 docker-run 이 있습니다.
iTech

3
이미지가 컨테이너 (예 : 같은 이름을 가진 경우 redis), LATEST=`docker inspect --format "{{.Id}}" $IMAGE`컨테이너 정보를 얻을 것이다. --type image이 문제를 해결하려면 추가하십시오 .
Patrick Fisher

1
게시물 주셔서 감사합니다. for IMAGE in $(docker ps --format {{.Image}} -q | sort -u)
Armand

25

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

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

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


AMQP 서비스에 대한 웹훅
goliatone

안타깝게도 github.com/docker/hub-feedback/issues/1717 에서 업스트림 트리거를 더 이상 사용할 수 없습니다 .
Julien Chastang

22

망루 를 사용 하여 컨테이너가 인스턴스화 된 이미지의 업데이트를보고 업데이트를 자동으로 가져 와서 업데이트 된 이미지를 사용하여 컨테이너를 다시 시작할 수 있습니다. 그러나 기반이되는 업스트림 이미지가 변경 될 때 사용자 지정 이미지를 다시 작성하는 문제는 해결되지 않습니다. 이것을 (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에서 더미 리포지토리를 만들어 업스트림 이미지가 업데이트 될 때 알림을받는 문제를 해결할 수 있습니다. 더미 리포지토리의 유일한 목적은 다시 빌드 될 때 웹 후크를 트리거하는 것입니다 (링크 된 리포지토리 중 하나가 업데이트되었음을 ​​의미). 이 웹 후크를 수신 할 수 있다면,이를 사용하여 다시 빌드를 시작할 수도 있습니다.


1
망루는 도커 소켓을 사용합니다. 호스트 컴퓨터에 대한 루트 액세스 권한을 제공하는 보안 관점에서.
JoeG

1
또한 Watchtower는 Docker Hub 이외의 개인 리포지토리에서 이미지를 업데이트 할 수 없습니다. Azure를 사용하는 우리에게는 부머입니다.
Thomas Eyde

1
REPO_USERREPO_PASS환경 변수를 사용하여 개인 레지스트리를 사용할 수 있습니다 . 자세한 내용은 Watchtower에서 readme.md를 참조하십시오 : github.com/v2tec/watchtower#usage
Alejandro Nortes

2
경고의 말로 망루는 관리자에 의해 버려지고 DockerHub의 이미지는 github의 이미지와 최신 상태가 아닙니다.
XanderStrike

망루 저장소가 containsrrr / watchtower 로 마이그레이션 된 것 같습니다 . 또한 유사한 질문에 대한이 답변에서 지적한 것처럼 Dockerhub의 연결된 자동화 빌드와 관련된 문제가 있습니다 .
chrki

10

나는 같은 문제가 있었고 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실행중인 모든 용기에


무인 업그레이드에 대한 나의 언급은 비도 커 환경에서만 유추를 보여주기위한 것이었다. 내 의도는이 도커 방식을 해결하는 것입니다 (10 월 존재하는 경우) 컨테이너에 추가 프로세스가 있으면 docker imo의 목적보다 뛰어납니다. 이미지 업스트림 업데이트와 사용자 사이의 지연 문제를 해결하지만 실제로는 현재 컨테이너에서 이미지를 제거합니다. 무인 업그레이드에서도 최대 1 일이 소요될 수 있지만 업데이트 메커니즘이 이제 호스트 OS에 크게 의존하기 때문에 github 참조는 만족스럽지 않습니다.
hbogert

"도커 방식"으로 인해 밀접하게 관련되어 있고 확장 성 병목 현상이 발생하지 않는 동일한 컨테이너에서 다른 프로세스를 실행할 수 있습니다. 이 특정 사용 사례는 다른 실행중인 프로세스가있는 컨테이너를 가질 수있는 좋은 예입니다. (예 : 동일한 컨테이너에서 여러 개의 필수 프로세스를 실행하는 gitlab의 이미지 참조 )
iTech

이미지의 주요 기능과 밀접하게 관련된 업데이트 메커니즘을 호출하지 않습니다. 이 솔루션은 패키지 관리자에게 부담을주지 않고 기존 시스템의 모든 애플리케이션에 자체 업데이트 메커니즘을 제공하는 것과 같습니다. 솔루션이지만 내 이미지에 자동으로 로컬 이미지를 업데이트 한 다음 컨테이너를 다시 실행해야한다는 내 질문에 대답하지 않습니다. 컨테이너 자체에서 업데이트하면서 우리는 다시 도커 방식에 반대하는 많은 상태를 다시 소개합니다 (imho).
hbogert

1
Kubernetes대규모 인프라 배포에 유용한 Docker보다 높은 수준의 것이 필요할 수 있지만 여전히 Google에서 개발 중입니다. 현재 Ansible과 같은 프로비저닝 도구를 사용하여 매우 간단한 방법으로이를 자동화 할 수 있습니다.
iTech

당신이 인용 한 "다른 접근법"은 내가 찾던 것일 수도 있습니다. 귀하의 기여는 "지방 컨테이너"에 대한 대안으로 보입니다. 답을 주셔서 감사합니다.
Mathias

7

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

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

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


1 : 좋아, 그러나 나는 모든 로컬 이미지를보고, 기본 이미지를 가져 와야합니다. 그런 다음 기본 이미지가 변경된 이미지를 다시 작성하십시오. 그런 다음 이미지가 변경된 컨테이너를 중지하고 'docker run'및 필요한 매개 변수를 사용하여 컨테이너를 다시 작성하십시오. 이것은 지나치게 수동적 인 것 같습니다. 그러나 이것이 현 상태라면 대답을 받아들입니다.
hbogert

수락하기 전에 기다려주십시오. 어쩌면 뭔가가있을 수 있습니다. 나는 6 개월 동안 도커를 사용했지만 최신 개발을 따라 가지 못했습니다.
seanmcl

내부적으로 Docker는 '캐싱'기능을 수행하기 위해 이미지를 비교할 수 있습니다. 아마도 당신은 THAT를 활용할 수있는 방법을 찾을 수있을 것입니다. 다시 말해, 기본 이미지 (기본으로 돌아가는 이미지)가 변경되었는지 확인한 다음 프로세스를 다시 빌드하도록 트리거합니다. 안타깝게도이 경우 캐싱이 도움이되지 않습니다. 기본 이미지가 변경되어 전체 이미지가 다시 작성됩니다.
Thom Parkin

5

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


5

여기에는 많은 답변이 있지만 그 중 어느 것도 내 요구에 적합한 것은 아닙니다. 나는 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

1
첫 번째 스크립트의 mkdir은 다음과 같아야합니다. mkdir -p 또한 첫 번째 스크립트는 VAR1과 VAR2를 비교하고 OLD와 NEW를 비교해야한다고 가정합니다. 사실 인 경우 설치시 처음 실행 된 스크립트가 아니라면이 스크립트가 실제로 OP가 원하는 것을 수행하지 않음을 의미합니다. 즉, 결과가 이전 실행과 다른 경우에 실제로 설치 대상에 대해 아무것도 결정하지 않습니다 ...
JoeG

5

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

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

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

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

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


4

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

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


1
이 명령은 모든 이미지를 업데이트하는 데 유용하지만 프로덕션에서 실행중인 항목은 변경하지 않습니다. 컨테이너는 여전히 태그가 지정되지 않은 이전 이미지에서 유래합니다.
없음

진실. 그리고 여기에 더 많은 책이 있습니다 ... # docker system prune -a --volumes -f오래된 (매달려있는) 이미지, 볼륨 등을 정리하는 데 사용
Meferdati

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 조절 문제를 고려하지 않습니다.

3

내 대답 전제 :

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

접근하다

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

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

장점

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

프로덕션 환경에서는 보안 업데이트이지만 무인 업데이트를 원하십니까? 무인 업데이트가 필요한 경우 프로세스를 정기적으로 (적절한 경우) 크론 작업으로 실행할 수 있습니다.
Phani

1
내 전제는 보안 업데이트가 업스트림 /베이스 이미지에서 제공되어야한다는 것입니다.
hbogert

@ hbogert 나는 이론과 실제 사이에 미세한 구분이 있다고 말합니다. 상황이 현실화 될 때 구현과 관련된 비용 (달러 가치뿐만 아니라 시간)과 같은 많은 외부 측면을 고려해야합니다.
Phani

3

위의 답변도 정확합니다

두 가지 접근법이 있습니다

  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

3

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

작업을 통해 $ 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


-1

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


iiuc, 이것은 일반적인 의미에서 도움이되지 않습니다. 왜냐하면 이것은 Swarm과 결합되어 업스트림 만 다시 시작 하기 때문입니다 . 반면, 업스트림 변경에 대해 반응, 재구성 등을하고 단순히 다시 시작하지 않기를 원합니다.
hbogert

그것은 당신이 CI 파이프 라인에서해야 할 일 같은 소리
user672009
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.