Jak automatycznie aktualizować kontenery dokerów, jeśli obrazy podstawowe są aktualizowane

205

Powiedz, że mam trywialny kontener oparty na ubuntu:latest. Teraz jest aktualizacja zabezpieczeń i ubuntu:latestjest aktualizowana w repozytorium dokera.

  1. Skąd mam wiedzieć, że mój lokalny obraz i jego kontenery biegną?

  2. Czy istnieje jakaś najlepsza praktyka w zakresie automatycznego aktualizowania lokalnych obrazów i kontenerów w celu śledzenia aktualizacji repozytorium dokującego, co w praktyce zapewniłoby takie same upodobania, jak w przypadku nienadzorowanej aktualizacji działającej na konwencjonalnej maszynie ubuntu

Hbogert
źródło
11
Szukam odpowiedzi na to pytanie od początku dokera. To nawet trochę bardziej skomplikowane. Jeśli zainstaluję Apache (na przykład) i zostanie on zaktualizowany, obraz podstawowy nie zmieni się, ponieważ zainstalowałem go później. Nadal chciałbym mieć automatyczne aktualizacje apache. Właściwie zapytałem w IRC o to i dostałem odpowiedź „śledź i przebudowuj aktualizacje” jako odpowiedź ...
Mathias
8
Cieszę się, że nie jestem jedynym, który się zastanawia. Wydaje się, że rozwój i odtwarzalność jest ważniejsza dla twórców dokerów niż rozsądne mechanizmy aktualizacji, które mieliśmy od lat.
hbogert
Problem polega na tym, że doker to tylko technologia dla kontenerów. Myślę, że potrzebuje trochę czasu, aby ekosystem ewoluował wokół tego. Istnieją inne problemy, które doker nie rozwiązuje, takie jak logowanie.
Mathias
3
Dziękujemy wszystkim, którzy odpowiedzieli. Przepraszam, że nie mogłem podzielić nagrody. Mimo że nie było ostatecznego rozwiązania mojego problemu, wszyscy otrzymali dobry wkład.
Mathias
1
W przypadku @Mathias, właśnie dodane rozwiązanie zawiera skrypt, który będzie sprawdzał aktualizacje zabezpieczeń dla pakietów zainstalowanych w kontenerze po pobraniu. Ma również osobny skrypt do sprawdzania obrazu podstawowego.
Fmstrat

Odpowiedzi:

8

Jednym ze sposobów, aby to zrobić, jest przejęcie tego przez systemy CI / CD. Po zbudowaniu obrazu nadrzędnego możesz mieć coś, co skanuje repozytorium git w poszukiwaniu obrazów przy użyciu tego rodzica. Jeśli zostanie znaleziony, wyślesz żądanie ściągnięcia, aby podskoczyć do nowych wersji obrazu. Żądanie ściągnięcia, jeśli wszystkie testy zakończą się pomyślnie, zostanie scalone, a otrzymasz nowy obraz potomny na podstawie zaktualizowanego elementu nadrzędnego. Przykład narzędzia stosującego to podejście można znaleźć tutaj: https://engineering.salesforce.com/open-sourcing-dockerfile-image-update-6400121c1a75 .

Jeśli nie kontrolujesz swojego wizerunku rodzica, tak jak w przypadku urzędnika ubuntu obrazu , możesz napisać narzędzia wykrywające zmiany w znaczniku obrazu nadrzędnego lub sumie kontrolnej (nie to samo, tagi są zmienne) i wywoływać odpowiednio buduje obraz dzieci.

Ma3oxuct
źródło
Wow, to jest wielki młotek, który powiedział: od czasu, kiedy zadałem to pytanie, zdałem sobie również sprawę, że serwer kompilacji jest miejscem do rozwiązania tego problemu. Cieszę się, że widzę jakieś narzędzia. Jeśli wyjaśnisz swoje podejście w ogólnych pojęciach (a nie dokładne narzędzie / implementację) i umieścisz je w odpowiedzi, prawdopodobnie to zaakceptuję.
hbogert
Dzięki @hbogert Zredagowałem powyższe, a także zawiera pomysł na to, co zrobić, jeśli masz do czynienia z obrazami publicznymi
Ma3oxuct
123

