Docker使用笔记

背景知识

如果你有一个ubuntu22.04,但是你有一个任务需要在ubuntu2004做,那就需要配置一个docker环境,一个docker环境叫做docler容器container,可以通过镜像构建,一个镜像是一个模板,而容器是一个镜像的实例。

你可以通过docker hub下载别人安装编译好的docker镜像也可以自己写一个dockerfile,一个dockerfile就是可以认为首先你要继承哪个镜像,然后编译镜像的时候你需要做哪些处理,一起写到dockerfile中比如安装opencv等。

docker镜像是一个空白的环境,没有额外的文件,如果想要容器能够编辑当前本地环境的文件,就需把当前本地的文件夹挂载到环境中

docker->imgae->container,是单向的。如果我先写了一个dockerfile然后编译了一个镜像,然后基于这个镜像创建了一个容器,我在这个容器中发现有个事情没写对,我修改了dockerfile,增加了一些东西,那我这个镜像还得重新编译,我这个已经实例化的容器是不是还得删除重新实例化一个容器才行。

我可以把当前的container变成一个新的image

背景

我的ubuntu2204电脑没安装过docker,现在想配置三个slam算法,目前想配置一个ubuntu2004的docker能够运行这三个slam算法,数据集在本地,然后配置好这个docker之后需要给另一个人运行完整数据集,我现在把这三个slam算法的github仓库给你,请你首先帮我查看并总结这三个算法如何配置环境,然后告诉我如何在我的电脑上一步步安装docker并在docker中配置环境并运行这三个slam: https://github.com/xiaoli-1664/AMC-SLAM https://github.com/neufieldrobotics/MultiCamSLAM https://github.com/urbste/MultiCol-SLAM

宿主机:Ubuntu 22.04,只安装 Docker Engine

容器:Ubuntu 20.04

容器内统一装:

  • ROS Noetic
  • OpenCV 4.5.5
  • Pangolin
  • Eigen3
  • GTSAM 4.1.1
  • OpenGV
  • gflags/glog
  • yaml-cpp
  • nlohmann-json
  • 基础编译工具

三个项目分别放在容器的:

  • /opt/slam_ws/AMC-SLAM
  • /opt/slam_ws/MultiCamSLAM
  • /opt/slam_ws/MultiCol-SLAM

数据集不打进镜像,而是从宿主机挂载进去:

  • 宿主机:/data/slam_datasets
  • 容器内:/datasets

Docker engine安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1. 卸载旧版本(防止冲突)
sudo apt remove -y docker.io docker-compose docker-doc podman-docker containerd runc
# 2. 安装基础依赖
sudo apt install -y ca-certificates curl
# 3. 创建密钥目录
sudo install -m 0755 -d /etc/apt/keyrings
# 4. 下载 Docker 阿里云 GPG 密钥(国内可用)
sudo curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
# 5. 设置密钥可读权限
sudo chmod a+r /etc/apt/keyrings/docker.asc
# 6. 添加阿里云Docker软件源(关键)
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 7. 只更新 Docker 源,不更新系统坏源(修复你报错的核心)
sudo apt update -o Dir::Etc::sourcelist="sources.list.d/docker.list" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0"
# 8. 安装 Docker 引擎
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 9. 开机自启 + 启动服务
sudo systemctl enable docker
sudo systemctl start docker
# 10. 测试是否安装成功,如果运行失败说明Docker 官方镜像仓库国内访问超时
sudo docker run hello-world

然后把自己加入 docker 组:

1
2
3
sudo usermod -aG docker $USER
newgrp docker
docker run hello-world

配置阿里云镜像加速(但是不能翻墙)

复制下面整段命令直接运行,自动创建配置文件 + 重启 Docker:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 创建 docker 配置文件夹
sudo mkdir -p /etc/docker

# 写入阿里云镜像加速器地址(国内专用)
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://mirror.baidubce.com"
]
}
EOF

# 重新加载配置 + 重启 Docker
sudo systemctl daemon-reload
sudo systemctl restart docker

翻墙状态下使用docker(单独配置代理)

代理只给了 shell / 浏览器没有给 Docker systemd 服务配置代理

假设你的宿主机代理端口是:HTTP/HTTPS 代理:127.0.0.1:7890那就这样配。

1)创建 systemd 代理目录

1
sudo mkdir -p /etc/systemd/system/docker.service.d

2)写代理配置

1
sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf

填入:

1
2
3
4
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,::1"

3)重载并重启

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

