ベースイメージが更新された場合に、Dockerコンテナーを自動的に更新する方法


205

に基づいた簡単なコンテナがあるとしましょうubuntu:latest。現在、セキュリティアップデートがありubuntu:latest、Dockerリポジトリで更新されています。

  1. ローカルイメージとそのコンテナーが背後で実行されていることをどのようにして知ることができますか?

  2. ローカルイメージとコンテナーを自動的に更新してdocker repoの更新を追跡するためのいくつかのベストプラクティスはありますか?


11
私はドッカーの始まり以来、これに対する答えを探しています。さらに少し複雑です。apache(たとえば)をインストールして更新した場合、後でインストールしたため、base-imageは変更されません。私はまだapacheの自動更新が欲しいです。私は実際にこれについてIRCに質問し、答えとして「アップストリームに従い、更新時に再構築する」を取得しました...
Mathias

8
不思議に思っているのは私だけではありません。開発と再現性は、Docker開発者にとって、これまで何年にもわたった賢明な更新メカニズムよりも重要であるようです。
hbogert 2014年

問題は、Dockerがコンテナーのテクノロジーにすぎないことです。エコシステムがそれを中心に進化するまでには時間がかかると思います。dockerがロギングのように対処しない他の問題があります。
Mathias

3
答えてくれた皆さんありがとう。賞金を分割できなかったのは残念です。私の問題に対する最終的な解決策はありませんでしたが、皆からの良い意見がありました。
Mathias

1
@Mathiasの場合、先ほど追加したソリューションには、プル後のコンテナーにインストールされているパッケージのセキュリティ更新をチェックするスクリプトがあります。また、ベースイメージをチェックするための個別のスクリプトもあります。
Fmstrat 2017年

回答:


8

これを行う方法の1つは、CI / CDシステムを通じてこれを実行することです。親イメージが構築されたら、その親を使用して画像のgitリポジトリをスキャンするものを用意します。見つかった場合は、プルリクエストを送信して、イメージの新しいバージョンにバンプします。すべてのテストに合格すると、プルリクエストがマージされ、更新された親に基づいて新しい子イメージが作成されます。このアプローチを取るツールの例は、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

そしてinitは次のようになります

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

1
この貴重な貢献に感謝します。これは、ベースイメージを更新するための良い方法のようです。残りの質問は、dockerfileのディストリビューションによってインストールされたアプリケーション(apacheなど)をどのように更新するかです。または、アプリケーションコードのみを必要とする既製のベースイメージ(ウェブサイトなど)のみを使用していますか?
Mathias 2014年

パッカーとパペットを使用してイメージを構成します。私たちの画像は、作成後に本番
環境

@Mathias、私の編集済みの回答を参照してください。実行中のすべてのコンテナーでLinux(現在はdebian / ubuntu)パッケージを更新するために使用している小さなツールdocker-runがあります。
iTech 11/05/14

3
画像は、容器(例えば同じ名前を持つ場合redis)、LATEST=`docker inspect --format "{{.Id}}" $IMAGE`コンテナ情報を取得します。これ--type imageを修正するために追加します。
パトリックフィッシャー2016年

1
投稿ありがとうございます。私は、ドッキングウィンドウから画像を取得するためにループ内全体をラップするためにそれを修正: for IMAGE in $(docker ps --format {{.Image}} -q | sort -u)
アルマン

25

「ドッカーの方法」は、ドッカーハブの 自動ビルドを使用することです。リポジトリのリンク上流のコンテナが再構築されたときに機能があなたのコンテナを再構築し、ウェブフック機能はあなたに通知を送信します。

WebhookはHTTP POST呼び出しに限定されているようです。それらをキャッチするサービスをセットアップするか、POSTの1つを使用してサービスをメールで送信する必要があります。

まだ調べていませんが、新しいDocker Universal Control Planeには、更新されたコンテナーを検出して再デプロイする機能があるかもしれません。


AMQPサービスへのWebhookを作成する必要がありました:github.com/goliatone/rabbithook
goliatone

残念ながら、上流のトリガーは使用できなくなりました:github.com/docker/hub-feedback/issues/1717
ジュリアンチャスタン

23

Watchtowerを使用して、コンテナーがインスタンス化されるイメージの更新を監視し、更新を自動的にプルして、更新されたイメージを使用してコンテナーを再起動できます。ただし、ベースとなっているアップストリームイメージに変更があった場合に、独自のカスタムイメージを再構築する問題は解決されません。これは、(1)アップストリームイメージがいつ更新されたかを知る、(2)実際のイメージの再構築を行う、という2つの部分からなる問題と見なすことができます。(1)はかなり簡単に解決できますが、(2)ローカルのビルド環境/プラクティスに大きく依存するため、そのための一般化されたソリューションを作成することはおそらくはるかに困難です。