Używamy skryptu, który sprawdza, czy działający kontener jest uruchamiany z najnowszym obrazem. Używamy również wstępnych skryptów inicjujących do uruchomienia obrazu dokera.

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

I wygląda na to, że init

docker run -t -i --name $NAME $im /bin/bash
bsuttor
źródło
1
Wielkie dzięki za ten cenny wkład. To wydaje się dobrym sposobem na aktualizację obrazu podstawowego. Pozostaje pytanie, jak zaktualizować aplikację (taką jak apache), która została zainstalowana przez dystrybucję w pliku dokera? A może używasz tylko gotowych obrazów podstawowych, które wymagają jedynie kodu aplikacji (np. Strony internetowej)?
Mathias
Używamy pakera i marionetki do konfiguracji naszych zdjęć. Nasze obrazy są gotowe do produkcji po ich stworzeniu
bsuttor
@Mathias, zobacz moją zredagowaną odpowiedź. Mam mały program uruchamiający okno dokowane, którego używam do aktualizacji pakietów linux (obecnie debian / ubuntu) we wszystkich działających kontenerach.
iTech,
3
Jeśli obraz ma taką samą nazwę jak kontener (np. redis), LATEST=`docker inspect --format "{{.Id}}" $IMAGE`Otrzyma informacje o kontenerze. Dodaj, --type imageaby to naprawić.
Patrick Fisher
1
Dzięki za twój post. Zmodyfikowałem go, aby owinąć całość w pętlę, aby uzyskać obrazy z okna dokowanego: for IMAGE in $(docker ps --format {{.Image}} -q | sort -u)
Armand
25

„Sposób dokowania” polegałby na użyciu automatycznych kompilacji centrum dokującego . Funkcja Łącza repozytorium przebuduje Twój kontener, gdy zostanie on odbudowany, a funkcja Webhooks wyśle ​​Ci powiadomienie.

Wygląda na to, że haki są ograniczone do wywołań POST HTTP. Trzeba będzie skonfigurować usługę, aby je złapać, lub może użyć jednego z POST, aby wysłać pocztą e-mail usługi.

Nie zagłębiłem się w to, ale nowy uniwersalny samolot kontrolny Docker może mieć funkcję wykrywania zaktualizowanych kontenerów i ponownego wdrażania.

TAKSÓWKA
źródło
Musiałem zbudować hak internetowy do usługi AMQP: github.com/goliatone/rabbithook
goliatone
Niestety wyzwalacze wysyłania nie są już dostępne: github.com/docker/hub-feedback/issues/1717 .
Julien Chastang
22

Możesz użyć Strażnicy można obserwować aktualizacje obrazu, z którego utworzono instancję kontenera, a następnie automatycznie pobrać aktualizację i ponownie uruchomić kontener, używając zaktualizowanego obrazu. Nie rozwiązuje to jednak problemu przebudowywania własnych obrazów niestandardowych, gdy następuje zmiana obrazu wyjściowego, na którym jest oparty. Można to potraktować jako dwuczęściowy problem: (1) wiedząc, kiedy obraz nadrzędny został zaktualizowany, i (2) wykonując rzeczywistą odbudowę obrazu. (1) można rozwiązać dość łatwo, ale (2) wiele zależy od lokalnego środowiska / praktyk kompilacji, więc prawdopodobnie trudniej jest stworzyć uogólnione rozwiązanie.

