(为免误导,特免责声明如下:本文所有内容,只是基于个人当前理解和实际做法,后面亦会有更正和修订,但任何版本都不免有个人能力有限、理解有误或者工作环境不同的状况,故文中内容仅供参考。任何人都可以借鉴或者直接使用代码片段,但对任何直接引用或者借鉴产生的技术问题等后果,作者不承担任何责任。)
1 本笔记
是我学习使用Docker的记录,以便于后面忘记后查询,和其他人借鉴。
使用docker目标包括:快速部署Ros:humble和Nav2 以及qt环境和自己的qt代码,实现小车自动导航
2 安装docker
curl -fsSL https://test.docker.com -o test-docker.sh
sudo sh test-docker.sh
3 Docker基本概念理解
3.1 镜像image和容器container
- 镜像是固化的文件,用于永久保存。内有系统和文件包括自己安装的程序等
- 容器是运行中的镜像,可以在里面做修改,退出镜像只要没有删除,修改就还存在着。
- 最好把修改固化到镜像里,用commit命令。
- image是逐层依赖的关系,即在一个镜像运行的容器里面做的修改,commit后产生的新镜像与原镜像文件存在父子关系(我的理解:系统是增量保存的),用docker history可以查看历史使用和修改情况
- 慎用–rm,这个会在exit退出容器后删除容器,如果没做commit,容器运行时做到修改就没有了
- 用docker save 会合并各层保存为单个的image文件(没试过,网上说有Python工具可以合并压缩image文件)
3.2 dockerhub
- 用于云端保存镜像文件,便于备份、分发和部署
- 可以用pull 获取(包括公共的镜像,比如ubuntu的基本包,Docker run 的镜像如果本地没有系统会自动pull最新版)
- 用push把修改好的镜像推送到你的docker hub账户下(login 登录)
4 我用到的命令
4.1 基本创建容器运行镜像
- docker run -it --镜像id(/或名称:版本)-- --命令(如 /bin/bash)–
-i t 可以交互,像开了个终端
可选:–rm :终端退出后会删除容器
-d :后台运行(如要连接用docker attach) - 另外开一个终端连接到已在运行的容器:docker exec -it mycontainer bash
4.2 管理镜像
- 查看 docker images
- 删除 docker rm
- 合并 docker save
4.3 管理容器
- 查看运行中的 docker ps
- 查看所有 docker ps -a
- 删除某个docker rmi
- 删除所有不在运行中的 docker container prune
- 挂接运行中的容器 docker attach
- 启动现有 docker start
5 我用到的功能
5.1 共享文件,用run创建容器时加 -v 主机目录:容器目录
如果多个目录需要映射可以用多个-v:docker run -v /host/dir1:/container/dir1 -v /host/dir2:/container/dir2 image_name
5.2 端口映射,用run创建容器时加 -p 主机端口:容器端口
5.3 远程登录,在远程用ssh登录到容器:
- 在容器内装ssh服务,apt-get install openssh-server
- 在容器内配置ssh服务,确保/etc/ssh/sshd_config
- Port 22
- PermitRootLogin yes
- ChallengeResponseAuthentication no (新版本好像 变了)
- UsePAM yes
- X11Forwarding yes
- X11UseLocalhost no
- 启动ssh服务 /etc/init.d/ssh start
- 修改root用户密码 passwd
- 提交修改后再次启动 docker run -it -p 50001:22 --name xxx imageid(修改提交后的镜像) /usr/sbin/sshd -D
- 远程登录ssh -X root@192.168.2.246(宿主计算机ip,本机可用127.0.0.1) -p 50001(宿主端口,会映射到容器端口22)
- 可以远程命令行,启动UI界面程序(如果远程是Windows,需要加装VcXsrv Windows X Server:https://sourceforge.net/projects/vcxsrv/files/vcxsrv/ 然后先运行起来,ubuntu需要运行xhost +)
5.4 docker内部程序使用UI界面:
- 采用远程登录方案(参见5.3) qt证实可用,vscode不知为啥起不来,但找到remote ssh的方法,就其他电脑或者宿主机打开vscode,装Dev container(这个好像可以不要)和remote ssh插件,连接到docker里,就可以远程调试了。
- 采用共享x11服务方案,qt实践可用。sudo docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY imageid
5.5 docker内部运行ros2
- 直接运行,可以在外部看到topic。(我的理解是docker 在宿主机器里构建了内部虚拟网络,docker容器内部与宿主机都在同一网络里,可以正常通信)
5.6 使用宿主串口,usb口:
***下列为可选方案,还在实验,还未验证 可能要配合 --privileged --privileged=true ***
- 设备映射 docker run -it --name mycontainer --device=/dev/usbdevice1 ubuntu:latest /bin/bash
- 设备映射 docker run -it --device=/dev/video0:/dev/video0 ubuntu
- 挂载方式(映射dev目录)docker run -it -v /dev:/dev ubuntu
5.6.1 使用宿主机CANBus
因为Nav2导航的小车用CANbus控制,需要用到USB-Canbus,并转化成Can0的网络接口,所以在run的时候加了 --network=host,容器内部可以启动和读写Can0。
但用了–network=host就没法用端口映射,也就没法用其他端口 进行ssh登录docker容器,但是可以把宿主机器SSH服务停了,启动容器内的SSH服务,这样远程登录就直接进容器了。(内外同时启动SSH服务?没试过,也行可以用不同的端口号)
5.6.2 使用宿主机USB连接的IMU
项目用的wheeltec的imu会把设备设置别名为fdilink_ahrs,如果在容器内的/dev下看到这个映射就说明可以连上。
加 -v /dev:/dev 实测可用@ 2023-11-23日。
Nav2和自己的ros2 node都可以正常运行
5.7 准备push 到docker hub
- 给最终的image打tag:sudo docker imageid dockerhub账号/名称(新取名)
- sudo docker login 输入账号和密码登录到dockerhub
- sudo push dockerhub账号/名称(新取名)
- 最终容器启动命令:sudo docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -v /dev:/dev --network=host --privileged=true --name=Nav2Docker -e DISPLAY=$DISPLAY imageid
参考
[1]: https://www.runoob.com/docker/ubuntu-docker-install.html
[2]: https://codeleading.com/article/57846523901/
[3]: https://www.huoban.com/news/post/15019.html
[4]: https://www.python100.com/html/K0S0TN331S6D.html
——————————
需要500关注,拜托点个关注,谢谢