Docker容器自动更新利器-WatchTower使用手册
最近在弄私服Docker容器相关的内容, 因为需要测试构建好的容器,
每次都是先docker rm -f xxx然后再docker run -d xxxx属实效率太低,
就想着找一个可以自动更新容器镜像的工具, 做到无感更新.
第一时间就想到了containrrr/watchtower这个工具, 说实话,
这个工具我老早就在用, 只不过一直都是官方的quickstart方式使用,
没深入了解, 这次就遇到坑了, 因此记录一下.
无法连接到私服
阅读在DockerHub上的文档, 这个工具的quickstart方式为
1 | docker run -d \ |
并且, 上面的链接给出了官方文档地址1, 通过阅读官方文档的介绍信息2, 其中明确的说明了以下内容:
Watchtower is an application that will monitor your running Docker containers and watch for changes to the images that those containers were originally started from. If watchtower detects that an image has changed, it will automatically restart the container using the new image.
With watchtower you can update the running version of your containerized app simply by pushing a new image to the Docker Hub or your own image registry. Watchtower will pull down your new image, gracefully shut down your existing container and restart it with the same options that were used when it was deployed initially.
简单概括就是Watchtower可以无感知的自动使用原有启动参数更新现有容器的镜像,
通过阅读使用参数3,
其中指出可以添加--run-once的方式单次执行该工具, 如下
1 | docker run --rm \ |
先单次执行一下试试看是否可用
如上面展示的, 无法链接到私服, 很明显我并未提供用户名密码等信息, 因此报错是正常的, 通过查阅官方的使用概览4, 其中提到了私服相关的信息
If pulling images from private Docker registries, supply registry authentication credentials with the environment variables
REPO_USERandREPO_PASSor by mounting the host's docker config file into the container (at the root of the container filesystem/).Passing environment variables:
1
2
3
4
5
6 >docker run -d \
--name watchtower \
-e REPO_USER=username \
-e REPO_PASS=password \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower container_to_watch --debugAlso check out this Stack Overflow answer for more options on how to pass environment variables.
Mounting the host's docker config file:
1
2
3
4
5 >docker run -d \
--name watchtower \
-v /home/<user>/.docker/config.json:/config.json \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower container_to_watch --debug
其中提供了两种方法, 一种是通过环境变量,
一种是通过挂载宿主机的认证文件, 由于公司有多个私服,
并且直接写用户名密码的方式有些粗暴不安全, 而且也非常不优雅,
常写Python的我肯定无法接收第一种方法, 因此采取了挂载宿主机文件的方式,
不过这个方式有个严重的问题, 官方文档里也明确提到
Changes to config.json while running
If you mount
config.jsonin the manner above, changes from the host system will (generally) not be propagated to the running container. Mounting files into the Docker daemon uses bind mounts, which are based on inodes. Most applications (includingdocker loginandvim) will not directly edit the file, but instead make a copy and replace the original file, which results in a new inode which in turn breaks the bind mount. As a workaround, you can create a symlink to yourconfig.jsonfile and then mount the symlink in the container. The symlinked file will always have the same inode, which keeps the bind mount intact and will ensure changes to the original file are propagated to the running container (regardless of the inode of the source file!).
翻译一下, 主要是以下几点:
- 挂载的config.json文件==一般不会==实时地反馈到正在运行的容器中
- 因为大部分挂载为
bind mount, 是通过inodes5方式实现, 而大部分应用对于更新文件的操作是创建一个新的副本并替换源文件, 因此会导致inodes变化, 进而中断bind mount - 作为一个==解决方法==(并非Solution6),
可以通过创建一个软连接, 然后挂载软连接的方式解决,
因为软连接不会改变
inodes
因此, 在我的情况下, 启动Watchtower的命令为
1 | # Make a soft link |
其中--cleanup命令是指清理none的镜像和无用的中间层镜像,
更多参数见7
更多关于私服的使用方法, 如ECR等, 参见: Private registries - Watchtower
长期运行, 执行以下
1 | # Make a soft link |