我有一个基于 Python 的 ROS2 节点在 Docker 容器内运行,我试图通过捕获来处理节点的正常关闭SIGTERM
/SIGINT
信号和/或通过捕捉KeyboardInterrupt
例外。
问题是当我使用以下命令在容器中运行节点时docker-compose
。我似乎无法捕捉到容器被停止/杀死的“时刻”。我已经明确添加了STOPSIGNAL https://docs.docker.com/engine/reference/builder/#stopsignal在 Dockerfile 和stop_signal https://docs.docker.com/compose/compose-file/#stop_signal在 docker-compose 文件中。
以下是节点代码示例:
import signal
import sys
import rclpy
def stop_node(*args):
print("Stopping node..")
rclpy.shutdown()
return True
def main():
rclpy.init(args=sys.argv)
print("Creating node..")
node = rclpy.create_node("mynode")
print("Running node..")
while rclpy.ok():
rclpy.spin_once(node)
if __name__ == '__main__':
try:
signal.signal(signal.SIGINT, stop_node)
signal.signal(signal.SIGTERM, stop_node)
main()
except:
stop_node()
以下是用于重新创建映像的示例 Dockerfile:
FROM osrf/ros2:nightly
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
RUN apt-get update && \
apt-get install -y vim
WORKDIR /nodes
COPY mynode.py .
ADD run-node.sh /run-node.sh
RUN chmod +x /run-node.sh
STOPSIGNAL SIGTERM
这是示例 docker-compose.yml:
version: '3'
services:
mynode:
container_name: mynode-container
image: mynode
entrypoint: /bin/bash -c "/run-node.sh"
privileged: true
stdin_open: false
tty: true
stop_signal: SIGTERM
这是 run-node.sh 脚本:
source /opt/ros/$ROS_DISTRO/setup.bash
python3 /nodes/mynode.py
When I manually run the node inside the container (using python3 mynode.py
or by /run-node.sh
) or when I do docker run -it mynode /bin/bash -c "/run-node.sh"
, I get the "Stopping node.." message. But when I do docker-compose up
, I never see that message when I stop the container, by Ctrl+C or by docker-compose down
.
$ docker-compose up
Creating network "ros-node_default" with the default driver
Creating mynode-container ... done
Attaching to mynode-container
mynode-container | Creating node..
mynode-container | Running node..
^CGracefully stopping... (press Ctrl+C again to force)
Stopping mynode-container ... done
$
我试过了:
- 将呼叫移至
signal.signal
- using
atexit
代替signal
- using
docker stop
and docker kill --signal
我也检查过这个docker容器内的Python,优雅地停止 https://stackoverflow.com/q/53852681/2745495问题,但没有明确的解决方案,并且我不确定使用 ROS/rclpy 是否会使我的设置有所不同(另外,我的主机是 Ubuntu 18.04,而该用户使用的是 Windows)。
是否有可能在我的容器中捕捉到容器的停止stop_node
method?