英文:
Using docker watch feature for CI/CD
问题
我对“实验性”的Docker Compose监视功能很感兴趣:[1] [2]。
可用的两种操作是“同步”和“重建”(实际上是重建+重启)。
我需要这个功能来实现持续部署:我只希望Docker能够检测到我已更改了.env
或docker-compose.yml
文件(通过更新要拉取的镜像版本) - 然后重新启动容器。不需要重新构建,因为我首先并未构建镜像,而是从Docker注册表中拉取它。
我该如何做到这一点?
英文:
I'm interested in the "experimental" docker compose watch feature: [1] [2].
The two actions available are "sync" and "rebuild" (which is actually rebuild + restart).
I need this for continuous deployment: all I want is docker to detect that I've changed the .env
or docker-compose.yml
file (by updating the image version to be pulled) - and to restart the container. No rebuilding is necessary, as I'm not building the image in the first place but rather pulling it from a docker registry.
How can I do that?
答案1
得分: 1
我已尝试了许多方法,似乎不可能在修改.env
或docker-compose.yml
时更新/重新启动容器。由于某种原因,更改这些文件会重新启动容器,但不会遵守更改。
但是,你可以实现你想要的效果,但不是修改.env
或docker-compose.yml
,而是需要定义一个中间的Dockerfile
,然后直接对该文件进行更改。对我来说,这更容易,因为所有更改都局限于该Dockerfile
。你可以在docker-compose.yml
中定义以下内容:
services:
myapp:
build:
context: ./myapp
x-develop:
watch:
- action: rebuild
path: ./myapp/Dockerfile
无论如何,以下是一个示例,使用来自DockerHub的envoyproxy/envoy
镜像。
示例
具有以下目录结构:
$ tree
.
├── docker-compose.yml
└── envoy
├── Dockerfile
└── envoy.yaml # 没关系,这只是一个虚拟的配置文件
以及以下文件:
envoy/Dockerfile
FROM envoyproxy/envoy:v1.27.0
ENV ENVOY_UID=1234
docker-compose.yml
:
version: '3'
services:
envoy:
build:
context: ./envoy
ports:
- "9901:9901"
volumes:
- ./envoy/envoy.yaml:/etc/envoy/envoy.yaml
x-develop:
watch:
- action: rebuild
path: ./envoy/Dockerfile
对于你在问题中提到的对envoy/Dockerfile
的任何更改,比如:
- 更新镜像(
FROM
指令):相当于在你的问题中更改docker-compose.yml
中的镜像 - 更新/添加/删除环境变量(
ENV
指令):相当于在你的问题中更改.env
都将触发镜像的重建,并使用新值重新启动。
你可以通过执行以下操作来测试它是否正常工作:
$ docker compose up -d 2>/dev/null
$ docker compose alpha watch
然后在另一个窗口中:
$ # 检查 envoy 版本(与 Dockerfile 中的版本匹配)
$ curl -s http://localhost:9901/server_info | jq -r .version | cut -d / -f 2
1.27.0
$ # 检查 ENVOY_UID 环境变量
$ docker inspect 76803907-using-docker-watch-feature-for-ci-cd-envoy | jq -r '.[0].Config.Env' | grep 'ENVOY_UID'
"ENVOY_UID=1234"
$ # 进行一些更改(镜像版本、环境变量)
$ sed -i -e 's/v1.27.0/v1.21.0/' -e 's/ENVOY_UID=1234/ENVOY_UID=5678/' envoy/Dockerfile
$ # 等待几秒钟,直到 docker compose 重新启动容器...
$ sleep 5
$ # 检查 envoy 版本已更新!
$ curl -s http://localhost:9901/server_info | jq -r .version | cut -d / -f 2
1.21.0
$ # 检查 ENVOY_UID 环境变量已更新!
$ docker inspect 76803907-using-docker-watch-feature-for-ci-cd-envoy | jq -r '.[0].Config.Env' | grep 'ENVOY_UID'
"ENVOY_UID=5678"
英文:
I've tried many things, and it does not seem possible to update/restart the containers when modifying either .env
or docker-compose.yml
. For some reason, changing these files restarts the container, but does not honor the changes.
However, you can achieve what you want, but instead of modifying .env
or docker-compose.yml
, it requires defining an intermediate Dockerfile
and make changes to that file directly. To me, it's even easier because all changes are localized to that Dockerfile
. And you can define the following in your docker-compose.yml
:
services:
myapp:
build:
context: ./myapp
x-develop:
watch:
- action: rebuild
path: ./myapp/Dockerfile
Anyway, here's an example below with envoyproxy/envoy
image from DockerHub.
Example
With the following directory structure:
$ tree
.
├── docker-compose.yml
└── envoy
├── Dockerfile
└── envoy.yaml # it does not matter, it's just a dummy config file
And the following files:
envoy/Dockerfile
FROM envoyproxy/envoy:v1.27.0
ENV ENVOY_UID=1234
docker-compose.yml
:
version: '3'
services:
envoy:
build:
context: ./envoy
ports:
- "9901:9901"
volumes:
- ./envoy/envoy.yaml:/etc/envoy/envoy.yaml
x-develop:
watch:
- action: rebuild
path: ./envoy/Dockerfile
Any changes to envoy/Dockerfile
you've asked in your question, like:
- updating the image (
FROM
directive): equivalent of changing the image indocker-compose.yml
in your question - updating/adding/removing an environment variable (
ENV
directive): equivalent of changing the.env
in your question
will trigger a rebuild of the image, and restart with the new values.
You can test it works by doing:
$ docker compose up -d 2>/dev/null
$ docker compose alpha watch
And in another window:
$ # check envoy version (matches the version in Dockerfile)
$ curl -s http://localhost:9901/server_info | jq -r .version | cut -d / -f 2
1.27.0
$ # check ENVOY_UID env var
$ docker inspect 76803907-using-docker-watch-feature-for-ci-cd-envoy | jq -r '.[0].Config.Env' | grep 'ENVOY_UID'
"ENVOY_UID=1234"
$ # make some changes (image version, env var)
$ sed -i -e 's/v1.27.0/v1.21.0/' -e 's/ENVOY_UID=1234/ENVOY_UID=5678/' envoy/Dockerfile
$ # wait a few seconds while docker compose is restarting the container...
$ sleep 5
$ # check envoy version has been updated!
$ curl -s http://localhost:9901/server_info | jq -r .version | cut -d / -f 2
1.21.0
$ # check ENVOY_UID env var has been updated!
$ docker inspect 76803907-using-docker-watch-feature-for-ci-cd-envoy | jq -r '.[0].Config.Env' | grep 'ENVOY_UID'
"ENVOY_UID=5678"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论