• Docker实践:使用Docker搭建个人开发环境



    使用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 |
    +-----------------------------------------------------------------------------+
    
    
    • 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
    • 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
    
    • 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
    • vscode
      安装扩展并登陆帐号以便同步扩展和设置,必备扩展为微软的Remote
      在这里插入图片描述

    推荐环境

    主机

    容器

    同样是zsh及其相关插件,安装教程见ZSH、oh-my-zsh安装教程及插件和主题推荐

    软件一

    安装

    1. 打开软件商店,输入软件名称,然后点击Install下载安装(若下载速度过慢,尝试本文中的方法一)
      可能会出现下载一会失败的情况,使用以下命令解决
      sudo snap changes #查看ID
      
      • 1
      sudo snap abort [ID] #将 [ID] 替换为实际安装qv2ray的ID,例如 sudo snap abort 49
      
      • 1

    在这里插入图片描述

    1. 下载核心文件(链接见表格,整行复制粘贴到浏览器地址栏,删掉其中多余的空格和制表符),选择linux-64版本下载,等软件一下载好后,解压到如图所示的文件夹(.config是隐藏文件夹,需要在文件管理器的设置中勾选“显示隐藏文件(show hidden files)才会显示”)
    https://github.com/v2fly/v2ray-core/releases
    1. 下载链接解析插件(链接见表格,整行复制粘贴到浏览器地址栏,删掉其中多余的空格和制表符),下v2.0.3.linux-x64.so就可以,因为软件商店下载的软件一是v2.6.0版本,更高版本的链接解析插件不支持该版本
    https://github.com/Qv2ray/QvPlugin-SSR/releases/tag/v2.0.3
    1. 第一次打开软件一,会提示有2.7.0版本,不升级,点击忽略。打开左上角首选项
      在这里插入图片描述
      内核设置中点击“检查核心设置”,若已按照步骤2.解压并移动到指定位置,则会有以下提示
      在这里插入图片描述
      入站设置中将监听地址改为“0.0.0.0”
      在这里插入图片描述
      连接设置如图所示
      在这里插入图片描述
      最后点右下角的“OK”完成设置

    2. 在软件首页点击插件,“打开本地插件目录”
      在这里插入图片描述
      把步骤3.中下载好的插件放到该目录,然后重启程序,再次打开插件,若显示如上图所示,则说明安装成功
      在这里插入图片描述

    3. 点击程序首页下方的分组,再点击“组列表”下方垃圾桶图标左边的图标,添加一个分组,在“订阅设置”中勾选“此分组是一个订阅”,输入订阅地址,点击下方“更新订阅”中,然后点ok完成设置
      在这里插入图片描述

    4. 回到程序首页,就可以在分组中选择服务器使用了

    配置

    终端&脚本

    使用的如果是bash,则修改~/.bashrc,添加如下两行,zsh同理修改~/.zshrc

    export http_proxy="http://127.0.0.1:8889"
    export https_proxy="http://127.0.0.1:8889"
    
    • 1
    • 2

    若是脚本,则在脚本开头加入这两行即可

    若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

    1. 为docker服务创建systemd目录
    sudo mkdir -p /etc/systemd/system/docker.service.d
    
    • 1
    1. 创建一个名为 /etc/systemd/system/docker.service.d/http-proxy.conf 的文件并添加一个或多个环境变量
    sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf
    
    • 1

    以下为示例内容

    [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"
    
    • 1
    • 2
    • 3
    • 4
    1. 刷新更改并重新启动Docker
    sudo systemctl daemon-reload
    sudo systemctl restart docker
    
    • 1
    • 2
    1. 验证是否加载成功
    sudo systemctl show --property=Environment docker
    
    • 1

    针对build命令

    方法一

    针对pull命令

    为docker pull设置代理

    针对run命令

    方法三

    针对容器

    方法二

    软件二

    安装

    1. 直接在Ubuntu Software搜索并安装,或使用命令
      在这里插入图片描述

    在这里插入图片描述

    1. 应用程序菜单找到程序,打开后点击左下角“+”添加配置
      在这里插入图片描述
    2. 右下角分别有三个选项,其中手动相当于关闭,根据需求三选一即可
      在这里插入图片描述

    使用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]
    
    • 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
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    关于GPU的更多配置,见Ubuntu下 NVIDIA Container Runtime 安装与使用

    2. 设置显卡

    在主机的nvidia显卡设置中(即nvidia-settings),找到PRIME Profiles,选择NVIDIA(Performance Mode),然后重启电脑
    在这里插入图片描述

    3. 在容器内配置开发环境

    1. 使用docker compose命令创建容器
      在docker-compose.yml所在文件夹执行

      docker compose up -d
      
      • 1

      该命令执行一次即可,重复执行会导致之前使用该命令创建的容器被删除,然后创建新的容器,数据会丢失
      容器关闭后,正确的启动方法是使用docker start命令,下文会介绍

      在前面的docker-compose.yml中,使用container_name将容器名称定义为了my_dev,因此会在主机中创建一个名为my_dev的容器

    2. 使用docker exec命令进入容器

      docker exec -it my_dev bash
      
      • 1

      在哪个终端执行这个命令,那么之后在这个终端输入的命令就会在容器中执行

    3. 为容器换中科大源

      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
      
      • 1
      apt update && apt upgrade -y
      
      • 1
    4. 为主机和容器安装中文语言包
      主机终端执行

      sudo apt install language-pack-zh*
      
      • 1

      容器终端执行(因为容器默认用户为root,并且未安装sudo,所以命令里不需要加上sudo)

      apt install language-pack-zh*
      
      • 1
    5. 在步骤1.中打开的容器终端输入 exit ,退出容器终端

      exit
      
      • 1
    6. 在主机的终端中使用docker restart命令重启容器

      docker restart my_dev
      
      • 1
    7. 重复步骤1.,然后在这个终端中为容器配置自己需要的环境就可以了
      若想打开更多容器内终端,同样重复步骤1.即可

      • 开发的时候会用到ssh连接容器,所以需要给容器安装openssh-server

        apt install openssh-server
        
        • 1

        然后修改容器内的/etc/ssh/sshd_config文件:

        • 将 Port 解注释,并把值从22改为其他值(不能使用主机正在使用的端口,因为容器在 host 模式下与主机共用端口),比如2222
        • 找到 PermitRootLogin ,解注释并把值改为 yes

        修改容器root用户的密码

        passwd
        
        • 1

    4. 保存/备份容器

    配完容器的环境后,需要将容器保存为镜像,这样才能复用

    1. 使用docker stop命令关闭容器

      docker stop my_dev
      
      • 1
    2. 使用docker export命令将容器导出为tar包

      docker export -o=my_dev.tar my_dev
      
      • 1

      -o=my_dev.tar指定了tar包的生成路径为当前文件夹且生成的包的名称为my_dev.tar,最后的参数my_dev是容器名称

    3. 使用docker import命令将tar包导入为镜像

      docker import my_dev.tar my_dev:latest
      
      • 1

      这样就成功导入了镜像,可以通过docker image命令查看自己导入的镜像

      docker image ls -a
      # 另一种写法
      # docker images -a
      
      • 1
      • 2
      • 3

      my_dev是镜像名称,latest是标签,可以理解为镜像的分支或版本,就像git中的master一样,镜像的默认标签为latest,标签可以自定义,比如my_dev:v1

    4. 将镜像推送到远程仓库
      推送到Docker Hub:Docker官方文档学习笔记(二):入门Docker官方文档学习笔记(三):总结与补充
      推送到阿里云:使用阿里云管理Docker镜像

      简单来说就是注册账户->创建远程仓库->使用docker login本地终端登陆账户->使用docker tag修改本地镜像名称->使用docker push推送到远程仓库

    5. 修改docker-compose.yml

    在步骤编写docker-compose.yml中,使用的镜像是nvidia的镜像,现在要更换为自己的镜像,所以将image修改为

    image: my_dev:latest
    
    • 1

    需要ssh连接容器,所以在容器启动的时候就要启动ssh服务,将command修改为

    command: bash -c "service ssh start && tail -f /dev/null"
    
    • 1

    然后重新创建容器

    docker compose up -d
    
    • 1

    6. 开始使用

    以后每次开机后,启动自己配好的容器时,都只需要使用docker start命令

    docker start my_dev
    
    • 1

    要运行GUI程序,见Docker容器运行GUI程序的方法(直接进入Docker容器运行或通过SSH连接Docker容器运行)

    • 使用vscode在容器内写代码
      安装好Remote插件后,点击左侧的远程资源管理器图标
      在这里插入图片描述
      点击右上角的齿轮图标
      在这里插入图片描述
      点击“Settings”
      在这里插入图片描述
      自己新建好一个空文件用于保存SSH配置

      touch ~/vscode_Remote_config
      
      • 1

      然后在这里指定好路径
      在这里插入图片描述
      点击右上角的“+”
      在这里插入图片描述
      输入命令,按回车,选择保存在刚才新建的配置文件中

      ssh -p 2222 root@localhost -Y
      
      • 1

      保存成功后配置文件如图所示,远程资源管理器中也出现了添加的连接
      在这里插入图片描述
      右键选择连接
      在这里插入图片描述
      如图所示连接成功
      在这里插入图片描述
      点击左侧的扩展图标,进入扩展界面,会显示主机和容器安装的扩展,点击下载图标即可同步扩展到容器中
      在这里插入图片描述
      这样就设置完成了,可以在容器中写代码了

    • 连接容器

      • ssh连接
        ssh -p 2222 root@localhost -Y
        
        • 1
      • docker exec连接
        docker exec -it my_dev bash
        
        • 1

    无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"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    写好后,使用docker build命令构建镜像

    docker build -t=my_dev:latest .
    
    • 1

    -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
    
    • 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
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    和上文中的docker-compose.yml大部分内容一样,只是少了GPU设置,使用的镜像不同而已

    3. 在容器内配置开发环境

    1. 使用docker compose命令创建容器
      在docker-compose.yml所在文件夹执行

      docker compose up -d
      
      • 1

      该命令执行一次即可,重复执行会导致之前使用该命令创建的容器被删除,然后创建新的容器,数据会丢失
      容器关闭后,正确的启动方法是使用docker start命令,下文会介绍

      在前面的docker-compose.yml中,使用container_name将容器名称定义为了my_dev,因此会在主机中创建一个名为my_dev的容器

    2. 使用docker exec命令进入容器

      docker exec -it my_dev bash
      
      • 1

      在哪个终端执行这个命令,那么之后在这个终端输入的命令就会在容器中执行

    3. 为容器换中科大源

      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
      
      • 1
      apt update && apt upgrade -y
      
      • 1
    4. 为主机和容器安装中文语言包
      主机终端执行

      sudo apt install language-pack-zh*
      
      • 1

      容器终端执行(因为容器默认用户为root,并且未安装sudo,所以命令里不需要加上sudo)

      apt install language-pack-zh*
      
      • 1
    5. 在步骤1.中打开的容器终端输入 exit ,退出容器终端

      exit
      
      • 1
    6. 在主机的终端中使用docker restart命令重启容器

      docker restart my_dev
      
      • 1
    7. 重复步骤1.,然后在这个终端中为容器配置自己需要的环境就可以了
      若想打开更多容器内终端,同样重复步骤1.即可

      • 开发的时候会用到ssh连接容器,所以需要给容器安装openssh-server

        apt install openssh-server
        
        • 1

        然后修改容器内的/etc/ssh/sshd_config文件:

        • 将 Port 解注释,并把值从22改为其他值(不能使用主机正在使用的端口,因为容器在 host 模式下与主机共用端口),比如2222
        • 找到 PermitRootLogin ,解注释并把值改为 yes

        修改容器root用户的密码

        passwd
        
        • 1

    4. 保存/备份容器

    配完容器的环境后,需要将容器保存为镜像,这样才能复用

    1. 使用docker stop命令关闭容器

      docker stop my_dev
      
      • 1
    2. 使用docker export命令将容器导出为tar包

      docker export -o=my_dev.tar my_dev
      
      • 1

      -o=my_dev.tar指定了tar包的生成路径为当前文件夹且生成的包的名称为my_dev.tar,最后的参数my_dev是容器名称

    3. 使用docker import命令将tar包导入为镜像

      docker import my_dev.tar my_dev:latest
      
      • 1

      这样就成功导入了镜像,可以通过docker image命令查看自己导入的镜像

      docker image ls -a
      # 另一种写法
      # docker images -a
      
      • 1
      • 2
      • 3

      my_dev是镜像名称,latest是标签,可以理解为镜像的分支或版本,就像git中的master一样,镜像的默认标签为latest,标签可以自定义,比如my_dev:v1

    4. 将镜像推送到远程仓库
      推送到Docker Hub:Docker官方文档学习笔记(二):入门Docker官方文档学习笔记(三):总结与补充
      推送到阿里云:使用阿里云管理Docker镜像

      简单来说就是注册账户->创建远程仓库->使用docker login本地终端登陆账户->使用docker tag修改本地镜像名称->使用docker push推送到远程仓库

    5. 修改docker-compose.yml

    在步骤编写docker-compose.yml中,使用的镜像是nvidia的镜像,现在要更换为自己的镜像,所以将image修改为

    image: my_dev:latest
    
    • 1

    需要ssh连接容器,所以在容器启动的时候就要启动ssh服务,将command修改为

    command: bash -c "service ssh start && tail -f /dev/null"
    
    • 1

    然后重新创建容器

    docker compose up -d
    
    • 1

    6. 开始使用

    以后每次开机后,启动自己配好的容器时,都只需要使用docker start命令

    docker start my_dev
    
    • 1

    要运行GUI程序,见Docker容器运行GUI程序的方法(直接进入Docker容器运行或通过SSH连接Docker容器运行)

    • 使用vscode在容器内写代码
      安装好Remote插件后,点击左侧的远程资源管理器图标
      在这里插入图片描述
      点击右上角的齿轮图标
      在这里插入图片描述
      点击“Settings”
      在这里插入图片描述
      自己新建好一个空文件用于保存SSH配置

      touch ~/vscode_Remote_config
      
      • 1

      然后在这里指定好路径
      在这里插入图片描述
      点击右上角的“+”
      在这里插入图片描述
      输入命令,按回车,选择保存在刚才新建的配置文件中

      ssh -p 2222 root@localhost -Y
      
      • 1

      保存成功后配置文件如图所示,远程资源管理器中也出现了添加的连接
      在这里插入图片描述
      右键选择连接
      在这里插入图片描述
      如图所示连接成功
      在这里插入图片描述
      点击左侧的扩展图标,进入扩展界面,会显示主机和容器安装的扩展,点击下载图标即可同步扩展到容器中
      在这里插入图片描述
      这样就设置完成了,可以在容器中写代码了

    • 连接容器

      • ssh连接
        ssh -p 2222 root@localhost -Y
        
        • 1
      • docker exec连接
        docker exec -it my_dev bash
        
        • 1

    常见问题与解答

    在容器内使用git clone的时候报错,显示Bad owner or permissions on /root/.ssh/config

    可能是因为使用vscode连接容器时没有修改SSH配置文件的存储位置,使用了默认位置,然后容器启动后将该文件挂载到了容器中

    首先在容器内尝试修改权限

    chmod 600 ~/.ssh/config
    
    • 1

    如果还不行,则删除该文件,按照上文教程,在vscode中指定SSH配置文件的存储位置

    容器和主机间能共享文件,但是打不开/不能编辑/无法执行

    这是权限问题导致的,容器内是root用户,主机使用非root权限用户当然无法访问,修改权限和所有者即可

    命令前面加不加sudo取决于是使用容器中的root用户还是使用主机中的非root用户

    • 修改权限
      sudo chmod -R [所有者][用户组][其他]
      
      • 1
      4:可读
      2:可写
      1:可执行
      -R:所有文件及其子目录,如果只是修改单个文件,不加-R参数
      例如修改SHARE目录及其中的文件、文件夹的权限
      sudo chmod -R 777 SHARE
      
      • 1
    • 修改所有者
      chown -R [所有者]:[用户组]
      
      • 1
      例如
      chown -R root:root
      
      • 1

    无法运行GUI程序

    要运行GUI程序,见Docker容器运行GUI程序的方法(直接进入Docker容器运行或通过SSH连接Docker容器运行)

    容器内环境崩了,如何恢复

    1. 先删除崩了的容器

      在docker-compose.yml所在目录执行

      docker compose down
      
      • 1
    2. 创建新容器

      在docker-compose.yml所在目录执行

      docker compose up -d
      
      • 1

    在容器内能不能使用主机的用户

    这个需要实现用户映射,见ROS官方文档中的login as yourselfThe isolated way

  • 相关阅读:
    “随机森林”及“混合随机森林和多目标粒子群优化”(RF_MOPSO),以预测目标作为学习方法并分别找到多特征过程的最佳参数(Matlab代码实现)
    SpringMVC学习篇(三)
    玩转数据可视化之R语言ggplot2:(九)网络图绘制
    react组件多次渲染问题
    【Unity】两种方式实现弹跳平台/反弹玩家(玩家触发与物体自身触发事件实现蹦床的物理效果)
    疯狂星期四,但是程序员
    Dubbo与SpringCloud的Ribbon、Hystrix、 Feign的优劣势⽐较
    数字经济崛起,企业数字化转型的底层逻辑
    PHP写一个 电商Api接口需要注意哪些?考虑哪些?
    【数据分析】基于Matlab的Critic和修正Critic得到权重结果
  • 原文地址:https://blog.csdn.net/qq_35395195/article/details/126125106