Jeśli możesz korzystać ze zautomatyzowanych kompilacji Docker Hub , cały problem można rozwiązać stosunkowo czysto za pomocą funkcji łączy repozytorium , która pozwala automatycznie uruchomić przebudowę po aktualizacji połączonego repozytorium (prawdopodobnie wcześniejszego). Możesz również skonfigurować hak internetowy, aby powiadamiał Cię o automatycznej kompilacji. Jeśli chcesz otrzymywać powiadomienia e-mail lub SMS, możesz podłączyć hak internetowy do IFTTT Maker . Stwierdziłem, że interfejs użytkownika IFTTT jest nieco mylący, ale skonfigurowałbyś hak internetowy Dockera, aby publikować na https://maker.ifttt.com/trigger/docker_xyz_image_built / with / key / your_key.

Jeśli musisz budować lokalnie, możesz przynajmniej rozwiązać problem z otrzymywaniem powiadomień, gdy aktualizowany jest obraz wyjściowy, tworząc fałszywe repozytorium w Docker Hub połączone z Twoimi interesującymi repozytoriami. Jedynym celem atrapowego repozytorium byłoby wywołanie haka sieciowego po jego odbudowaniu (co oznacza, że ​​jedno z powiązanych repozytoriów zostało zaktualizowane). Jeśli możesz otrzymać ten hak internetowy, możesz go nawet użyć do uruchomienia odbudowy po swojej stronie.

jjlin
źródło
1
Strażnica korzysta jednak z gniazda dokującego. Z punktu widzenia bezpieczeństwa, który daje dostęp rootowi do hosta.
JoeG
1
Strażnica również nie wydaje się być w stanie aktualizować obrazów z prywatnych repozytoriów innych niż Docker Hub. Bummer dla nas, którzy używają platformy Azure.
Thomas Eyde,
1
Możesz używać rejestrów prywatnych przy użyciu REPO_USERi REPO_PASSzmiennych środowiskowych. Spójrz na readme.md ze Strażnicy, aby uzyskać więcej informacji: github.com/v2tec/watchtower#usage
Alejandro Nortes
2
Ostrzegam, jego strażnik porzuca wieżę, a obraz w DockerHub nie jest nawet zgodny z tym w github.
XanderStrike
Wygląda na to, że repozytorium Strażnicy zostało przeniesione do przechowalni / wieży strażniczej . I są pewne problemy z połączonymi automatycznymi kompilacjami w Dockerhub, jak wskazano w tej odpowiedzi na podobne pytanie .
chrki
10

Miałem ten sam problem i pomyślałem, że można go po prostu rozwiązać, unattended-upgradecodziennie dzwoniąc do pracy crona .

Zamierzam mieć to jako automatyczne i szybkie rozwiązanie zapewniające bezpieczeństwo i aktualizację kontenera produkcyjnego, ponieważ może to zająć trochę czasu, aby zaktualizować moje obrazy i wdrożyć nowy obraz dokera z najnowszymi aktualizacjami zabezpieczeń.

Możliwe jest również zautomatyzowanie budowania i wdrażania obrazu za pomocą haków Github

Stworzyłem podstawowy obraz dokera, który automatycznie sprawdza i instaluje codziennie aktualizacje zabezpieczeń (może być uruchamiany bezpośrednio przez docker run itech/docker-unattended-upgrade).

Natknąłem się również na inne podejście, aby sprawdzić, czy kontener wymaga aktualizacji.

Moja pełna realizacja:

Plik Docker

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

Skrypty pomocnicze

zainstalować

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

początek

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

Edytować

Opracowałem małe narzędzie do uruchamiania dokerów, które działa jako kontener dokerów i może być używane do aktualizacji pakietów we wszystkich lub wybranych uruchomionych kontenerach, może także służyć do uruchamiania dowolnych poleceń.

Można go łatwo przetestować za pomocą następującego polecenia:

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

który domyślnie wykona datepolecenie we wszystkich działających kontenerach i wyświetli wyniki. Jeśli podasz updatezamiast tego exec, zostanie wykonany, apt-get updatea następnie apt-get upgrade -ywe wszystkich uruchomionych kontenerach

