首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >docker继续重新启动,直到在挂载的卷中创建文件为止。

docker继续重新启动,直到在挂载的卷中创建文件为止。
EN

Stack Overflow用户
提问于 2022-07-09 22:36:13
回答 2查看 66关注 0票数 0

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

这是我的对接者撰写文件:

代码语言:javascript
复制
docker-compose.yml 
代码语言:javascript
复制
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的摘录。

代码语言:javascript
复制
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

基本上,我想要的是在app-data卷中创建了一个文件之后重新启动容器app-data,该卷被挂载到node-red容器以及/data文件夹路径下,例如,文件路径是:/data/myfile.txt

请注意,这个文件是自动生成到google-iot微服务的,但是node-red容器需要该文件,并且经常是node-red容器启动而/data/myfile.txt文件不存在的情况。

EN

回答 2

Stack Overflow用户

发布于 2022-07-10 00:42:02

这听起来像是在尝试延迟一个容器的启动,直到另一个容器生成了您想要的文件,或者在它不可用的情况下退出。

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

代码语言:javascript
复制
#!/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开头,所以我们不需要显式地命名解释器来运行它。)

代码语言:javascript
复制
# 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连接,另一个是创建文件。如果这些情况中的任何一种都失败了,脚本exit 1在运行CMD之前就会失败。这将导致容器作为一个整体使用该状态代码退出( restart: on-failure仍将重新启动它)。

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

票数 1
EN

Stack Overflow用户

发布于 2022-07-09 23:57:14

您可以使用long-syntax of depends_on来解决竞赛条件的问题,您可以在其中指定健康检查。这将保证您的文件在运行node-red服务时存在。

代码语言:javascript
复制
  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 (参见docs 这里),以查看您的文件是否存在于卷中。可以将以下内容添加到google-iot服务的服务描述中:

代码语言:javascript
复制
healthcheck:
  test: ["CMD", "cat", "/data/myfile.txt"]
  interval: 1m30s
  timeout: 10s
  retries: 3
  start_period: 40s

随时根据需要调优持续时间值。

这能解决你的问题吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72925044

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档