4)检查是否生效

1
systemctl show --property=Environment docker

你应该能看到刚才那几个代理变量。然后再拉:

1
docker run hello-world

Docker卸载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 删除docker残留物,没有就不用卸载了
dpkg -l | grep -i docker
# 删除io ce
sudo apt-get purge -y docker-engine docker docker.io docker-ce
sudo apt-get autoremove -y --purge docker-engine docker docker.io docker-ce
# 删除参数
sudo rm -rf /var/lib/docker /etc/docker
sudo rm /etc/apparmor.d/docker
sudo groupdel docker
sudo rm -rf /var/run/docker.sock
# 如果使用dpkg的方式安装 发现还未清除docker残留
sudo find / -name "*docker*"
# rm 这些项
cd /var/lib/dpkg/
sudo gedit status
# 在status与status-old 文件里查找docker相关的项,删除相关内容。

Docker常见操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 下载镜像
docker pull ubuntu:22.04
# 查看本地所有镜像
docker images
# 删除镜像
docker rmi 镜像ID/名字

# 运行一个容器(最常用:后台运行 + 端口映射 + 文件夹挂载)
docker run -d -p 主机端口:容器端口 -v 主机路径:容器路径 --name 自定义名字 镜像名
# 例子(跑一个Ubuntu)
docker run -it --name myubuntu ubuntu:22.04

# 查看正在运行的容器
docker ps
# 查看所有容器(包括停止的)
docker ps -a

# 进入正在运行的容器(最常用!)
docker exec -it 容器ID/名字 bash

# 启动/停止/重启容器
docker start 容器名
docker stop 容器名
docker restart 容器名

# 删除容器(必须先停止)
docker rm 容器ID/名字

# Dockerfile 构建镜像(你最需要)
# 当前目录有 Dockerfile,构建镜像(最后的 . 很重要)
docker build -t 你的镜像名:版本号 .
# 例子
docker build -t myslam:v1 .


# 查看容器日志
docker logs 容器ID/名字
# 实时刷新日志
docker logs -f 容器ID/名字

# 把主机当前目录挂载到容器 /code 目录,容器里改文件 = 本机直接改,不用复制文件进容器。
docker run -v $(pwd):/code -it ubuntu

# 清理停止的容器、无用镜像、缓存
docker system prune -a

# 把容器保存成镜像
docker commit 容器ID 新镜像名:版本

Docker容器内翻墙

如果你宿主机已经有可用代理,比如:

1
2
3
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export ALL_PROXY=socks5://127.0.0.1:7890

那启动容器时一起传进去:

1
2
3
4
5
6
7
8
9
10
11
12
13
docker run -it --name slam2004 \
--net=host \
-e DISPLAY=$DISPLAY \
-e HTTP_PROXY=$HTTP_PROXY \
-e HTTPS_PROXY=$HTTPS_PROXY \
-e ALL_PROXY=$ALL_PROXY \
-e http_proxy=$HTTP_PROXY \
-e https_proxy=$HTTPS_PROXY \
-e all_proxy=$ALL_PROXY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v /data/slam_datasets:/datasets \
-v ~/docker_slam_2004/workspace:/workspace \
slam-all:ubuntu2004

这样容器里的:aptgit clonepipnpm,Copilot/Codex 相关联网能力通常都会跟着走。

如果想让 apt / git 也固定用代理进入容器后可加:

1
2
3
4
git config --global http.proxy "$HTTP_PROXY"
git config --global https.proxy "$HTTPS_PROXY"
npm config set proxy "$HTTP_PROXY"
npm config set https-proxy "$HTTPS_PROXY"

Codex和VScode插件

先在宿主机安装 VS Code 扩展:

  • Dev Containers
  • GitHub Copilot
  • 需要的话再装你要用的 Codex 扩展/CLI 辅助插件

然后:

  1. 启动你的容器
  2. 打开 VS Code
  3. Ctrl+Shift+P
  4. 运行 Dev Containers: Attach to Running Container…
  5. 选中你的容器 slam2004

docker容器打包成镜像

把容器打包成镜像

docker commit = 快照

1
2
3
docker commit 你的容器名 你要生成的镜像名:版本号

docker commit my_slam_container slam_env:v1

把镜像导出成一个文件发给他

1
2
3
docker save -o 镜像文件.tar 镜像名:版本

docker save -o slam_env.tar slam_env:v1

别人如何基于文件创建容器

1
2
docker load -i slam_env.tar
docker run -it slam_env:v1