iTech
źródło
moje odniesienie do aktualizacji nienadzorowanej miało na celu pokazanie analogii w środowisku innym niż doker. Moim zamiarem jest rozwiązanie tego sposobu dokowania (jeśli tak jest ok.). Dodatkowy proces w kontenerze jest lepszy niż cel dokera imo. Łata rozwiązuje problem opóźnienia między aktualizacją obrazu a aktualizacją obrazu przez użytkownika. Chociaż może to potrwać nawet 1 dzień w przypadku uaktualnień nienadzorowanych, więc .. Również odniesienie do github jest niezadowalające, ponieważ mechanizm aktualizacji jest obecnie silnie zależny od systemu operacyjnego hosta.
hbogert
„Sposób dokowania” nie zapobiega uruchamianiu innych procesów na tym samym kontenerze, jeśli są one ściśle powiązane i nie tworzą wąskiego gardła skalowalności. Ten szczególny przypadek użycia jest dobrym przykładem tego, kiedy możesz mieć kontener z innym działającym procesem. (np. zobacz obraz gitlab, ponieważ uruchamia wiele obowiązkowych procesów na tym samym kontenerze).
iTech
Nie nazwałbym mechanizmu aktualizacji ściśle powiązanym z główną funkcją obrazu. To rozwiązanie przypomina nadanie każdej aplikacji na konwencjonalnej maszynie własnego mechanizmu aktualizacji zamiast obciążania menedżera pakietów. Chociaż jest to rozwiązanie, nie odpowiada na moje pytanie, które polega na automatycznej aktualizacji lokalnych obrazów, a następnie pojemniki powinny zostać ponownie uruchomione. Dzięki aktualizacji w samych kontenerach ponownie wprowadzamy wiele stanów, o których nie mamy pojęcia, co jest sprzeczne ze sposobem dokera (ponownie imho).
hbogert
1
Możesz potrzebować czegoś wyższego niż doker, takiego jak Kubernetesprzydatny przy wdrażaniu dużej infrastruktury, ale Google wciąż go rozwija. W tej chwili możesz to zautomatyzować za pomocą narzędzia do obsługi administracyjnej, takiego jak Ansible, w dość prosty sposób.
iTech
Twoje cytowane „inne podejście” może być tym, czego szukałem. Twój wkład wygląda jak realna alternatywa dla „pojemników na tłuszcz”. Na pewno przyjrzę się nieco dalej, dzięki za odpowiedź.
Mathias
7

Nie wiedziałbyś, że twój kontener jest z tyłu bez uruchomienia ściągacza dokującego . Następnie musisz odbudować lub ponownie skomponować obraz.

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

Polecenia można umieścić w skrypcie wraz ze wszystkim innym, co jest konieczne do ukończenia aktualizacji, chociaż odpowiedni kontener nie potrzebuje niczego dodatkowego.

seanmcl
źródło
1: ok, ale wtedy musiałbym spojrzeć na wszystkie moje obrazy lokalne, zdobyć ich obrazy podstawowe, wyciągnąć je. Następnie odbuduj obrazy, których obrazy podstawowe uległy zmianie. Następnie zatrzymaj kontenery, których obraz został zmieniony, i ponownie utwórz kontenery z „uruchomieniem dokera” i potrzebnymi parametrami. To wydaje się zbyt ręczne. Ale jeśli to jest status quo, wtedy zaakceptuję odpowiedź.
hbogert
Poczekaj, zanim zaakceptujesz. Może coś tam jest. Używam dokera od 6 miesięcy, ale nie nadążam za najnowszymi osiągnięciami.
seanmcl
W jakiś sposób wewnętrznie Docker jest w stanie porównywać obrazy w celu wykonania funkcji „buforowania”. Być może możesz znaleźć sposób, aby to WYKORZYSTAĆ. Innymi słowy, sprawdź, czy obrazy poniżej (aż do bazy) uległy zmianie, a następnie uruchom proces odbudowy. Niestety buforowanie nie pomoże ci w takim przypadku: cały obraz zostanie odbudowany, ponieważ zmienił się obraz podstawowy.
Thom Parkin
5

