У меня есть узел ROS2 на основе Python, работающий внутри контейнера Docker, и я пытаюсь обработать корректное завершение работы узла, перехватывая сигналы SIGTERM
/SIGINT
и/или перехватывая исключение KeyboardInterrupt
.
Проблема в том, что когда я запускаю узел в контейнере, используя docker-compose
. Кажется, я не могу поймать «момент», когда контейнер останавливается/убивается. Я явно добавил STOPSIGNAL
в Dockerfile и 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
Когда я вручную запускаю узел внутри контейнера (используя python3 mynode.py
или /run-node.sh
) или когда я делаю docker run -it mynode /bin/bash -c "/run-node.sh"
, я получаю сообщение «Остановка узла..». Но когда я делаю docker-compose up
, я никогда не вижу это сообщение при остановке контейнера с помощью Ctrl+C или 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
- используя
atexit
вместоsignal
- используя
docker stop
иdocker kill --signal
Я также проверил этот вопрос Python внутри док-контейнера, изящно остановите, но там нет четкого решения, и я не уверен, что использование ROS/rclpy делает мою настройку другой (к тому же, мой хост-компьютер - Ubuntu 18.04, а этот пользователь был в Windows).
Можно ли отловить остановку контейнера в моем методе stop_node
?