如何自动更新您的docker容器,如果基本图像更新

假设我有一个基于ubuntu:latest的普通容器。现在有一个安全更新,ubuntu:latest在docker repo中更新。

  1. 我如何知道我的本地映像及其容器运行落后?

  2. 是否有一些最佳实践来自动更新本地映像和容器来跟踪docker回购更新,这在实践中会给你同样的好处,让无人值守的升级运行在传统的ubuntu机器上

175676 次浏览

如果不运行码头工人拉,你不会知道你的容器落后了。然后你需要重建重新安排你的图像。

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

这些命令可以与完成升级所需的任何其他东西一起放在脚本中,尽管一个合适的容器不需要任何额外的东西。

我有同样的问题,并认为它可以通过每天调用unattended-upgrade的cron作业简单地解决。

我的意图是将其作为一种自动和快速的解决方案,以确保生产容器是安全和更新的,因为更新映像和部署具有最新安全更新的新docker映像需要花费一些时间。

也可以使用Github钩子来自动化映像的构建和部署

我已经创建了一个基本的码头工人形象,它每天自动检查和安装安全更新(可以直接通过docker run itech/docker-unattended-upgrade运行)。

我还遇到了另一个不同的方法来检查容器是否需要更新。

我的完整实现:

Dockerfile

FROM ubuntu:14.04


