簡體   English   中英

docker 不斷重啟,直到在掛載的卷中創建文件

[英]docker keep restarting until file is created in a mounted volume

我正在嘗試創建一個可以自行重啟的腳本,一個微服務(在我的例子中是node-red )。

這是我的碼頭工人撰寫文件:

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來檢查之前的容器。

這是 node-red 微服務的 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容器以及/data文件夾路徑下的app-data卷中​​創建文件后重新啟動容器node-red ,例如,文件路徑為: /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

根據需要隨意調整持續時間值。

這能解決您的問題嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM