什么是Docker
- 他是一个集装箱的概念
- 他是利用linux的namespace特性实现的
- 环境的隔离
- 你可以通过docker,实现创建多个os(操作系统),并且每个os之间是相互独立隔离的
- docker、nvidia-docker,由于历史原因,docker 没有考虑GPU的计算问题,所以没有配置好的GPU计算驱动,因此nvidia-docker为了解决自家显卡可以进行容器化,所以开发了nvidia-docker
- NOW,docker直接把
nvidia-docker
作为runtime的存在,也就是docker --runtime=nvidia
就可以了,集成进去了。就可以实现容器内调用GPU进行运算或者训练等操作
-
容器(Container,运行着的操作系统)
镜像的实例,他是实际执行起来的操作系统实例
可以基于同一个镜像创建n个容器实例,那么每一个容器实例就是一个独立的操作系统,具有独立的文件管理、网络等各种配置,可以进行ssh连接、训练等各类操作
Ubuntu18.04安装Docker
:::warning 警告:切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker. :::
准备工作
系统要求
Docker 支持以下版本的 Ubuntu 操作系统:
Ubuntu Hirsute 21.04
- Ubuntu Groovy 20.10
- Ubuntu Focal 20.04 (LTS)
- Ubuntu Bionic 18.04 (LTS)
Docker 可以安装在 64 位的 x86 平台或 ARM 平台上。Ubuntu 发行版中,LTS(Long-Term-Support)长期支持版本,会获得 5 年的升级维护支持,这样的版本会更稳定,因此在生产环境中推荐使用 LTS 版本。
卸载旧版本
旧版本的 Docker 称为 docker 或者 docker-engine,使用以下命令卸载旧版本:
sudo apt-get remove docker docker-engine docker.io
使用 APT 安装
由于 apt 源使用 HTTPS 以确保软件下载过程中不被篡改。因此,我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书。
$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
鉴于国内网络问题,强烈建议使用国内源,官方源请在注释中查看。
为了确认所下载软件包的合法性,需要添加软件源的 GPG 密钥。
$ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 建议用官方源,快
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
然后,我们需要向 sources.list
中添加 Docker
软件源
$ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 官方源
$ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
以上命令会添加稳定版本的 Docker APT 镜像源,如果需要测试版本的 Docker 请将 stable 改为 test。
安装 Docker
更新 apt
软件包缓存,并安装 docker-ce
:
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Ubuntu 系统上可以使用这套脚本安装,另外可以通过 --mirror
选项使用国内源进行安装:
若你想安装测试版的 Docker, 请从 test.docker.com 获取脚本
# $ curl -fsSL test.docker.com -o get-docker.sh
$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
# $ sudo sh get-docker.sh --mirror AzureChinaCloud
执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中。
启动 Docker
$ sudo systemctl enable docker # 开机启动
$ sudo systemctl start docker
建立 docker 用户组
默认情况下,docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组。
建立 docker 组:
$ sudo groupadd docker
将当前用户加入 docker 组:
$ sudo usermod -aG docker $USER
测试 Docker 是否安装正确
$ docker run --rm hello-world docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create": dial unix /var/run/docker.sock: connect: permission denied. See 'docker run --help'.
权限问题解决方案
```shell $ sudo cat /etc/group | grep docker docker:x:999:darrenzhang # 可以看到已经将当前用户加入到用户组中
$ sudo systemctl restart docker # 重启docker服务,并退出终端,重新进入终端 $ docker info Client: Context: default Debug Mode: false Plugins: app: Docker App (Docker Inc., v0.9.1-beta3) buildx: Docker Buildx (Docker Inc., v0.8.1-docker) scan: Docker Scan (Docker Inc., v0.17.0)
Server: ERROR: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get “http://%2Fvar%2Frun%2Fdocker.sock/v1.24/info“: dial unix /var/run/docker.sock: connect: permission denied errors pretty printing info
同样还是报权限问题的错误,提示中已经明确提示到要修改`/var/run/docker.sock`的权限
```shell
$ sudo chmod a+rw /var/run/docker
$ docker info
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Docker Buildx (Docker Inc., v0.8.1-docker)
scan: Docker Scan (Docker Inc., v0.17.0)
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 1
Server Version: 20.10.14
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 3df54a852345ae127d1fa3092b95168e4a88e2f8
runc version: v1.0.3-0-gf46b6ba
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: default
Kernel Version: 5.4.0-105-generic
Operating System: Ubuntu 18.04.6 LTS
OSType: linux
Architecture: x86_64
CPUs: 12
Total Memory: 15.57GiB
Name: DarrenZhang
ID: LAD2:6DTJ:MBX3:LLWK:FQCD:N6LL:ABUG:EQ57:3RT7:MTDE:VXBJ:AGOU
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: No swap limit support
$ docker run --rm hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
基本指令
- docker —help:查看帮助
- docker ps:查看当前运行的容器
- docker ps -a:查看当前全部容器(包含了运行和没运行的)
- docker pull 镜像名字:拉一个镜像下来
- 从docker hub上拉一个下来,跟你git clone类似
docker images
:查看所有的镜像- 通过
**镜像名字:tag**
来区分他,或者通过**image id(镜像id)**
区分
- 通过
**docker run -itd --name 容器名称 镜像名称 执行的指令**
:从<镜像>
创建一个容器-it
是必备-d
是背景运行,也就是运行后不占用终端,持续背景运行。如果没有d
,则运行会在当前终端,ctrl+a+d
结束后,容器停止并不删除。$ docker run -it --name myubuntu ba6acccedd29 /bin/bash
docker start <容器id/名称>
:启动一个停止了的容器- 可以使用容器id或者名称进行启动或者任意操作
- 也可以使用部分容器id,只要他是唯一的即可作为名称/id操作
docker exec -it <容器id/名称> 执行的指令
:进入容器- 为某个容器执行一条指令,如果执行的是
/bin/bash
,那么等于进入其终端
- 为某个容器执行一条指令,如果执行的是
docker stop <容器id/名称>
:停止一个正在运行的容器docker rm <容器id/名称>
:删除一个容器- 删除前,必须得停止掉对应容器
docker rmi <镜像id/名称>
:删除一个镜像- id的原则和容器id是一样的,只要能唯一区分即可
- 如果要删除镜像,必须先删除其镜像创建的所有容器才可以
- 删除镜像后,所有数据才会正式清空
docker export [容器id/名称] > name.tar
:储存一个容器- 储存的
name.tar
后缀可以随便个,无所谓 - 储存的文件没有经过压缩,所以会很大,如果做了压缩(
tar -cvf
)会变小很多,适合做发布
- 储存的
docker import name.tar [镜像名称]:[TAG]
:导入一个镜像为启动的容器挂载一个盘
- 在容器创建时,增加
-v
参数,格式是:-v 物理机:容器
- 在容器创建时,增加
- 要注意的是,物理机路径和容器路径必须是全绝对路径,不能是相对路径
案例:
docker run -itd -v /data/sxai/docker/demo/datav:/datav --name test ubuntu:latest
因为默认情况下,容器是没有任何可访问的端口,所以你想ssh直接连接进去是不可能的。所以必须为其开放端口
- 端口的通信链路是这样的:
- 主机A访问主机B的12345端口,此时如果希望主机A的数据能够发送到主机B内的docker容器X的22端口,则需要做一个映射,映射方式是物理机B->容器X的映射,比如:物理机B的12345映射到容器X的22端口。
- 如果还有容器Y、容器Z,都需要开放22端口,则需要消耗主机B的其他端口进行映射,比如说:12346映射到容器Y的22,12347映射到容器Z的22
- 此时主机A访问
主机B:12345
则等价于访问容器X的22端口。主机B:12346 => 容器Y:22,主机B:12347 => 容器Z:22
- 映射方式是:
-p
参数,格式是:-p 物理机端口:容器端口,同样是在容器创建时,即docker run时给参数,然后一直生效 - 案例:
docker run -itd -p 12345:22 --name test ubuntu:latest
- 如果要开放多个端口,可以加多个-p参数
- 这里是映射主机的12345端口到容器的22端口上
- 进入到容器之后,尝试ssh连接 ```shell $ docker exec -it 7ecddads /bin/bash # 进入容器 $ apt update $ apt install openssh-server # 需要选择时区 $ apt install vim $ vim /etc/ssh/sshd_config
需要修改的内容
:/Root 查找 LogiGraceTime 2m PermitRootLogin yes StrictModes yes
需要修改的内容
$ service ssh restart # 重启ssh服务
[Docker中ubuntu镜像配置apt阿里源](https://segmentfault.com/a/1190000041369057)<br />默认ubuntu的docker镜像的apt软件源在国内访问过慢,经常会导致安装失败,这里使用sed命令对apt软件源进行替换,换成阿里的apt软件源,这个方法在安装ubuntu系统的地方都可以使用。
```shell
sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
apt-get clean
apt-get update
高级内容3 - C++,GDB可调试选项
- 提升权限选项
--privileged=true
- 如果容器没有提升权限,则gdb无法调试,因此,容器创建时需要加此选项才可调试
高级内容4 - GPU可用选项,比如要做GPU计算、训练等
:::info ubuntu 在docker中使用gpu,需要安装nvidia-container-runtime :::安装nvidia-container-runtime
- 参考https://nvidia.github.io/nvidia-container-runtime/ 配置nvidia 源
主要执行:
curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-container-runtime/$distribution/nvidia-container-runtime.list | sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.list
curl -k -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update
安装
sudo apt-get install nvidia-container-runtime
停止docker
systemctl stop docker
把运行时添加到docker中
dockerd --add-runtime=nvidia=/usr/bin/nvidia-container-runtime
重新运行容器
systemctl restart docker
按照如上步骤,docker就可以调用本地GPU。
- runtime必须配置为nvidia,
--runtime=nvidia
- 如果提示错误,说明你docker没配好
- 如果你安装的是
nvidia-docker
,可能会因为版本原因没有--runtime=nvidia
,此时可以换成是nvidia-docker run
就行了
- 加上gpu可用选项,
--gpus=all
,这个选项也可以控制容器开放的显卡数量或者特定显卡开放。如果你的docker
提示没有--gpus
这个选项,则说明你的docker
没有配置nvidia
的支持,所以还是没配好 - 增加环境变量,开放nvidia的能力,通过
-e NVIDIA_DRIVER_CAPABILITIES=compute,utility,video,graphics
,这里列举的是compute是计算(cuda、cudnn等),video是硬件解码,graphics是图形显示。通常都写上,因为graphics这个没啥用加上避免出问题 - 如果加了
--runtime=nvidia
成功,并且配置了--gpus=all
,会默认给你配上nvidia的驱动程序,可以使得你正常执行nvidia-smi
你应该知道的是,使用
cuda
= 安装cuda驱动(显卡驱动自动) + cuda toolkits挂载共享内存,用于啥暂时未明确
-v /dev/shm:/dev/shm
:映射容器的共享内存,使用物理机的共享内存
- 有一个开源方案,别人配置好了vnc,可以直接使用
- https://registry.hub.docker.com/r/dorowu/ubuntu-desktop-lxde-vnc
- 这个方案帮你配置好了vnc,可以直接下载vnc viewer直接连接并可视化
- 他是一个精简版的gnome桌面,比ubuntu的桌面要简洁很多,功能少很多,但是不妨碍做基本的研究和使用
我配置好的容器:
- https://registry.hub.docker.com/r/hopef/tensorrt-pro
- 里面附带了必要的大部分库
最后的高级内容6-如何修改已经配置好的参数
如果端口、盘等参数已经映射设置好,容器已经在使用,之后想增加新的端口或者盘,该怎么操作?
- 需要了解docker容器存放的位置,一般是在:
/var/lib/docker/containers/
下,通过sudo ls /var/lib/docker/containers
来查看目录下文件,sudo下,tab补全不能用 - 通过容器id的前缀,查找文件夹名字,然后
sudo ls /var/lib/docker/containers/c213305b2379ed94db47d15dcf0013b91fd87ecd8b0c491a66f46c58d591c89f
查看容器下的文件 - 这里面有好几个文件,可以通过
sudo cp -r/var/lib/docker/containers/c213305b2379ed94db47d15dcf0013b91fd87ecd8b0c491a66f46c58d591c89f/ ./
复制到当前目录来。不能用*
进行匹配 - 为当前目录的容器配置所属权
sudo chown -R th:th .
,这里的th:th
是当前电脑的用户名- 里面的文件因为具有super user权限,所以需要修改所属才可以访问
- 里面的
config.v2.json
和hostconfig.json
就是容器的配置储存位置 - 右键格式化可以在vscode中变得可读
MountPoints
是挂载点,可以直接修改添加之类的操作
- 在复制后的副本上修改,修改完成后,通过
sudo cp
指令复制回去 - 一定要注意,需要执行
sudo service docker stop
,关闭docker
服务后,然后再把config.v2.json
、hostconfig.json
复制出来,进行修改。再复制回去,再通过sudo service docker start
启动服务,修改才可生效,否则无效。 - 复制回去只需要修改
config.v2.json
、hostconfig.json
,不要尝试修改任何其他文件,否则可能会使得容器坏掉案例
```shell!/bin/bash
array=() varname=(“ImageName” “ContainerName” “PortPrefix”) defval=(“template” “vnc-ros” “111”)
for i in $(seq 0 2) do type=${varname[i]} typeval=${defval[i]} input=””
read -p “Enter your ${type}[default ‘${typeval}’]: “ input if [ “$input” == “” ]; then input=”$typeval” fi
array+=(“${input}”) done
HostData=pwd
/data
ImageName=${array[0]}
ContainerName=${array[1]}
PortPrefix=${array[2]}
echo Make new container, name is ${ContainerName}, image is ${ImageName}, port_prefix is ${PortPrefix} sudo docker run -itd \ —runtime=nvidia —gpus=all \ -e NVIDIA_DRIVER_CAPABILITIES=compute,utility,video,graphics \ -v ${HostData}:/datav \ -p ${PortPrefix}80:80 \ -p ${PortPrefix}90:5900 \ -p ${PortPrefix}22:22 \ —name $ContainerName —privileged=true \ -v /dev/shm:/dev/shm \ ${ImageName} \ /startup.sh
echo Done, VNC Port is ${PortPrefix}90, SSH Port is ${PortPrefix}22 for root, All password is “123”