RUN apt-get update \
&& apt-get install -y supervisor unattended-upgrades \
&& rm -rf /var/lib/apt/lists/*


COPY install /install
RUN chmod 755 install
RUN /install


COPY start /start
RUN chmod 755 /start

辅助脚本

安装

#!/bin/bash
set -e


cat > /etc/supervisor/conf.d/cron.conf <<EOF
[program:cron]
priority=20
directory=/tmp
command=/usr/sbin/cron -f
user=root
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
EOF


rm -rf /var/lib/apt/lists/*


ENTRYPOINT ["/start"]

开始

#!/bin/bash


set -e


echo "Adding crontab for unattended-upgrade ..."
echo "0 0 * * * root /usr/bin/unattended-upgrade" >> /etc/crontab


# can also use @daily syntax or use /etc/cron.daily


echo "Starting supervisord ..."
exec /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf

编辑

我开发了一个小工具docker-run,它作为docker容器运行,可以用来更新所有或选定的运行容器中的包,它也可以用来运行任何任意命令。

可以使用以下命令轻松测试:

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

默认情况下,它将在所有运行的容器中执行date命令并显示结果。如果你传递update而不是exec,它将在所有运行的容器中执行apt-get updateapt-get upgrade -y

我们使用一个脚本来检查正在运行的容器是否以最新映像启动。我们还使用upstart init脚本来启动docker映像。

    #!/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. 容器使用标签运行。
  2. 相同的标签可以指向不同的图像UUID,因为我们喜欢/觉得合适。
  3. 对图像的更新可以提交到新的图像层

方法

  1. 首先使用安全补丁更新脚本构建所有容器
  2. 为以下内容构建一个自动化流程
    • 使用安全补丁脚本将现有映像运行到新容器
    • 提交对映像的更改为
      • 现有标记->,然后逐个重新启动容器
      • 新版本标签->用新标签替换少数容器->验证->将所有容器移动到新标签
      • 李< / ul > < / > 李< / ul > < / >

此外,可以升级基本映像/可以定期构建具有完整的新基本映像的容器,这是维护者认为必要的

优势

  1. 我们在创建新的安全补丁映像时保留映像的旧版本,因此如果需要,我们可以回滚到以前正在运行的映像
  2. 我们保留了docker缓存,从而减少了网络传输(只有被更改的层连接到网络上)
  3. 升级过程可以在过渡到产品化之前在阶段中进行验证
  4. 这可以是一个受控的过程,因此只有在必要/被认为重要时才可以推送安全补丁。

另一种方法是假设您的基本映像很快就会落后(这很可能发生),并定期强制应用程序构建另一个映像(例如每周),如果它发生了更改,则重新部署它。

据我所知,像官方Debian或Java这样的流行基础镜像会更新它们的标记来满足安全修复,所以标记不是不可变的(如果你想要更强的保证,你需要使用参考[image:@digest],在最新的Docker版本中可用)。因此,如果你要用docker build --pull构建你的映像,那么你的应用程序应该得到你引用的base image标签的最新和最大的值。

由于可变标记可能令人困惑,所以最好每次都增加应用程序的版本号,这样至少在您的方面,事情会更清楚。

因此,我不确定在前面的答案之一中建议的脚本是否能完成工作,因为它不重新构建应用程序的映像——它只是更新基本映像标记,然后重新启动容器,但新的容器仍然引用旧的基本映像散列。

我不提倡在容器中运行cron类型的作业(或任何其他进程,除非真的有必要),因为这违背了每个容器只运行一个进程的原则(关于为什么这样更好有各种各样的争论,所以我不打算在这里讨论)。

我不打算讨论您是否希望在生产中进行无人值守的更新(我认为不需要)。我只是把这个留在这里作为参考,以防有人觉得有用。在终端中使用以下命令将所有docker映像更新到最新版本:

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

“docker方法”是使用码头工人中心 自动化的构建。当上游容器被重建时,存储库链接特性将重建你的容器,并且人则特性将向你发送一个通知。

看起来webhooks仅限于HTTP POST调用。您需要设置一个服务来捕获它们,或者可能使用其中一个POST发送电子邮件服务。

我还没有深入研究,但是新的Docker通用控制平面可能有一个检测更新的容器和重新部署的功能。

Docker映像的依赖管理是一个真正的问题。我是一个团队的一员,该团队构建了一个工具MicroBadger,通过监视容器映像和检查元数据来帮助实现这一点。它的功能之一是让你设置一个通知网络钩子,当你感兴趣的图像(例如基本图像)发生变化时,它会被调用。

你可以使用瞭望塔来监视容器实例化的映像的更新,并自动提取更新并使用更新后的映像重新启动容器。然而,这并不能解决当其所基于的上游映像发生更改时重新构建自己的自定义映像的问题。您可以将此视为两个部分的问题:(1)知道上游映像何时更新,以及(2)进行实际的映像重建。(1)可以相当容易地解决,但(2)很大程度上取决于您本地的构建环境/实践,因此可能很难为此创建一个通用的解决方案。

如果你能够使用Docker Hub的自动化的构建,整个问题可以使用存储库链接特性相对干净地解决,该特性允许你在链接的存储库(可能是上游存储库)更新时自动触发重建。你也可以配置webhook,当自动构建发生时通知你。如果你想要一个电子邮件或短信通知,你可以将webhook连接到IFTTT制造商。我发现IFTTT用户界面有点混乱,但你可以配置Docker webhook来发布到https://maker.ifttt.com/trigger/“docker_xyz_image_built”/ /键/“your_key”

如果你需要在本地构建,你至少可以通过在Docker Hub中创建一个连接到你感兴趣的repo的虚拟repo来解决上游映像更新时收到通知的问题。虚拟回购的唯一目的是在重新构建时触发一个webhook(这意味着它的一个链接回购被更新)。如果你能收到这个webhook,你甚至可以用它来触发你这边的重建。

这里有很多答案,但没有一个符合我的需要。我想知道提问者第一个问题的确切答案。如何知道hub.docker.com上的图像何时更新?

下面的脚本可以每天运行。在第一次运行时,它从HUB注册中心获得标记的基线和更新日期,并将它们保存在本地。从那时起,每次运行它都会检查注册表中的新标记和更新日期。因为每当有新图像存在时,它都会改变,所以它会告诉我们基本图像是否发生了变化。以下是剧本:

#!/bin/bash


DATAPATH='/data/docker/updater/data'


if [ ! -d "${DATAPATH}" ]; then
mkdir "${DATAPATH}";
fi
IMAGES=$(docker ps --format "\{\{.Image}}")
for IMAGE in $IMAGES; do
ORIGIMAGE=${IMAGE}
if [[ "$IMAGE" != *\/* ]]; then
IMAGE=library/${IMAGE}
fi
IMAGE=${IMAGE%%:*}
echo "Checking ${IMAGE}"
PARSED=${IMAGE//\//.}
if [ ! -f "${DATAPATH}/${PARSED}" ]; then
# File doesn't exist yet, make baseline
echo "Setting baseline for ${IMAGE}"
curl -s "https://registry.hub.docker.com/v2/repositories/${IMAGE}/tags/" > "${DATAPATH}/${PARSED}"
else
# File does exist, do a compare
NEW=$(curl -s "https://registry.hub.docker.com/v2/repositories/${IMAGE}/tags/")
OLD=$(cat "${DATAPATH}/${PARSED}")
if [[ "${VAR1}" == "${VAR2}" ]]; then
echo "Image ${IMAGE} is up to date";
else
echo ${NEW} > "${DATAPATH}/${PARSED}"
echo "Image ${IMAGE} needs to be updated";
H=`hostname`
ssh -i /data/keys/<KEYFILE> <USER>@<REMOTEHOST>.com "{ echo \"MAIL FROM: root@${H}\"; echo \"RCPT TO: <USER>@<EMAILHOST>.com\"; echo \"DATA\"; echo \"Subject: ${H} - ${IMAGE} needs update\"; echo \"\"; echo -e \"\n${IMAGE} needs update.\n\ndocker pull ${ORIGIMAGE}\"; echo \"\"; echo \".\"; echo \"quit\"; sleep 1; } | telnet <SMTPHOST> 25"
fi


fi
done;

你会想要改变顶部的DATAPATH变量,并改变末尾的电子邮件通知命令以适应你的需要。对我来说,我把它SSH到我的SMTP所在的另一个网络上的服务器上。但是你也可以很容易地使用mail命令。

现在,您还需要检查容器本身中是否有更新的包。这实际上可能比在容器工作后“拉”更有效。以下是实现这一目标的脚本:

#!/bin/bash




function needsUpdates() {
RESULT=$(docker exec ${1} bash -c ' \
if [[ -f /etc/apt/sources.list ]]; then \
grep security /etc/apt/sources.list > /tmp/security.list; \
apt-get update > /dev/null; \
apt-get upgrade -oDir::Etc::Sourcelist=/tmp/security.list -s; \
fi; \
')
RESULT=$(echo $RESULT)
GOODRESULT="Reading package lists... Building dependency tree... Reading state information... Calculating upgrade... 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded."
if [[ "${RESULT}" != "" ]] && [[ "${RESULT}" != "${GOODRESULT}" ]]; then
return 0
else
return 1
fi
}


function sendEmail() {
echo "Container ${1} needs security updates";
H=`hostname`
ssh -i /data/keys/<KEYFILE> <USRER>@<REMOTEHOST>.com "{ echo \"MAIL FROM: root@${H}\"; echo \"RCPT TO: <USER>@<EMAILHOST>.com\"; echo \"DATA\"; echo \"Subject: ${H} - ${1} container needs security update\"; echo \"\"; echo -e \"\n${1} container needs update.\n\n\"; echo -e \"docker exec ${1} bash -c 'grep security /etc/apt/sources.list > /tmp/security.list; apt-get update > /dev/null; apt-get upgrade -oDir::Etc::Sourcelist=/tmp/security.list -s'\n\n\"; echo \"Remove the -s to run the update\"; echo \"\"; echo \".\"; echo \"quit\"; sleep 1; } | telnet <SMTPHOST> 25"
}


CONTAINERS=$(docker ps --format "\{\{.Names}}")
for CONTAINER in $CONTAINERS; do
echo "Checking ${CONTAINER}"
if needsUpdates $CONTAINER; then
sendEmail $CONTAINER
fi
done

其中一种方法是通过CI/CD系统来实现。一旦你的父映像被构建,有一些东西扫描你的git回购使用父映像的映像。如果找到了,就会发送一个pull请求,以碰撞到图像的新版本。如果所有测试都通过,则将合并拉取请求,并且您将拥有基于更新的父映像的新子映像。可以在这里找到采用这种方法的工具示例:https://engineering.salesforce.com/open-sourcing-dockerfile-image-update-6400121c1a75

如果你不控制你的父映像,就像你依赖于官方ubuntu映像的情况一样,你可以编写一些工具来检测父映像标记或校验和(不是一回事,标记是可变的)的变化,并相应地调用子映像构建。

以上答案也是正确的

有两种方法

  1. 使用的人
  2. 每隔一分钟运行脚本以获取新的docker映像

我只是分享脚本可能会对你有帮助! 你可以使用cronjob,我在OSX

上成功尝试过
#!/bin/bash
##You can use below commented line for setting cron tab for running cron job and to store its O/P in one .txt file
#* * * * * /usr/bin/sudo -u admin -i bash -c /Users/Swapnil/Documents/checkimg.sh > /Users/Swapnil/Documents/cron_output.log 2>&1
# Example for the Docker Hub V2 API
# Returns all images and tags associated with a Docker Hub organization account.
# Requires 'jq': https://stedolan.github.io/jq/


# set username, password, and organization
# Filepath where your docker-compose file is present
FILEPATH="/Users/Swapnil/Documents/lamp-alpine"
# Your Docker hub user name
UNAME="ur username"
# Your Docker hub user password
UPASS="ur pwd"
# e.g organisation_name/image_name:image_tag
ORG="ur org name"
IMGNAME="ur img name"
IMGTAG="ur img tag"
# Container name
CONTNAME="ur container name"
# Expected built mins
BUILDMINS="5"
#Generally cronjob frequency
CHECKTIME="5"
NETWORKNAME="${IMGNAME}_private-network"
#After Image pulling, need to bring up all docker services?
DO_DOCKER_COMPOSE_UP=true
# -------
echo "Eecuting Script @ date and time in YmdHMS: $(date +%Y%m%d%H%M%S)"
set -e
PIDFILE=/Users/Swapnil/Documents/$IMGNAME/forever.pid
if [ -f $PIDFILE ]
then
PID=$(cat $PIDFILE)
ps -p $PID > /dev/null 2>&1
if [ $? -eq 0 ]
then
echo "Process already running"
exit 1
else
## Process not found assume not running
echo $$
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
echo "Could not create PID file"
exit 1
fi
fi
else
echo $$ > $PIDFILE
if [ $? -ne 0 ]
then
echo "Could not create PID file"
exit 1
fi
fi


# Check Docker is running or not; If not runing then exit
if docker info|grep Containers ; then
echo "Docker is running"
else
echo "Docker is not running"
rm $PIDFILE
exit 1
fi


# Check Container is running or not; and set variable
CONT_INFO=$(docker ps -f "name=$CONTNAME" --format "\{\{.Names}}")
if [ "$CONT_INFO" = "$CONTNAME" ]; then
echo "Container is running"
IS_CONTAINER_RUNNING=true
else
echo "Container is not running"
IS_CONTAINER_RUNNING=false
fi




# get token
echo "Retrieving token ..."
TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${UNAME}'", "password": "'${UPASS}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token)


# get list of repositories
echo "Retrieving repository list ..."
REPO_LIST=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/?page_size=100 | jq -r '.results|.[]|.name')


# output images & tags
echo "Images and tags for organization: ${ORG}"
echo
for i in ${REPO_LIST}
do
echo "${i}:"
# tags
IMAGE_TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${i}/tags/?page_size=100 | jq -r '.results|.[]|.name')
for j in ${IMAGE_TAGS}
do
echo "  - ${j}"
done
#echo
done


# Check Perticular image is the latest or not
#imm=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${IMGNAME}/tags/?page_size=100)
echo "-----------------"
echo "Last built date details about Image ${IMGNAME} : ${IMGTAG} for organization: ${ORG}"
IMAGE_UPDATED_DATE=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${ORG}/${IMGNAME}/tags/?page_size=100 | jq -r '.results|.[]|select(.name | contains("'${IMGTAG}'")).last_updated')
echo "On Docker Hub IMAGE_UPDATED_DATE---$IMAGE_UPDATED_DATE"
echo "-----------------"


IMAGE_CREATED_DATE=$(docker image inspect ${ORG}/${IMGNAME}:${IMGTAG} | jq -r '.[]|.Created')
echo "Locally IMAGE_CREATED_DATE---$IMAGE_CREATED_DATE"


updatedDate=$(date -jf '%Y-%m-%dT%H:%M' "${IMAGE_UPDATED_DATE:0:16}" +%Y%m%d%H%M%S)
createdDate=$(date -jf '%Y-%m-%dT%H:%M' "${IMAGE_CREATED_DATE:0:16}" +%Y%m%d%H%M%S)
currentDate=$(date +%Y%m%d%H%M%S)


start_date=$(date -jf "%Y%m%d%H%M%S" "$currentDate" "+%s")
end_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s")
updiffMins=$(( ($start_date - $end_date) / (60) ))
if [[ "$updiffMins" -lt $(($CHECKTIME+1)) ]]; then
if [ ! -d "${FILEPATH}" ]; then
mkdir "${FILEPATH}";
fi
cd "${FILEPATH}"
pwd
echo "updatedDate---$updatedDate" > "ScriptOutput_${currentDate}.txt"
echo "createdDate---$createdDate" >> "ScriptOutput_${currentDate}.txt"
echo "currentDate---$currentDate" >> "ScriptOutput_${currentDate}.txt"
echo "Found after regular checking time -> Docker hub's latest updated image is new; Diff ${updiffMins} mins" >> "ScriptOutput_${currentDate}.txt"
echo "Script is checking for latest updates after every ${CHECKTIME} mins" >> "ScriptOutput_${currentDate}.txt"
echo "Fetching all new"
echo "---------------------------"
if $IS_CONTAINER_RUNNING ; then
echo "Container is running"
else
docker-compose down
echo "Container stopped and removed; Network removed" >> "ScriptOutput_${currentDate}.txt"
fi
echo "Image_Created_Date=$currentDate" > ".env"
echo "ORG=$ORG" >> ".env"
echo "IMGNAME=$IMGNAME" >> ".env"
echo "IMGTAG=$IMGTAG" >> ".env"
echo "CONTNAME=$CONTNAME" >> ".env"
echo "NETWORKNAME=$NETWORKNAME" >> ".env"
docker-compose build --no-cache
echo "Docker Compose built" >> "ScriptOutput_${currentDate}.txt"
if $DO_DOCKER_COMPOSE_UP ; then
docker-compose up -d
echo "Docker services are up now, checked in" >> "ScriptOutput_${currentDate}.txt"
else
echo "Docker services are down, checked in" >> "ScriptOutput_${currentDate}.txt"
fi
elif [[ "$updatedDate" -gt "$createdDate" ]]; then
echo "Updated is latest"
start_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s")
end_date=$(date -jf "%Y%m%d%H%M%S" "$createdDate" "+%s")
diffMins=$(( ($start_date - $end_date) / (60) ))
if [[ "$BUILDMINS" -lt "$diffMins" ]]; then
if [ ! -d "${FILEPATH}" ]; then
mkdir "${FILEPATH}";
fi
cd "${FILEPATH}"
pwd
echo "updatedDate---$updatedDate" > "ScriptOutput_${currentDate}.txt"
echo "createdDate---$createdDate" >> "ScriptOutput_${currentDate}.txt"
echo "currentDate---$currentDate" >> "ScriptOutput_${currentDate}.txt"
echo "Found after comparing times -> Docker hub's latest updated image is new; Diff ${diffMins} mins" >> "ScriptOutput_${currentDate}.txt"
echo "Actual image built time is less i.e. ${diffMins} mins than MAX expexted BUILD TIME i.e. ${BUILDMINS} mins" >> "ScriptOutput_${currentDate}.txt"
echo "Fetching all new" >> "ScriptOutput_${currentDate}.txt"
echo "-----------------------------"
if $IS_CONTAINER_RUNNING ; then
echo "Container is running"
else
docker-compose down
echo "Container stopped and removed; Network removed" >> "ScriptOutput_${currentDate}.txt"
fi
echo "Image_Created_Date=$currentDate" > ".env"
echo "ORG=$ORG" >> ".env"
echo "IMGNAME=$IMGNAME" >> ".env"
echo "IMGTAG=$IMGTAG" >> ".env"
echo "CONTNAME=$CONTNAME" >> ".env"
echo "NETWORKNAME=$NETWORKNAME" >> ".env"
docker-compose build --no-cache
echo "Docker Compose built" >> "ScriptOutput_${currentDate}.txt"
if $DO_DOCKER_COMPOSE_UP ; then
docker-compose up -d
echo "Docker services are up now" >> "ScriptOutput_${currentDate}.txt"
else
echo "Docker services are down" >> "ScriptOutput_${currentDate}.txt"
fi
elif [[ "$BUILDMINS" -gt "$diffMins" ]]; then
echo "Docker hub's latest updated image is NOT new; Diff ${diffMins} mins"
echo "Docker images not fetched"
else
echo "Docker hub's latest updated image is NOT new; Diff ${diffMins} mins"
echo "Docker images not fetched"
fi
elif [[ "$createdDate" -gt "$updatedDate" ]]; then
echo "Created is latest"
start_date=$(date -jf "%Y%m%d%H%M%S" "$createdDate" "+%s")
end_date=$(date -jf "%Y%m%d%H%M%S" "$updatedDate" "+%s")
echo "Docker hub has older docker image than local; Older than $(( ($start_date - $end_date) / (60) ))mins"
fi
echo
echo "------------end---------------"
rm $PIDFILE

这是我的docker-compose文件

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


networks:
private-network:
driver: bridge

一个简单而伟大的解决方案是牧羊人

更新:使用Dependabot - https://dependabot.com/docker/

BLUF:找到正确的插入点来监视容器的更改是一个挑战。如果DockerHub能解决这个问题,那就太好了。(存储库链接已经提到了,但请注意在DockerHub - 每当Docker Hub上的基本映像更新时,都会触发此存储库中的构建。只适用于非官方图片。”上设置它们时)

当我自己尝试解决这个问题时,我看到了几个webhook的建议,所以我想详细说明我使用过的几个解决方案。

  1. 使用microbadger.com跟踪容器中的变化并使用它的 通知webhook功能来触发一个动作。我设置了这个 zapier.com(但你可以使用任何可定制的webhook服务) 在我的github存储库中创建一个新问题,使用Alpine作为 基地形象。< / p >

    • 优点:在采取行动之前,您可以在github中查看microbadger报告的更改。
    • 缺点:Microbadger不能让你追踪特定的标签。看起来它只追踪“最新”。
    • 李< / ul > < / >
    • 跟踪git提交到上游容器的RSS提要。https://github.com/gliderlabs/docker-alpine/commits/rootfs/library-3.8/x86_64。我使用zapier.com来监视这个提要,并在任何时候提交一些东西时触发在Travis-CI中自动构建我的容器。这有点极端,但您可以更改触发器来做其他事情,例如在git存储库中打开一个问题以进行手动干预。

      • 优点:更接近自动化管道。Travis-CI构建只是检查你的容器是否有提交到基本映像存储库的任何问题。您的CI服务是否采取进一步的行动取决于您。
      • 缺点:跟踪提交提要并不完美。提交给存储库的很多东西都不会影响基本映像的构建。没有考虑到提交频率/数量和任何API节流的任何问题。
      • 李< / ul > < / >

你有没有试过这个:https://github.com/v2tec/watchtower。 它是一个简单的工具,运行在docker容器中,监视其他容器,如果它们的基本映像改变了,它将拉出并重新部署。< / p >

下面是一种自动更新docker容器的最简单方法

通过$ crontab -e放置作业:

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

用文件cron.sh创建目录~/.docker:

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