docker 不断重新启动,直到在挂载的卷中创建文件



我正在尝试创建一个可以重新启动自己的脚本,一个微服务(在我的例子中是node-red)。

这是我的 docker 撰写文件:

docker-compose.yml 
version: '2.1'
services:
wifi-connect:
build: ./wifi-connect
restart: always
network_mode: host
privileged: true
google-iot:
build: ./google-iot
volumes:
- 'app-data:/data'
restart: always
network_mode: host
depends_on:
- "wifi-connect"
ports:
- "8883:8883"
node-red:
build: ./node-red/node-red
volumes:
- 'app-data:/data'
restart: always
privileged: true
network_mode: host
depends_on:
- "google-iot"
volumes:
app-data:

我正在使用 wait-for-it.sh 来检查以前的容器是否。

下面是节点红色微服务的 Dockerfile 的摘录。

RUN chmod +x ./wait-for-it/wait-for-it.sh
# server.js will run when container starts up on the device
CMD ["bash", "/usr/src/app/start.sh", "bash", "/usr/src/app/wait-for-it/wait-for-it.sh google-iot:8883 -- echo Google IoT Service is up and running"]

我看过inotify.

基本上我想要的只是在挂载到node-red容器的app-data卷内创建文件后重新启动容器node-red/data文件夹路径下,例如文件路径将是:/data/myfile.txt

请注意,此文件自动生成到google-iot微服务,但node-red容器需要该文件,并且通常node-red容器启动并且/data/myfile.txt文件不存在。

听起来您正在尝试延迟一个容器的启动,直到另一个容器生成了您要查找的文件,或者如果它不可用则退出。

您可以相当直接地将该逻辑写入 shell 脚本。 例如:

#!/bin/sh
# entrypoint.sh
# Wait for the server to be available
./wait-for-it/wait-for-it.sh google-iot:8883
if [ $? -ne 0 ]; then
echo 'google-iot container did not become available' >&2
exit 1
fi
# Wait for the file to be present
seconds=30
while [ $seconds -gt 0 ]; do
if [ -f /data/myfile.txt ]; then
break
fi
sleep 1
seconds=$(($seconds-1))
done
if [ $seconds -eq 0 ]; then
echo '/data/myfile.txt was not created' >&2
exit 1
fi
# Run the command passed to us as arguments
exec "$@"

在您的 Dockerfile 中,将此脚本设为ENTRYPOINT。 必须在ENTRYPOINT行中使用 JSON 数组语法。 您的CMD可以使用任何有效的语法。 请注意,我们在入口点包装器中运行wait-for-it脚本,因此您无需将其包含在CMD中。 (由于脚本是可执行的,并且以"shebang"行#!/bin/sh开头,我们不需要显式命名解释器来运行它。

# Dockerfile
RUN chmod +x entrypoint.sh wait-for-it/wait-for-it.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
CMD ["/usr/src/app/start.sh"]

入口点包装器有两个检查,首先检查google-iot容器最终接受端口 8883 上的 TCP 连接,第二个检查是否创建文件。 如果其中任何一种情况失败,则脚本在运行CMD之前exit 1。 这将导致容器作为一个整体退出并带有该状态代码(restart: on-failure仍将重新启动它)。

我还可以考虑获取文件的其他方法是否可行,例如使用curl向其他容器发出 HTTP 请求。 共享 Docker 卷存在几个实际问题(特别是在所有权方面,但如果文件的旧副本仍然存在于以前的运行中),并且共享文件在像 Kubernetes 这样的集群环境中效果尤其糟糕。

您可以使用depends_onlong-syntax来修复争用条件问题,您可以在其中指定运行状况检查。这将保证在node-red服务运行时文件存在。

node-red:
build: ./node-red/node-red
volumes:
- 'app-data:/data'
restart: always
privileged: true
network_mode: host
depends_on:
google-iot:
condition: service_healthy

然后,您可以定义一个health-check(请参阅此处的文档)以查看您的文件是否存在于卷中。您可以将以下内容添加到google-iot服务的服务描述中:

healthcheck:
test: ["CMD", "cat", "/data/myfile.txt"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s

请根据需要随意调整持续时间值。

这能解决您的问题吗?

最新更新