我的目標:我希望能夠使用容器內的某些命令基于官方 Python Image 重新啟動容器。
我的系統:我有一個基于官方 python 映像的自己的 Docker 映像,如下所示:
FROM python:3.6.15-buster
WORKDIR /webserver
COPY requirements.txt /webserver
RUN /usr/local/bin/python -m pip install --upgrade pip
RUN pip3 install -r requirements.txt --no-binary :all:
COPY . /webserver
ENTRYPOINT ["./start.sh"]
如您所見,該影像不執行單個 python 檔案,而是執行一個名為 start.sh 的腳本,如下所示:
#!/bin/bash
echo "Starting"
echo "Env: $ENTORNO"
exec python3 "$PATH_ENTORNO""Script1.py" &
exec python3 "$PATH_ENTORNO""Script2.py" &
exec python3 "$PATH_ENTORNO""Script3.py" &
所有這一切都完美無缺,但是,我希望,例如,如果腳本 3 失敗,則基于此映像的整個容器將重新啟動。
我的方法:我對這個問題有兩個想法。首先,嘗試在 python3 腳本中執行重啟命令,如下所示:
from subprocess import call
[...]
call(["reboot"])
由于錯誤,這在 Python Debian 映像中不起作用:
重啟:找不到命令
另一種方法是在容器內掛載docker.sock,但是這次的錯誤是:
root@MachineName:/var/run# /var/run/docker.sock docker ps
bash: /var/run/docker.sock: Permission denied
我不知道這兩種方法是否正確,或者是否有人對此有任何想法,但任何幫助將不勝感激。
uj5u.com熱心網友回復:
更新
在考慮之后,我意識到您可以向 PID 1(您的入口點)發送一些信號,捕獲它并使用處理程式以適當的代碼退出,以便 docker 重新安排它。
這是一個 MRE:
Dockerfile
FROM python:3.9
WORKDIR /app
COPY ./ /app
ENTRYPOINT ["./start.sh"]
啟動.sh
#!/usr/bin/env bash
python script.py &
# This traps user defined signal and kills the last command
# (`tail -f /dev/null`) before exiting with code 1.
trap 'kill ${!}; echo "Killed by backgrounded process"; exit 1' USR1
# Launches `tail` in the background and sets this program to wait
# for it to finish, so that it does not block execution
tail -f /dev/null & wait $!
腳本.py
import os
import signal
# Process 1 will be your entrypoint if you declared it in `exec-form`*
print("Sending signal to stop container")
os.kill(1, signal.SIGUSR1)
*exec form
測驗它
> docker build . -t test
> docker run test
Sending signal to stop container
Killed by backgrounded process
> docker inspect $(docker container ls -n 1 -q) --format='{{.State.ExitCode}}'
1
原帖
我認為最安全的選擇是在出現故障時指示 docker 重新啟動您的容器。然后,您只需要使用非零代碼(即:exit 1從您的運行start.sh)退出程式,docker 將從頭開始重新啟動它。
選項1:docker run --restart
相關檔案
docker run --restart on-failure <image>
選項 2:使用docker-compose
版本 3
在您的docker-compose.yml中,您可以將restart_policy指令設定為您對重新啟動感興趣的服務。IE:
version: "3"
services:
app:
...
restart_policy:
condition: on-failure
...
版本 2
在版本 3 之前,可以使用restart指令應用相同的策略,從而減少配置。
version: "2"
services:
app:
...
restart: "on-failure"
...
uj5u.com熱心網友回復:
您有什么理由在同一個容器中運行 3 個行程嗎?根據微服務架構基礎知識,容器中只能運行一個行程。所以你應該為 3 個腳本運行 3 個 docker。所有 3 個腳本都應該具有這樣的邏輯,即如果 3 個 docker 之一無法訪問,那么它應該被殺死。
uj5u.com熱心網友回復:
好吧,最終解決方案比我預期的要簡單得多。
我從在容器內安裝 docker 套接字的基礎開始(我知道不推薦這種做法,但就我而言,我知道它不會造成安全問題),使用 docker-compose 中的命令:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
然后,就像使用Python 的 Docker 庫一樣簡單,它通過該套接字提供了一個完整的 SDK,允許我以極其簡單的方式重新啟動 Python 腳本中的容器。
import docker
[...]
docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock')
docker_client.containers.get("container_name").restart()
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/510482.html