Zarządzanie zależnościami dla obrazów Docker to prawdziwy problem. Należę do zespołu, który zbudował narzędzie MicroBadger , które pomaga w tym, monitorując obrazy kontenerów i sprawdzając metadane. Jedną z jego funkcji jest umożliwienie skonfigurowania haka do powiadomień, który będzie wywoływany, gdy zmieni się obraz, który Cię interesuje (np. Obraz podstawowy).

Liz Rice
źródło
5

Tutaj jest wiele odpowiedzi, ale żadna z nich nie odpowiada moim potrzebom. Chciałem rzeczywistej odpowiedzi na pytanie nr 1 pytającego. Skąd mam wiedzieć, kiedy obraz jest aktualizowany na hub.docker.com?

Poniższy skrypt można uruchamiać codziennie. Przy pierwszym uruchomieniu pobiera linię bazową znaczników i aktualizuje daty z rejestru HUB i zapisuje je lokalnie. Odtąd za każdym razem, gdy jest uruchamiany, sprawdza rejestr pod kątem nowych znaczników i dat aktualizacji. Ponieważ zmienia się to za każdym razem, gdy istnieje nowy obraz, informuje nas, czy zmienił się obraz podstawowy. Oto skrypt:

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

Będziesz chciał zmienić DATAPATHzmienną u góry i zmienić polecenie powiadomienia e-mail na końcu, aby dostosować je do swoich potrzeb. Dla mnie mam SSH do serwera w innej sieci, w której znajduje się mój SMTP. Ale możesz łatwo użyćmail polecenia.

Teraz chcesz również sprawdzić zaktualizowane pakiety w samych kontenerach. Jest to prawdopodobnie bardziej efektywne niż „ściąganie”, gdy twoje pojemniki działają. Oto skrypt, aby to zrobić:

#!/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
źródło
1
mkdir w pierwszym skrypcie powinien być prawdopodobnie: mkdir -p Ponadto pierwszy skrypt porównuje VAR1 z VAR2, zakładając, że powinien on porównywać OLD z NOWYM. Jeśli to prawda, oznacza to, że ten skrypt nie zrobi tego, czego chce OP, JEŚLI był on uruchamiany po raz pierwszy podczas instalacji. Oznacza to, że tak naprawdę nie określa niczego, co jest instalowane, tylko jeśli wyniki różnią się od poprzednich uruchomień ...
JoeG
5

Innym podejściem może być założenie, że obraz podstawowy dość szybko się opóźnia (i bardzo prawdopodobne, że tak się stanie) i wymuszanie okresowego kompilowania obrazu aplikacji (np. Co tydzień), a następnie ponowne wdrożenie go, jeśli uległo zmianie.

O ile mi wiadomo, popularne obrazy podstawowe, takie jak oficjalna Debian lub Java, aktualizują swoje tagi, aby uwzględnić poprawki bezpieczeństwa, więc tagi nie są niezmienne (jeśli chcesz silniejszej gwarancji, że musisz użyć referencji [image: @digest ], dostępne w nowszych wersjach Docker). Dlatego jeśli chcesz zbudować obraz docker build --pull, aplikacja powinna uzyskać najnowszy i największy z podstawowych znaczników obrazu, do których się odwołujesz.

Ponieważ zmienne tagi mogą być mylące, najlepiej zwiększać numer wersji aplikacji za każdym razem, gdy to robisz, aby przynajmniej po twojej stronie wszystko było czystsze.

Nie jestem więc pewien, czy skrypt zasugerowany w jednej z poprzednich odpowiedzi spełnia swoje zadanie, ponieważ nie odbudowuje obrazu twojej aplikacji - po prostu aktualizuje podstawowy znacznik obrazu, a następnie uruchamia ponownie kontener, ale nowy kontener wciąż się odwołuje stary skrót obrazu podstawowego.

Nie opowiadałbym się za uruchamianiem zadań typu cron w kontenerach (lub innych procesach, chyba że jest to naprawdę konieczne), ponieważ jest to sprzeczne z mantrą uruchamiania tylko jednego procesu na kontener (istnieją różne argumenty na temat tego, dlaczego jest to lepsze, więc „ nie zamierzam tu wchodzić).

