我正在尝试创建一个可以重新启动自己的脚本,一个微服务(在我的例子中是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_on
long-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
请根据需要随意调整持续时间值。
这能解决您的问题吗?