我是 docker 的新手,我尝试创建一个 docker-compose,让两个容器可以互相看到。这个问题可能与许多其他关于“没有这样的文件或目录”错误的问题重复,但其他问题到目前为止还没有帮助我解决这个问题。
它是针对 ROS 项目的,框架取自“小型 ROS 示例“,其中,主要是docker-compose-explicit.yml示例,并且该教程有效。
现在,使用我的项目图像并更改一些其他内容:
- 桥接网络已运行,可通过简单的“hello world”回声和
ping master
aso进行测试。 - 我不确定可解析的体积。
我没有找到像容器似乎自动执行的那样进入图像工作目录的方法。好像我没有挂载 MYPROJECT,它是在创建映像时安装在 /root 中的。
这个容器的运行不需要挂载参数,它似乎自动以根目录作为镜像的工作目录启动,然后可以访问 MYPROJECT 目录而不会出现错误:
docker run -it --rm --name test MYPROJECT /bin/bash -c "cd MYPROJECT"
这个docker-compose文件不起作用。我已添加ls
查看“容器当时看到的内容”:
version: '2'
services:
master:
build: .
networks:
- MYPROJECT_bridge
command: bash -c "echo 'hello world' && cd MYPROJECT && ls"
talker:
build: .
networks:
- MYPROJECT_bridge
environment:
- "ROS_HOSTNAME=talker.MYPROJECT_bridge"
- "ROS_MASTER_URI=http://master.MYPROJECT_bridge:11311/"
command: bash -c "echo 'hello world' && ls && echo '___' && cd MYPROJECT && ls"
listener:
build: .
networks:
- MYPROJECT_bridge
environment:
- "ROS_HOSTNAME=listener.MYPROJECT_bridge"
- "ROS_MASTER_URI=http://master.MYPROJECT_bridge:11311/"
command: bash -c "echo 'hello world' && ls && echo '___' && cd MYPROJECT && ls"
# "resolvable" is providing a DNS entry for the Docker bridge interface address, by default for docker0, just to avoid having to set ROS_IP for every container, see the tutorial
resolvable:
image: MYIMAGE
volumes:
- /:/MYPROJECT:rw
command: bash -c "echo 'hello world';tail -f /dev/null;"
volumes:
MYPROJECT:
networks:
MYPROJECT_bridge:
侦听器的错误输出示例:
Attaching to MYPROJECTPATH_listener_1, MYPROJECTPATH_resolvable_1
resolvable_1 | 2021/02/06 10:43:42 systemd: disabled, cannot read /tmp/systemd: stat /tmp/systemd: no such file or directory
resolvable_1 | 2021/02/06 10:43:42 Starting resolvable 0.2 ...
resolvable_1 | 2021/02/06 10:43:42 got local address: 172.26.0.2
resolvable_1 | 2021/02/06 10:43:42 error adding container 98682f299611: unknown network mode%!(EXTRA string=MYPROJECTPATH_MYPROJECT_bridge)
resolvable_1 | 2021/02/06 10:43:42 error adding container 55f741dabd1c: unknown network mode%!(EXTRA string=MYPROJECTPATH_default)
listener_1 | hello world
listener_1 | bin
listener_1 | boot
listener_1 | dev
listener_1 | etc
listener_1 | home
listener_1 | lib
listener_1 | lib64
listener_1 | media
listener_1 | mnt
listener_1 | opt
listener_1 | proc
listener_1 | root
listener_1 | ros_entrypoint.sh
listener_1 | run
listener_1 | sbin
listener_1 | srv
listener_1 | sys
listener_1 | tmp
listener_1 | usr
listener_1 | var
listener_1 | ___
listener_1 | bash: line 0: cd: MYPROJECT: No such file or directory
如何修复最后一行No such file or directory
?无法进入 MYPROJECT 目录。
这个问题可能还涉及,但我不确定:当使用已经在容器上运行且没有 mount 参数的相同 bash 命令时,为什么以及如何在 docker-compose 文件中挂载卷?并且在开始cannot read /tmp/systemd
和时都有警告unknown network mode%
,但该错误也出现在教程中并且不会阻止它工作。
更新:如果我在每个服务中加载图像(这样您image: MYIMAGE
也可以在主服务、谈话者和监听器中看到),尽管命令找不到主服务,但它们在每个服务中都有效:
RLException: ERROR: unable to contact ROS master at [http://master.MYPROJECT_bridge:11311] talker_1 | The traceback for the exception was written to the log file
。
我怎样才能在可解析中只加载一次图像,以便其他服务使用该图像?或者更广泛地说,如果可能不需要可解析:如何使用docker-compose让ROS在Docker上运行?
答案1
回答我自己的问题。更好的方法是参加另一个 ROS 撰写教程,请参阅 2.)。
- 尝试运行给定的docker-compose:
我不能再肯定地说主要的变化是什么。但至少最终还是奏效了。
version: '2'
services:
master:
build: .
command: roscore
talker:
build: .
workdir: /MYPROJECT
environment:
- "ROS_HOSTNAME=talker"
- "ROS_MASTER_URI=http://master:11311/"
command: bash -c "source devel/setup.bash && MYCOMMAND --wait"
listener:
build: .
workdir: /MYPROJECT
environment:
- "ROS_HOSTNAME=listener"
- "ROS_MASTER_URI=http://master:11311/"
command: bash -c "source devel/setup.bash && MYCOMMAND --wait"
resolvable:
image: MYIMAGE
volumes:
- /var/run/docker.sock:/tmp/docker.sock
- /etc/resolv.conf:/tmp/resolv.conf
如果我想cd MYPROJECT &&
不使用workdir:
,我可能必须将卷装入每个容器,而不仅仅是“可解析”容器。请参阅在 docker-compose 中挂载卷。如何操作?和如何使用docker-compose挂载主机目录?或者官方文档。
尽管遵循 2.) 的指导可能是最好的方法,但这是一种使问题的 docker-compose 工作的方法,使用没有单独网络和卷的精简脚本,因为这由“可解析”容器覆盖。您需要在talker 和 listener 的 bash 命令的命令行末尾添加--wait
(前面没有);其目的与 相同,这也使容器保持活动状态,但没有。使用在测试中有效,甚至可能是主要技巧。;
--wait
;tail -f /dev/null
;
--wait
- 更官方的 wiki.ros.org 指南似乎更好:
根据 wiki.ros.org 官方指南的建议,ROS 和 Docker Compose 入门,这里首先只是复制粘贴:
version: '2'
networks:
ros:
driver: bridge
services:
ros-master:
image: ros:kinetic-ros-core --> replace with MYIMAGE
command: stdbuf -o L roscore
networks:
- ros
restart: always
talker:
image: ros:kinetic-ros-core --> replace with MYIMAGE
depends_on:
- ros-master
environment:
- "ROS_MASTER_URI=http://ros-master:11311"
- "ROS_HOSTNAME=talker"
command: stdbuf -o L rostopic pub /chatter std_msgs/String "hello" -r 1
networks:
- ros
restart: always
listener:
image: ros:kinetic-ros-core --> replace with MYIMAGE
depends_on:
- ros-master
environment:
- "ROS_MASTER_URI=http://ros-master:11311"
- "ROS_HOSTNAME=listener"
command: stdbuf -o L rostopic echo /chatter
networks:
- ros
restart: always
您stdbuf -o L ...
还可以使用bash -c "..."
。
跟问题的docker-compose有什么区别?
网络的构建还有一个额外的步骤:
networks: ros: driver: bridge
这个网络在容器中被这样调用:
networks: - ros
虽然问题的 docker-compose 使用
networks: - MYPROJECT_bridge
并使用相同的方法调用网络:
networks: - MYPROJECT_bridge
我们还看到“可解析”容器根本不需要。
restart: always
引入,以便容器不会在一个命令之后直接退出,可能与--wait
1.) 中 bash 命令末尾的操作相同。问题的 docker-composetail -f /dev/null
仅用于可解析,可能错误地希望这将适用于所有容器中图像的使用。