Docker Hubの自動ビルドを使用できる場合は、リポジトリリンク機能を使用して問題全体を比較的きれいに解決できます。これにより、リンクされたリポジトリ(おそらく上流のもの)が更新されたときに自動的に再ビルドをトリガーできます。自動ビルドが発生したときに通知するようにWebhookを構成することもできます。メールまたはSMS通知が必要な場合は、WebhookをIFTTT Makerに接続できます。IFTTTのユーザーインターフェイスはややわかりにくいのですが、https: //maker.ifttt.com/trigger/ docker_xyz_image_built/ with / key / に投稿するようにDocker Webhookを構成しますyour_key

ローカルでビルドする必要がある場合は、対象のリポジトリにリンクされたDocker Hubにダミーのリポジトリを作成することで、アップストリームイメージが更新されたときに通知を受け取る問題を少なくとも解決できます。ダミーリポジトリの唯一の目的は、再構築されたときにWebhookをトリガーすることです(リンクされたリポジトリの1つが更新されたことを意味します)。このWebhookを受信できる場合は、それを使用して、サイドで再構築をトリガーすることもできます。


1
ものみの塔はドッキングソケットを使用します。ホストマシンへのrootアクセスを与えるセキュリティの観点から。
JoeG 2017

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

Watchtowerリポジトリは、containerrr / watchtowerに移行されたようです。同様の質問に対するこの回答で指摘されているように、 Dockerhub上のリンクされた自動ビルドにはいくつかの問題があります。
chrki

10

私は同じ問題を抱えており、unattended-upgrade毎日cronジョブを呼び出すことで簡単に解決できると思いました。

私の意図は、イメージを更新し、最新のセキュリティ更新で新しいDockerイメージをデプロイするのに時間がかかるため、本番コンテナーが安全で更新されることを保証する自動の迅速なソリューションとして提供することです。

Githubフックを使用してイメージのビルドとデプロイを自動化することもできます。

