使用Docker搭建开发环境:
- 可以避免因配环境失误导致系统崩溃,更换电脑或重装系统后也可快速恢复工作环境,相当于备份系统
- 只需下载镜像启动容器即可使用,方便部署在其他设备上,既统一了环境,便于查找问题,又节约了配环境的时间
- 想使用不同的系统及相应的软件,不需要重装系统,新建一个镜像,在镜像内搭建环境就能使用
- Docker Hub、GitHub上有很多开源的Dockerfile和已经制作好的镜像,在它们的基础上定制自己的环境也很方便,不需要从0开始搭建
- 跨平台,例如x86平台上构建好用于arm平台的镜像,可以在x86上运行、测试好后部署到arm平台
- 在Windows上也能使用Linux系统,且比虚拟机节约资源
- 方便导入和导出,一个压缩包就能打包环境
环境配置
必备环境
主机
- Ubuntu
我使用的是Kubuntu 22.04,基于Ubuntu 22.04 的一个风味发行版,功能非常丰富,详情见官网
Ubuntu18.04、Ubuntu20.04、Ubuntu22.04等版本也可正常使用 - Nvidia驱动
若要在容器内使用Nvidia显卡,需要在主机中安装nvidia显卡驱动(建议安装最新版本,使用系统自带的驱动管理程序安装)并安装 NVIDIA Container Runtime,安装教程见Ubuntu下 NVIDIA Container Runtime 安装与使用
nvidia-smi
Tue Aug 9 11:13:42 2022
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 515.65.01 Driver Version: 515.65.01 CUDA Version: 11.7 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 NVIDIA GeForce ... Off | 00000000:01:00.0 On | N/A |
| N/A 47C P5 25W / N/A | 570MiB / 8192MiB | 22% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| 0 N/A N/A 1238 G /usr/lib/xorg/Xorg 286MiB |
| 0 N/A N/A 2020 G /usr/bin/kwin_x11 115MiB |
| 0 N/A N/A 2074 G /usr/bin/plasmashell 99MiB |
| 0 N/A N/A 6161 G ...159984077981301337,131072 63MiB |
+-----------------------------------------------------------------------------+
- docker版本
不要使用Docker Desktop for Linux(若想通过GUI程序管理Docker,可使用Portainer CE等其他开源工具)。经测试,可能会出现无法显示容器内GUI程序的问题,安装教程见Docker官方文档学习笔记(一):安装、升级、卸载Docker,有耐心的可以看一下Docker专栏里的Docker官方文档学习笔记,官方文档用的是Docker Desktop for Linux,但使用Docker Engine同样可以走完教程,讲Docker Desktop for Linux操作的部分跳过就可以了
docker version
Client: Docker Engine - Community
Version: 20.10.17
API version: 1.41
Go version: go1.17.11
Git commit: 100c701
Built: Mon Jun 6 23:02:46 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.17
API version: 1.41 (minimum version 1.12)
Go version: go1.17.11
Git commit: a89b842
Built: Mon Jun 6 23:00:51 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.6
GitCommit: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
runc:
Version: 1.1.2
GitCommit: v1.1.2-0-ga916309
docker-init:
Version: 0.19.0
GitCommit: de40ad0
- vscode
安装扩展并登陆帐号以便同步扩展和设置,必备扩展为微软的Remote
推荐环境
主机
- 主机安装日常所需的软件即可,例如WPS、百度网盘、Chrome、cmake、git等
- zsh及其相关插件,安装教程见ZSH、oh-my-zsh安装教程及插件和主题推荐
- 开热点的linux-wifi-hotspot
- 代理,教程见Ubuntu安装v2ray的QT客户端、Electron,配置全局&PAC代理,终端&脚本、Chrome浏览器、应用商店、Docker均可使用,本文也会展示该博文内容,见目录中的“软件一”、“软件二”
推荐两个软件,都是从snap商店下载(就是系统自带的软件商店Ubuntu Software),软件名称如图所示,在商店直接按名称搜索即可安装,为方便区分,下文以软件一(左)、软件二(右)代替这两个软件的名称
- vscode扩展,这里以截图的形式展示
容器
同样是zsh及其相关插件,安装教程见ZSH、oh-my-zsh安装教程及插件和主题推荐
软件一
安装
- 打开软件商店,输入软件名称,然后点击Install下载安装(若下载速度过慢,尝试本文中的方法一)
可能会出现下载一会失败的情况,使用以下命令解决sudo snap changes #查看ID
sudo snap abort [ID] #将 [ID] 替换为实际安装qv2ray的ID,例如 sudo snap abort 49
- 下载核心文件(链接见表格,整行复制粘贴到浏览器地址栏,删掉其中多余的空格和制表符),选择linux-64版本下载,等软件一下载好后,解压到如图所示的文件夹(.config是隐藏文件夹,需要在文件管理器的设置中勾选“显示隐藏文件(show hidden files)才会显示”)
https://github.com/v2 | fly/v2 | ray-core/releases |
---|
- 下载链接解析插件(链接见表格,整行复制粘贴到浏览器地址栏,删掉其中多余的空格和制表符),下v2.0.3.linux-x64.so就可以,因为软件商店下载的软件一是v2.6.0版本,更高版本的链接解析插件不支持该版本
https://github.com/Qv2 | ray/QvPlugin-SS | R/releases/tag/v2.0.3 |
---|
-
第一次打开软件一,会提示有2.7.0版本,不升级,点击忽略。打开左上角首选项
在内核设置中点击“检查核心设置”,若已按照步骤2.解压并移动到指定位置,则会有以下提示
在入站设置中将监听地址改为“0.0.0.0”
连接设置如图所示
最后点右下角的“OK”完成设置 -
在软件首页点击插件,“打开本地插件目录”
把步骤3.中下载好的插件放到该目录,然后重启程序,再次打开插件,若显示如上图所示,则说明安装成功
-
点击程序首页下方的分组,再点击“组列表”下方垃圾桶图标左边的图标,添加一个分组,在“订阅设置”中勾选“此分组是一个订阅”,输入订阅地址,点击下方“更新订阅”中,然后点ok完成设置
-
回到程序首页,就可以在分组中选择服务器使用了
配置
终端&脚本
使用的如果是bash,则修改~/.bashrc,添加如下两行,zsh同理修改~/.zshrc
export http_proxy="http://127.0.0.1:8889"
export https_proxy="http://127.0.0.1:8889"
若是脚本,则在脚本开头加入这两行即可
若apt安装还是速度慢,见Ubuntu设置apt代理(使用Synaptic Package Manager 新立得软件包管理器、修改 /etc/apt/apt.conf.d/proxy.conf 文件、修改 .bashrc)
Chrome浏览器
Chrome使用的是系统的代理设置,所以需要修改系统代理
该图为Ubuntu的设置
该图为Kubuntu的设置
应用商店
见Ubuntu Snap商店代理设置方法的方法二
Docker
对于不同的使用情景,需要在不同地方设置,建议一次全设置上,若没有安装Docker Desktop for Linux,则不需要针对run命令使用方法三
Docker Daemon
- 为docker服务创建systemd目录
sudo mkdir -p /etc/systemd/system/docker.service.d
- 创建一个名为 /etc/systemd/system/docker.service.d/http-proxy.conf 的文件并添加一个或多个环境变量
sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf
以下为示例内容
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:8889"
Environment="HTTPS_PROXY=http://127.0.0.1:8889"
Environment="NO_PROXY=localhost,127.0.0.1"
- 刷新更改并重新启动Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
- 验证是否加载成功
sudo systemctl show --property=Environment docker
针对build命令
针对pull命令
针对run命令
针对容器
软件二
安装
- 直接在Ubuntu Software搜索并安装,或使用命令
- 应用程序菜单找到程序,打开后点击左下角“+”添加配置
- 右下角分别有三个选项,其中手动相当于关闭,根据需求三选一即可
使用Electron的好处是不需要再去Ubuntu的设置里面手动修改地址和端口,选择任意一项,软件都会自动修改Ubuntu的配置,弊端是不像软件一可以修改监听地址,使用软件二无法设置docker build命令的代理,因为docker build的代理地址是本机的局域网ip地址,监听地址不改为0.0.0.0,无法通过局域网代理
配置
参照软件一的配置教程即可,凡是代理地址为127.0.0.1的设置都能生效
若想局域网共享代理,则须使用软件一,将监听地址设置为0.0.0.0,然后其他设备中代理地址填写本机的ip和开放的端口即可(本教程中为8889端口)
含Nvidia独显开发环境搭建教程
适用于有Nvidia独显的主机并希望能在容器中使用独显
需要在主机中安装nvidia显卡驱动(建议安装最新版本,使用系统自带的驱动管理程序安装)并安装 NVIDIA Container Runtime,安装教程见Ubuntu下 NVIDIA Container Runtime 安装与使用
1. 编写docker-compose.yml
之前尝试过写Dockerfile,然后手动安装cuda和cudnn,很麻烦,因此直接使用nvidia的cuda镜像,在它的基础上定制自己的镜像
使用 docker run 运行容器的时候,需要加很多参数,相比之下docker-compose.yml简化了run后跟的参数,将运行时的参数全部写到yml文件里面,只需执行 docker compose up -d 就可以启动,达到和 docker run 一样的效果
docker-compose.yml原本是为一次管理多个容器而设计的(见Docker官方文档学习笔记(二):入门),在这里管理一个容器同样方便
# 这个version指的是compose文档的官方版本,不同版本号所含的功能不同
# 具体见 https://docs.docker.com/compose/compose-file/compose-versioning/
# 编写本教程时的最新版本为3.8
version: '3.8'
# 项目名称
name: my_dev
# 所有的容器的定义都要在services这个顶级元素下定义
services:
# 服务名称,可以与项目名称保持一致
my_dev:
# 设置为true,则容器内PID为1的进程就会是docker提供的一个init程序
# 这样可以使容器能够回收内部的僵尸进程,避免占用资源
init: true
# 容器名称,可以与服务名称保持一致
container_name: my_dev
# 网络模式设置为host,就可以与主机使用同一个网络,而不是使用docker虚拟网卡的桥接网络,方便设置代理和ssh连接
network_mode: "host"
# 设置为true,则容器内的root用户与主机的root用户具有相同的权限
privileged: true
# 使用nvidia官方镜像:cuda11.6.2,cudnn8,ubuntu18.04
# 更多镜像见 https://hub.docker.com/r/nvidia/cuda/tags?page=1&ordering=last_updated
image: nvidia/cuda:11.6.2-cudnn8-devel-ubuntu18.04
# 设置容器启动后自动执行的命令,不能为空
# 容器内PID为1的进程退出后,容器就会关闭,为了防止容器自动关闭,就需要让容器一直运行程序
# 这个命令可以防止容器启动后自动退出
command: tail -f /dev/null
# 设置要挂载的目录,可以理解为共享文件夹
volumes:
# 使容器和主机共用一套ssh密钥,但主机内该文件夹的config文件(如果存在的话)不能被容器内的root用户使用,
# 可能会报错(Bad owner or permissions on /root/.ssh/config)。
# 这个config文件是vscode保存ssh连接的,权限为600
# 解决办法是将主机的这个config文件改名,例如改为config.back
# 但推荐方法是重新设置vscode保存ssh连接的文件的路径,下文会介绍
# - "~/.ssh:/root/.ssh:rw" # 本来是为了省事,现在不推荐挂载,因为会导致一些报错,处理起来比较麻烦。
# 显示GUI所必须的
- "/tmp/.X11-unix:/tmp/.X11-unix:rw"
# 使容器可以读取到外接设备
# 比如主机上插了一个USB相机,挂载/dev后,容器内就也可以使用该相机了
- "/dev:/dev:rw"
# 将docker-compose.yml所在目录下的ENVIRONMENTS文件夹(如果不存在则会自动创建一个)共享到容器中
# 目的是方便在容器和主机间共享数据
- "./ENVIRONMENTS:/root/ENVIRONMENTS:rw"
# 将docker-compose.yml所在目录下的SHARE文件夹(如果不存在则会自动创建一个)共享到容器中
# 目的是方便在容器和主机间共享数据
- "./SHARE:/root/SHARE:rw"
# 与主机共用git配置
# - "~/.gitconfig:/root/.gitconfig:rw" # 这个也就不推荐挂载了
# 设置容器的默认工作目录
working_dir: /root
# 设置环境变量
environment:
# 显示GUI所必须的
- DISPLAY=$DISPLAY
- QT_X11_NO_MITSHM=1
# 将语言设置成简体中文
- LC_ALL=zh_CN.UTF-8
# 启用GPU驱动的所有功能
- NVIDIA_DRIVER_CAPABILITIES=all
# 启用GPU
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
关于GPU的更多配置,见Ubuntu下 NVIDIA Container Runtime 安装与使用
2. 设置显卡
在主机的nvidia显卡设置中(即nvidia-settings),找到PRIME Profiles,选择NVIDIA(Performance Mode),然后重启电脑
3. 在容器内配置开发环境
-
使用docker compose命令创建容器
在docker-compose.yml所在文件夹执行docker compose up -d
该命令执行一次即可,重复执行会导致之前使用该命令创建的容器被删除,然后创建新的容器,数据会丢失
容器关闭后,正确的启动方法是使用docker start命令,下文会介绍在前面的docker-compose.yml中,使用container_name将容器名称定义为了my_dev,因此会在主机中创建一个名为my_dev的容器
-
使用docker exec命令进入容器
docker exec -it my_dev bash
在哪个终端执行这个命令,那么之后在这个终端输入的命令就会在容器中执行
-
为容器换中科大源
sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
apt update && apt upgrade -y
-
为主机和容器安装中文语言包
主机终端执行sudo apt install language-pack-zh*
容器终端执行(因为容器默认用户为root,并且未安装sudo,所以命令里不需要加上sudo)
apt install language-pack-zh*
-
在步骤1.中打开的容器终端输入 exit ,退出容器终端
exit
-
在主机的终端中使用docker restart命令重启容器
docker restart my_dev
-
重复步骤1.,然后在这个终端中为容器配置自己需要的环境就可以了
若想打开更多容器内终端,同样重复步骤1.即可-
开发的时候会用到ssh连接容器,所以需要给容器安装openssh-server
apt install openssh-server
然后修改容器内的/etc/ssh/sshd_config文件:
- 将 Port 解注释,并把值从22改为其他值(不能使用主机正在使用的端口,因为容器在 host 模式下与主机共用端口),比如2222
- 找到 PermitRootLogin ,解注释并把值改为 yes
修改容器root用户的密码
passwd
-
4. 保存/备份容器
配完容器的环境后,需要将容器保存为镜像,这样才能复用
-
使用docker stop命令关闭容器
docker stop my_dev
-
使用docker export命令将容器导出为tar包
docker export -o=my_dev.tar my_dev
-o=my_dev.tar指定了tar包的生成路径为当前文件夹且生成的包的名称为my_dev.tar,最后的参数my_dev是容器名称
-
使用docker import命令将tar包导入为镜像
docker import my_dev.tar my_dev:latest
这样就成功导入了镜像,可以通过docker image命令查看自己导入的镜像
docker image ls -a # 另一种写法 # docker images -a
my_dev是镜像名称,latest是标签,可以理解为镜像的分支或版本,就像git中的master一样,镜像的默认标签为latest,标签可以自定义,比如my_dev:v1
-
将镜像推送到远程仓库
推送到Docker Hub:Docker官方文档学习笔记(二):入门、Docker官方文档学习笔记(三):总结与补充
推送到阿里云:使用阿里云管理Docker镜像简单来说就是注册账户->创建远程仓库->使用docker login本地终端登陆账户->使用docker tag修改本地镜像名称->使用docker push推送到远程仓库
5. 修改docker-compose.yml
在步骤编写docker-compose.yml中,使用的镜像是nvidia的镜像,现在要更换为自己的镜像,所以将image修改为
image: my_dev:latest
需要ssh连接容器,所以在容器启动的时候就要启动ssh服务,将command修改为
command: bash -c "service ssh start && tail -f /dev/null"
然后重新创建容器
docker compose up -d
6. 开始使用
以后每次开机后,启动自己配好的容器时,都只需要使用docker start命令
docker start my_dev
要运行GUI程序,见Docker容器运行GUI程序的方法(直接进入Docker容器运行或通过SSH连接Docker容器运行)
-
使用vscode在容器内写代码
安装好Remote插件后,点击左侧的远程资源管理器图标
点击右上角的齿轮图标
点击“Settings”
自己新建好一个空文件用于保存SSH配置touch ~/vscode_Remote_config
然后在这里指定好路径
点击右上角的“+”
输入命令,按回车,选择保存在刚才新建的配置文件中ssh -p 2222 root@localhost -Y
保存成功后配置文件如图所示,远程资源管理器中也出现了添加的连接
右键选择连接
如图所示连接成功
点击左侧的扩展图标,进入扩展界面,会显示主机和容器安装的扩展,点击下载图标即可同步扩展到容器中
这样就设置完成了,可以在容器中写代码了 -
连接容器
- ssh连接
ssh -p 2222 root@localhost -Y
- docker exec连接
docker exec -it my_dev bash
- ssh连接
无Nvidia独显开发环境搭建教程
适用于无Nvidia独显的主机
1. 编写Dockerfile并构建镜像
# 使用的是ubuntu18.04镜像,是Docker Hub上的Ubuntu官方镜像
FROM ubuntu:18.04
# 每一个RUN命令都会在镜像中构建一个“层”
# 从DEBIAN_FRONTEND开始往下的都是安装命令,仅为示例,非必须
RUN /bin/bash -c "sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
&& sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
&& apt update && apt upgrade -y && \
DEBIAN_FRONTEND=noninteractive apt install tzdata git openssh-server vim zsh libgoogle-glog-dev libgflags-dev libatlas-base-dev \
libeigen3-dev libsuitesparse-dev \
build-essential libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev \
qt5-default qtcreator libssl-dev openssl sudo python-dev libgtest-dev net-tools inetutils-ping \
usbutils x11-apps language-pack-zh* iproute2 ninja-build -y"
写好后,使用docker build命令构建镜像
docker build -t=my_dev:latest .
-t=my_dev是将构建的镜像名称指定为my_dev,版本/标签为latest,后面的“.”是指Dockerfile的路径为当前目录下
执行该命令后,Docker会从Docker Hub下载ubuntu:18.04镜像,然后在这个镜像中执行RUN所给的命令,最后构建出一个名为my_dev的镜像
2. 编写docker-compose.yml
# 这个version指的是compose文档的官方版本,不同版本号所含的功能不同
# 具体见 https://docs.docker.com/compose/compose-file/compose-versioning/
# 编写本教程时的最新版本为3.8
version: '3.8'
# 项目名称
name: my_dev
# 所有的容器的定义都要在services这个顶级元素下定义
services:
# 服务名称,可以与项目名称保持一致
my_dev:
# 设置为true,则容器内PID为1的进程就会是docker提供的一个init程序
# 这样可以使容器能够回收内部的僵尸进程,避免占用资源
init: true
# 容器名称,可以与服务名称保持一致
container_name: my_dev
# 网络模式设置为host,就可以与主机使用同一个网络,而不是使用docker虚拟网卡的桥接网络,方便设置代理和ssh连接
network_mode: "host"
# 设置为true,则容器内的root用户与主机的root用户具有相同的权限
privileged: true
image: my_dev:latest
# 设置容器启动后自动执行的命令,不能为空
# 容器内PID为1的进程退出后,容器就会关闭,为了防止容器自动关闭,就需要让容器一直运行程序
# 这个命令可以防止容器启动后自动退出
command: tail -f /dev/null
# 设置要挂载的目录,可以理解为共享文件夹
volumes:
# 使容器和主机共用一套ssh密钥,但主机内该文件夹的config文件(如果存在的话)不能被容器内的root用户使用,
# 可能会报错(Bad owner or permissions on /root/.ssh/config)。
# 这个config文件是vscode保存ssh连接的,权限为600
# 解决办法是将主机的这个config文件改名,例如改为config.back
# 但推荐方法是重新设置vscode保存ssh连接的文件的路径,下文会介绍
# - "~/.ssh:/root/.ssh:rw" # 本来是为了省事,现在不推荐挂载,因为会导致一些报错,处理起来比较麻烦。
# 显示GUI所必须的
- "/tmp/.X11-unix:/tmp/.X11-unix:rw"
# 使容器可以读取到外接设备
# 比如主机上插了一个USB相机,挂载/dev后,容器内就也可以使用该相机了
- "/dev:/dev:rw"
# 将docker-compose.yml所在目录下的ENVIRONMENTS文件夹(如果不存在则会自动创建一个)共享到容器中
# 目的是方便在容器和主机间共享数据
- "./ENVIRONMENTS:/root/ENVIRONMENTS:rw"
# 将docker-compose.yml所在目录下的SHARE文件夹(如果不存在则会自动创建一个)共享到容器中
# 目的是方便在容器和主机间共享数据
- "./SHARE:/root/SHARE:rw"
# 与主机共用git配置
# - "~/.gitconfig:/root/.gitconfig:rw" # 这个也就不推荐挂载了
# 设置容器的默认工作目录
working_dir: /root
# 设置环境变量
environment:
# 显示GUI所必须的
- DISPLAY=$DISPLAY
- QT_X11_NO_MITSHM=1
# 将语言设置成简体中文
- LC_ALL=zh_CN.UTF-8
和上文中的docker-compose.yml大部分内容一样,只是少了GPU设置,使用的镜像不同而已
3. 在容器内配置开发环境
-
使用docker compose命令创建容器
在docker-compose.yml所在文件夹执行docker compose up -d
该命令执行一次即可,重复执行会导致之前使用该命令创建的容器被删除,然后创建新的容器,数据会丢失
容器关闭后,正确的启动方法是使用docker start命令,下文会介绍在前面的docker-compose.yml中,使用container_name将容器名称定义为了my_dev,因此会在主机中创建一个名为my_dev的容器
-
使用docker exec命令进入容器
docker exec -it my_dev bash
在哪个终端执行这个命令,那么之后在这个终端输入的命令就会在容器中执行
-
为容器换中科大源
sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
apt update && apt upgrade -y
-
为主机和容器安装中文语言包
主机终端执行sudo apt install language-pack-zh*
容器终端执行(因为容器默认用户为root,并且未安装sudo,所以命令里不需要加上sudo)
apt install language-pack-zh*
-
在步骤1.中打开的容器终端输入 exit ,退出容器终端
exit
-
在主机的终端中使用docker restart命令重启容器
docker restart my_dev
-
重复步骤1.,然后在这个终端中为容器配置自己需要的环境就可以了
若想打开更多容器内终端,同样重复步骤1.即可-
开发的时候会用到ssh连接容器,所以需要给容器安装openssh-server
apt install openssh-server
然后修改容器内的/etc/ssh/sshd_config文件:
- 将 Port 解注释,并把值从22改为其他值(不能使用主机正在使用的端口,因为容器在 host 模式下与主机共用端口),比如2222
- 找到 PermitRootLogin ,解注释并把值改为 yes
修改容器root用户的密码
passwd
-
4. 保存/备份容器
配完容器的环境后,需要将容器保存为镜像,这样才能复用
-
使用docker stop命令关闭容器
docker stop my_dev
-
使用docker export命令将容器导出为tar包
docker export -o=my_dev.tar my_dev
-o=my_dev.tar指定了tar包的生成路径为当前文件夹且生成的包的名称为my_dev.tar,最后的参数my_dev是容器名称
-
使用docker import命令将tar包导入为镜像
docker import my_dev.tar my_dev:latest
这样就成功导入了镜像,可以通过docker image命令查看自己导入的镜像
docker image ls -a # 另一种写法 # docker images -a
my_dev是镜像名称,latest是标签,可以理解为镜像的分支或版本,就像git中的master一样,镜像的默认标签为latest,标签可以自定义,比如my_dev:v1
-
将镜像推送到远程仓库
推送到Docker Hub:Docker官方文档学习笔记(二):入门、Docker官方文档学习笔记(三):总结与补充
推送到阿里云:使用阿里云管理Docker镜像简单来说就是注册账户->创建远程仓库->使用docker login本地终端登陆账户->使用docker tag修改本地镜像名称->使用docker push推送到远程仓库
5. 修改docker-compose.yml
在步骤编写docker-compose.yml中,使用的镜像是nvidia的镜像,现在要更换为自己的镜像,所以将image修改为
image: my_dev:latest
需要ssh连接容器,所以在容器启动的时候就要启动ssh服务,将command修改为
command: bash -c "service ssh start && tail -f /dev/null"
然后重新创建容器
docker compose up -d
6. 开始使用
以后每次开机后,启动自己配好的容器时,都只需要使用docker start命令
docker start my_dev
要运行GUI程序,见Docker容器运行GUI程序的方法(直接进入Docker容器运行或通过SSH连接Docker容器运行)
-
使用vscode在容器内写代码
安装好Remote插件后,点击左侧的远程资源管理器图标
点击右上角的齿轮图标
点击“Settings”
自己新建好一个空文件用于保存SSH配置touch ~/vscode_Remote_config
然后在这里指定好路径
点击右上角的“+”
输入命令,按回车,选择保存在刚才新建的配置文件中ssh -p 2222 root@localhost -Y
保存成功后配置文件如图所示,远程资源管理器中也出现了添加的连接
右键选择连接
如图所示连接成功
点击左侧的扩展图标,进入扩展界面,会显示主机和容器安装的扩展,点击下载图标即可同步扩展到容器中
这样就设置完成了,可以在容器中写代码了 -
连接容器
- ssh连接
ssh -p 2222 root@localhost -Y
- docker exec连接
docker exec -it my_dev bash
- ssh连接
常见问题与解答
在容器内使用git clone的时候报错,显示Bad owner or permissions on /root/.ssh/config
可能是因为使用vscode连接容器时没有修改SSH配置文件的存储位置,使用了默认位置,然后容器启动后将该文件挂载到了容器中
首先在容器内尝试修改权限
chmod 600 ~/.ssh/config
如果还不行,则删除该文件,按照上文教程,在vscode中指定SSH配置文件的存储位置
容器和主机间能共享文件,但是打不开/不能编辑/无法执行
这是权限问题导致的,容器内是root用户,主机使用非root权限用户当然无法访问,修改权限和所有者即可
命令前面加不加sudo取决于是使用容器中的root用户还是使用主机中的非root用户
- 修改权限
4:可读sudo chmod -R [所有者][用户组][其他]
2:可写
1:可执行
-R:所有文件及其子目录,如果只是修改单个文件,不加-R参数
例如修改SHARE目录及其中的文件、文件夹的权限sudo chmod -R 777 SHARE
- 修改所有者
例如chown -R [所有者]:[用户组]
chown -R root:root
无法运行GUI程序
要运行GUI程序,见Docker容器运行GUI程序的方法(直接进入Docker容器运行或通过SSH连接Docker容器运行)
容器内环境崩了,如何恢复
-
先删除崩了的容器
在docker-compose.yml所在目录执行
docker compose down
-
创建新容器
在docker-compose.yml所在目录执行
docker compose up -d
在容器内能不能使用主机的用户
这个需要实现用户映射,见ROS官方文档中的login as yourself和The isolated way