Bogdan
źródło
4

Nie zastanawiam się nad tym, czy chcesz produkować nienadzorowane aktualizacje (chyba nie). Zostawiam to tutaj w celach informacyjnych na wypadek, gdyby ktoś uznał to za przydatne. Zaktualizuj wszystkie obrazy dokerów do najnowszej wersji za pomocą następującego polecenia w terminalu:

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

Meferdati
źródło
1
Polecenie to jest przydatne do aktualizacji wszystkich obrazów, ale nie zmienia niczego uruchomionego podczas produkcji. Pojemniki wciąż pochodzą ze starych obrazów, które są teraz nieoznaczone.
Brak,
Prawdziwe. A oto jeszcze jedna książka ... Użyj, # docker system prune -a --volumes -faby posprzątać stare (wiszące) obrazy, tomy itp.
Meferdati
4

AKTUALIZACJA: Użyj Dependabot - https://dependabot.com/docker/

BLUF: znalezienie odpowiedniego punktu wstawienia do monitorowania zmian w kontenerze jest wyzwaniem. Byłoby wspaniale, gdyby DockerHub to rozwiązał. (Łącza do repozytorium zostały wspomniane, ale należy pamiętać, że podczas konfigurowania ich w DockerHub - Uruchom kompilację w tym repozytorium, ilekroć obraz podstawowy jest aktualizowany w Docker Hub. Działa tylko w przypadku obrazów nieoficjalnych.” )

Próbując rozwiązać ten problem sam, widziałem kilka rekomendacji dotyczących haków internetowych, więc chciałem rozwinąć kilka rozwiązań, z których skorzystałem.

  1. Skorzystaj z witryny microbadger.com, aby śledzić zmiany w kontenerze, i użyj funkcji haka powiadomień, aby wywołać akcję. Skonfigurowałem to za pomocą zapier.com (ale możesz użyć dowolnej dostosowywanej usługi webhook), aby utworzyć nowy problem w moim repozytorium github, który używa Alpine jako obrazu podstawowego.

    • Plusy: Możesz przejrzeć zmiany zgłoszone przez Microbadger w github przed podjęciem działania.
    • Minusy: Microbadger nie pozwala na śledzenie określonego tagu. Wygląda na to, że śledzi tylko „najnowsze”.
  2. Śledź kanał RSS dla git commits do nadrzędnego kontenera. dawny. https://github.com/gliderlabs/docker-alpine/commits/rootfs/library-3.8/x86_64 . Użyłem zapier.com do monitorowania tego kanału i wyzwalania automatycznej kompilacji mojego kontenera w Travis-CI za każdym razem, gdy coś zostało popełnione. Jest to trochę ekstremalne, ale możesz zmienić wyzwalacz, aby wykonywać inne czynności, takie jak otwieranie problemu w repozytorium git w celu ręcznej interwencji.

    • Plusy: Bliżej zautomatyzowanego rurociągu. Kompilacja Travis-CI sprawdza tylko, czy w kontenerze występują problemy z tym, co zostało zatwierdzone w podstawowym repozytorium obrazów. To od Ciebie zależy, czy usługa CI podejmie dalsze działania.
    • Minusy: Śledzenie pliku zatwierdzeń nie jest idealne. Wiele rzeczy zostaje przypisanych do repozytorium, które nie wpływają na kompilację obrazu podstawowego. Nie bierze pod uwagę żadnych problemów z częstotliwością / liczbą zatwierdzeń i ograniczeniem API.
2 stosy
źródło
3

Przesłanka do mojej odpowiedzi:

  1. Kontenery są uruchamiane za pomocą tagów.
  2. Ten sam tag można wskazać na inny UUID obrazu, jak nam się podoba / czujemy, że jest odpowiedni.
  3. Aktualizacje wykonane dla obrazu można przypisać do nowej warstwy obrazu