基本的なDockerイメージを作成しました。これにより、セキュリティアップデートが毎日自動的にチェックおよびインストールされます(で直接実行できます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コンテナーとして実行され、実行中のすべてのコンテナーまたは選択されたコンテナー内のパッケージを更新するために使用できる小さなツールdocker-runを開発しました。また、任意のコマンドの実行にも使用できます。

次のコマンドで簡単にテストできます。

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

デフォルトでは、実行date中のすべてのコンテナでコマンドを実行し、結果を表示します。update代わりに渡すexecと、実行中のすべてのコンテナで実行apt-get updateapt-get upgrade -yれます


無人アップグレードについての私の言及は、非ドッカー環境でのアナロジーを示すことだけでした。私の意図は、これをdockerの方法で解決することです(ocが存在する場合)。コンテナーに追加のプロセスがあることは、docker imoの目的に勝るものです。アップストリームによるイメージの更新と、ユーザーであるユーザーが実際に現在のコンテナーにイメージをデポジットするまでの遅延の問題にパッチを当てます。無人アップグレードの場合も、これには最大で1日かかることがあります。更新メカニズムがホストOSに大きく依存しているため、githubのリファレンスも不十分です。
hbogert 2014年

「ドッカー方式」は、それらが密接に関連していてスケーラビリティのボトルネックを作成しない場合、同じコンテナで他のプロセスを実行することを妨げません。そして、この特定のユースケースは、別の実行中のプロセスを持つコンテナを持つことができる良い例です。(たとえば、同じコンテナで複数の必須プロセスを実行するgitlabの画像を参照してください)。
iTech

画像の主な機能に密接に関連する更新メカニズムを呼び出すことはしません。このソリューションは、パッケージマネージャーに負担をかける代わりに、従来のマシン上のすべてのアプリケーションに独自の更新メカニズムを提供するようなものです。これは解決策ですが、ローカルイメージを自動的に更新してからコンテナーを再実行する必要があるという私の質問には答えません。コンテナ自体を更新することで、私たちにはまだわからない多くの状態が導入されています。
hbogert 2014年

1
Kubernetes大規模なインフラストラクチャの展開に役立つような、Dockerよりも高いレベルのものが必要になる場合がありますが、それでもGoogleによる開発が進んでいます。現時点では、Ansibleのようなプロビジョニングツールを使用して、これをかなり単純な方法で自動化できます。
iTech

あなたの引用された「異なるアプローチ」は私が探していたものかもしれません。あなた自身の貢献は、「脂肪コンテナ」の実行可能な代替手段のように見えます。私は間違いなく両方についてもう少し詳しく調べます。あなたの答えに感謝します。
Mathias 2014年

7

docker pullを実行しないと、コンテナーが遅れていることはわかりません。次に、イメージを再構築または再構成する必要があります。

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

コマンドは、アップグレードを完了するために必要な他のものと一緒にスクリプトに入れることができますが、適切なコンテナには追加のものが必要ありません。


1:わかりました、でも私はすべてのローカルイメージを見て、それらのベースイメージを取得し、それらをプルする必要があります。次に、ベースイメージが変更されたイメージを再構築します。次に、イメージが変更されたコンテナーを停止し、「docker run」と必要なパラメーターを使用してコンテナーを再作成します。これは過度に手動のようです。しかし、これが現状であれば、私はその答えを受け入れます。
hbogert 2014年

同意するまでお待ちください。多分そこに何かがあります。私はdockerを6か月間使用していますが、最新の開発に追いついていません。
seanmcl 2014年

どういうわけか、内部的には、Dockerは「キャッシング」機能を実行するためにイメージを比較できます。おそらく、それを活用する方法を見つけることができます。つまり、基になるイメージが(ベースに戻るまで)変更されているかどうかを確認し、再構築するプロセスをトリガーします。残念ながら、その場合、キャッシュは役に立ちません。ベースイメージが変更されたため、イメージ全体が再構築されます。
Thom Parkin

5

Dockerイメージの依存関係管理は実際の問題です。私はツールであるMicroBadgerを作成したチームの一員です。これは、コンテナーイメージを監視し、メタデータを検査することによってこれを支援します。その機能の1つは、関心のある画像(たとえば、基本画像)が変更されたときに呼び出される通知Webhookをセットアップできるようにすることです。


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、上部の変数を変更し、最後に電子メール通知コマンドを変更する必要があります。私にとっては、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を比較する必要があると想定します。trueの場合、これは、このスクリプトがインストール時に最初に実行されない限り、OPが望むことを実際には実行しないことを意味します。つまり、結果が以前の実行と異なる場合でも、何がインストールされているかを実際に決定するわけではありません...
JoeG

5

別のアプローチとして、ベースイメージが非常に早く遅れると想定し(そうなる可能性が高い)、アプリケーションの別のイメージビルドを定期的(たとえば、毎週)に強制し、変更があった場合は再デプロイします。

私が知る限り、公式のDebianやJavaなどの人気のあるベースイメージは、セキュリティ修正に対応するためにタグを更新しているため、タグは不変ではありません(参照[image:@digest ]、より最近のDockerバージョンで利用可能)。したがって、でイメージを作成する docker build --pull場合、アプリケーションは、参照しているベースイメージタグの最新かつ最大のものを取得する必要があります。

変更可能なタグは混乱を招く可能性があるため、これを行うたびにアプリケーションのバージョン番号をインクリメントして、少なくともあなたの側がよりクリーンになるようにするのが最善です。

したがって、前の回答のいずれかで提案されたスクリプトが機能するかどうかはわかりません。アプリケーションのイメージを再構築しないためです。ベースイメージタグを更新してからコンテナを再起動するだけですが、新しいコンテナはまだ参照しています。古いベースイメージハッシュ。

コンテナー(または本当に必要な場合を除いて、他のプロセス)でcronタイプのジョブを実行することは推奨しません。これは、コンテナーごとに1つのプロセスのみを実行するというマントラに反するためです(なぜこれが優れているかについてはさまざまな議論があります。 mはここには入りません)。


4

本番環境で無人アップデートを希望するかどうかという問題全体については説明しません(そうではないと思います)。誰かが便利だと思ったときのために、参考のためにここに置いておきます。端末で次のコマンドを使用して、すべてのdockerイメージを最新バージョンに更新します。

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


1
このコマンドはすべてのイメージを更新するのに役立ちますが、本番環境で実行されているものは何も変更しません。コンテナーはまだ古い画像から生じており、タグ付けされていません。
なし

そうだね。そして、これが本のもう1つです... # docker system prune -a --volumes -f古い(ぶら下がっている)画像、ボリュームなどのクリーンアップに使用します
Meferdati

4

UPDATE:使用Dependabot - https://dependabot.com/docker/

BLUF:コンテナーの変更を監視するための適切な挿入ポイントを見つけることは困難です。DockerHubがこれを解決できれば素晴らしいと思います。(リポジトリリンクについては触れましたが、DockerHubで設定する場合は、「Docker Hubでベースイメージが更新されるたびに、このリポジトリでビルドをトリガーしてください。非公式イメージでのみ機能します。」

これを自分で解決しようとしているときに、Webhookに関するいくつかの推奨事項を確認したので、使用したいくつかのソリューションについて詳しく説明したいと思いました。

  1. microbadger.comを使用してコンテナの変更を追跡し、その通知Webhook機能を使用してアクションをトリガーします。これをzapier.comで設定しました(ただし、カスタマイズ可能な任意のWebhookサービスを使用できます)。Alpineをベースイメージとして使用するgithubリポジトリに新しい問題を作成します。

    • 長所:アクションを実行する前に、githubのmicrobadgerによって報告された変更を確認できます。
    • 短所:Microbadgerでは特定のタグを追跡できません。「最新」のみを追跡しているようです。
  2. 上流のコンテナへのgit commitのRSSフィードを追跡します。例。https://github.com/gliderlabs/docker-alpine/commits/rootfs/library-3.8/x86_64。私はzapier.comを使用してこのフィードを監視し、何かがコミットされるたびにTravis-CIでコンテナーの自動ビルドをトリガーしました。これは少し極端ですが、トリガーを変更して、手動で介入するためにgitリポジトリで問題を開くなどの他のことを行うことができます。

    • 長所:自動化されたパイプラインに近い。Travis-CIビルドは、ベースイメージリポジトリにコミットされたすべての問題がコンテナにあるかどうかを確認するだけです。CIサービスがさらにアクションを実行するかどうかは、あなた次第です。
    • 短所:コミットフィードの追跡は完全ではありません。ベースイメージのビルドに影響を与えない多くのことがリポジトリにコミットされます。コミットの頻度/数、およびAPIスロットリングの問題を考慮に入れていません。

3

私の答えの前提:

  1. コンテナはタグ付きで実行されます。
  2. 同じタグが適切な/別の画像UUIDを指すようにすることができます。
  3. 画像に対して行われた更新は、新しい画像レイヤーにコミットできます

アプローチ

  1. 最初に、セキュリティパッチ更新スクリプトを使用してすべてのコンテナーをビルドします
  2. 次の自動プロセスを構築する
    • コマンドとしてセキュリティパッチスクリプトを使用して、既存のイメージを新しいコンテナに実行する
    • 画像への変更をコミット
      • 既存のタグ->コンテナを1つずつ再起動します
      • 新しいバージョンのタグ->いくつかのコンテナーを新しいタグで置き換え->検証->すべてのコンテナーを新しいタグに移動

さらに、メンテナーが必要と感じたときに、ベースイメージをアップグレードできます/完全な新しいベースイメージを含むコンテナーを定期的にビルドできます

メリット

  1. 新しいセキュリティパッチ済みイメージを作成している間、イメージの古いバージョンを保持しているため、必要に応じて以前の実行イメージにロールバックできます
  2. Dockerキャッシュを保持しているため、ネットワーク転送が少なくなります(変更されたレイヤーのみがネットワークに接続されます)
  3. アップグレードプロセスは、製品版に移行する前のステージングで検証できます
  4. これは制御されたプロセスである可能性があるため、必要または重要と思われる場合にのみセキュリティパッチを適用できます。

実稼働環境では、これらはセキュリティ更新プログラムですが、無人更新が必要になることはないと思います!無人更新が必要な場合、プロセスはcronジョブとして定期的に(必要に応じて)実行できます。
Phani 2015年

1
私の前提は、セキュリティアップデートはアップストリーム/ベースイメージから提供されることです。
hbogert 2015年

@hbogertむしろ理論と実践の間には微妙な違いがあると言いたいです。物事が現実になると、実装に関連するコスト(ドルの価値だけでなく、時間も)のような、考慮に入れる必要のある多くの外部の側面があります。
Phani 2015年

3

上記の回答も正しい

2つのアプローチがあります

  1. Webhookを使用する
  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

0

これを試しましたか:https : //github.com/v2tec/watchtower。これは、他のコンテナーを監視するdockerコンテナーで実行されるシンプルなツールです。ベースイメージが変更された場合、プルして再デプロイします。


-1

シンプルで優れたソリューションは羊飼いです


iiuc、これは一般的な意味では役に立ちません。これは、Swarmと連動して上流でのみ再起動するためです。一方、上流での変更に対応して再構築するだけで、単に再起動するのではありません。
hbogert

CIパイプラインで行うべきことのように聞こえます
user672009
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.