Podejście

  1. Zbuduj wszystkie kontenery przede wszystkim za pomocą skryptu aktualizacji zabezpieczeń
  2. Zbuduj zautomatyzowany proces dla następujących elementów
    • Uruchom istniejący obraz do nowego kontenera za pomocą skryptu poprawki zabezpieczeń jako polecenia
    • Zatwierdź zmiany w obrazie jako
      • istniejący znacznik -> następnie ponownie uruchamiaj kontenery jeden po drugim
      • tag nowej wersji -> zastąp kilka kontenerów nowym tagiem -> sprawdź poprawność -> przenieś wszystkie kontenery do nowego tagu

Dodatkowo obraz podstawowy można ulepszyć / kontener z kompletnie nowym obrazem podstawowym można budować w regularnych odstępach czasu, ponieważ opiekun uzna to za konieczne

Zalety

  1. Zachowujemy starą wersję obrazu podczas tworzenia nowego obrazu z poprawką bezpieczeństwa, dlatego w razie potrzeby możemy przywrócić poprzedni uruchomiony obraz
  2. Zachowujemy pamięć podręczną dokera, stąd mniej transferu sieci (tylko zmieniona warstwa dostaje się na drut)
  3. Proces aktualizacji można zweryfikować podczas przemieszczania przed przejściem do prod
  4. Może to być proces kontrolowany, dlatego łaty bezpieczeństwa można wprowadzać tylko wtedy, gdy jest to konieczne / uznane za ważne.
Phani
źródło
W środowisku produkcyjnym, chociaż są to aktualizacje zabezpieczeń, wątpię, czy chcesz mieć aktualizacje nienadzorowane! Jeśli konieczne są aktualizacje nienadzorowane, proces można uruchamiać w regularnych odstępach czasu (odpowiednio) jako zadanie CRON.
Phani,
1
Moje założenie jest takie, że aktualizacje bezpieczeństwa powinny pochodzić z obrazów nadrzędnych / podstawowych.
hbogert
@hbogert Wolę powiedzieć, że istnieje cienka linia rozróżnienia między teorią a praktyką. Kiedy wszystko wejdzie w życie, trzeba będzie wziąć pod uwagę wiele aspektów zewnętrznych, takich jak: koszt (nie tylko wartość dolara, ale także czas) związany z wdrożeniem.
Phani
3

Powyższe odpowiedzi są również poprawne

Istnieją dwa podejścia

  1. Użyj haków internetowych
  2. Uruchamiaj skrypt dla każdej konkretnej minuty, aby uzyskać nowy ciąg obrazów dokerów

Właśnie udostępniam skrypt, może ci to pomóc! Możesz go używać z cronjobem, próbowałem z powodzeniem na 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

Oto mój plik skomponowania dokera

version:  "3.2"
services:
  lamp-alpine:
    build:
      context: .
    container_name: "${CONTNAME}"
    image: "${ORG}/${IMGNAME}:${IMGTAG}"
    ports:
      - "127.0.0.1:80:80"
    networks:
      - private-network 

networks:
  private-network:
    driver: bridge
Akshay Shikre
źródło
3

Oto najprostszy sposób automatycznej aktualizacji kontenera dokowanego

Umieść pracę za pośrednictwem $ crontab -e:

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

Utwórz ~/.dockerkatalog z plikiem 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
źródło
0

próbowałeś tego: https://github.com/v2tec/watchtower . jest to proste narzędzie działające w kontenerze dokowanym, obserwujące inne kontenery, jeśli zmieni się ich podstawowy obraz, pociągnie i wdroży.

linehrr
źródło
-1

Prostym i doskonałym rozwiązaniem jest pasterz

użytkownik672009
źródło
iiuc, to nie pomaga w ogólnym sensie, ponieważ jest to sprzężone z Swarm i uruchamia się ponownie w górę, podczas gdy chcemy reagować, odbudowywać itp. na zmiany w górę, a nie po prostu restartować.
hbogert
To brzmi jak coś, co powinieneś zrobić w potoku CI
user672009,