Docker 是个很好用的东西,你可以把它类比为虚拟机,但它比虚拟机更轻量,虚拟所带来的性能损失更低。在容器内(可以类比为虚拟系统)可以安装任意版本工具和依赖包,在配置开发环境过程中出现问题,直接删除容器就好。

Docker基本概念

  • 镜像(Image)

Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。

  • 容器(Container)

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样;
1、镜像是静态的定义,容器是镜像运行时的实体;
2、容器可以被创建、启动、停止、删除、暂停等。

  • 仓库(Repository)

镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。一个 Docker Registry 中可以包含多个 仓库(Repository)每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像

Docker 安装

why?Because Docker 可以方便的安装深度学习环境(cuda+cudnn+tensorflow-gpu/pytorch),一键打包成镜像,解决不同电脑下软硬件的不同导致各种bug 满天飞的痛点!

1. Docker的安装

链接:https://docs.docker.com/install/linux/docker-ce/ubuntu/

跟着教程一路复制粘贴回车即可。
唯一的难点就是看懂英文的安装教程,看清楚段落层次结构。
反正,最后如果你运行sudo docker run hello-world,可以跑通,看到:
2022-03-15-Docker教程 - 图1
就说明Docker已经被你成功安装了!


2. Nvidia-docker的安装

为何又蹦出来一个nvidia-docker?由于默认安装的docker都是基于cpu版本的,如果想要配合GPU进行一些简单的部署的话,则需要安装nvidia-docker来支持GPU加速。所以NVIDIA单独做了一个docker,来让docker镜像可以使用NVIDIA的gpu。

链接:https://github.com/NVIDIA/nvidia-docker

也是直接找对应的操作系统的命令,一行行复制粘贴回车就搞定了。
反正,最后当你运行docker run —runtime=nvidia —rm nvidia/cuda:9.0-base nvidia-smi时,如果看到:
2022-03-15-Docker教程 - 图2
恭喜,安装成功了!


3. 深度学习镜像的安装

我这里使用镜像是deepo一款咱们中国人做出来的深度学习镜像,包含了现在多数流行的深度学习框架,而且版本也很新,所以我这个小白第一次就选择了这个。

链接:https://hub.docker.com/r/ufoym/deepo

只要安装好了前面的docker和nvidia-docker,这里就很方便了。
直接通过命令docker pull ufoym/deepo就可以把各种框架都下载下来。但是这样比较大,费时较长,所以教程里面也提供了只安装其中某一种框架的方式:

  1. docker pull ufoym/deepo:tensorflow


另外,还提供了jupyter notebook版的镜像,我这里就是安装的这个,因为我日常基本都是使用jupyter notebook,这里贴一下我的命令:

  1. sudo docker pull ufoym/deepo:all-jupyter-py36-cu100

这里的all-jupyter-py36-cu100也是deepo提供的jupyter notebook镜像的tag。
安装好之后,通过docker images命令,可以查看已经下载好的镜像:
image.png
好了,该装的东西都装好了,下面进入操作部分了!

PS: Docker 拉取镜像比较慢的解决方法

解决方法是 在/etc/docker文件夹下 修改daemon.json ,如果不存在这样的文件 新建一个即可.

  1. cd /etc/docker
  2. sudo vim daemon.json

然后编辑文件内容

  1. {
  2. "registry-mirrors":[
  3. "https://9cpn8tt6.mirror.aliyuncs.com",
  4. "https://registry.docker-cn.com"
  5. ]
  6. }
  1. sudo service docker restart
  2. sudo systemctl status docker
  3. # 以下命令还未尝试过
  4. sudo systemctl enable docker # 开机自动启动docker
  5. sudo systemctl start docker # 启动docker
  6. sudo systemctl restart docker # 重启dokcer
  7. sudo systemctl daemon-reload

重新试下docker pull 绝对速度飞起来~

镜像入门篇

如何获取镜像呢?

Docker 一般会将一些镜像放到 Docker Hub 上面,那么我们怎么才能获取到这些镜像呢?可以 采用以下命令获取镜像:

  1. $ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

docker pull 属于基本命令
[Docker Registry 地址[:端口号]:这个为 Docker 镜像仓库地址,默认地址为 Docker Hub(docker.io);
仓库名[:标签]:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

  • 实例
    1. docker pull ubuntu:18.04
    2. docker pull nvidia/cuda:10.0-base nvcc --version
    注:上面的命令中没有给出 Docker 镜像仓库地址,因此将会从 Docker Hub (docker.io)获取镜像。而镜像名称是 ubuntu:18.04,因此将会获取官方镜像 library/ubuntu 仓库中标签为 18.04 的镜像。docker pull 命令的输出结果最后一行给出了镜像的完整名称,即: docker.io/library/ubuntu:18.04。

如何 展示 镜像内容?

可以 采用 以下命令 对想要的内容镜像内容进行查看

  1. # 方式一
  2. $ docker image ls
  3. # 方式二
  4. $ docker images
  5. >>> output
  6. REPOSITORY TAG IMAGE ID CREATED SIZE
  7. ubuntu latest 8e428cff54c8 2 weeks ago 72.9MB
  8. ubuntu 18.04 3339fde08fc3 2 weeks ago 63.3MB
  9. hello-world latest d1165f221234 5 weeks ago 13.3kB
  10. alpine/git latest a939554ad0d0 7 weeks ago 25.1MB

注:在 上面内容中,我们可以查看 我们所下载的 镜像【REPOSITORY】,版本【TAG】,镜像 ID 【IMAGE ID】 ,镜像创建时间【CREATED】 和 大小【SIZE】

如何删除本地镜像?

我们可以采用以下 四种方式 删除镜像

  1. # 方式一:输入 长 id
  2. $ docker image rm 8e428cff54c8
  3. # 方式二:输入 短 id
  4. $ docker image rm 8e4

注:一般可以用镜像的完整 ID,也称为 长ID,来删除镜像。使用脚本的时候可能会用长 ID,但是人工输入就太累了,所以更多的时候是用 短ID 来删除镜像。

Docker容器入门

How to 新建容器?

  1. docker run hello-world
  2. docker run -it -d -p 10086:10086 --name nsx_cuda -v /data/ningshixian:/data/ningshixian 镜像id /bin/bash
  3. nvidia-docker run -it -d -p 10086:10086 --name=nsx_cuda -v /data/ningshixian:/data/ningshixian 镜像id /bin/bash
  4. # --ipc=host --runtime=nvidia

注:

  • -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上;
  • -i 交互式操作
  • -d 让 Docker 在后台运行而不是直接把执行命的结果输出在当前宿主机下
  • -p 端口映射
  • —name 自命名启动一个容器
  • -v /data/ningshixian:/data/ningshixian 可以将主机上的/data/ningshixian 地址挂载到容器里,并命名为/data/ningshixian 文件夹,这样这个文件夹的内容可以在容器和主机之间共享了。因为容器一旦关闭,容器中的所有改动都会清除,所以这样挂载一个地址可以吧容器内的数据保存到本地。
  • ubuntu: 基于ubuntu image创建 container
  • 0bedd0dfd4cb 则是你安装的 nvidia/cuda:9.0-base 镜像的id
  • /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。

新建好容器之后,就可以进行自定义的环境配置了:

解决Ubuntu终端下载速度过慢问题

  1. # 进入容器后执行
  2. apt-get update
  3. # apt-get upgrade
  4. apt-get install vim git
  5. wget https://repo.anaconda.com/archive/Anaconda3-2020.11-Linux-x86_64.sh
  6. wget -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2020.11-Linux-x86_64.sh
  7. # 进入下载目录...
  8. sudo bash Anaconda3-2020.11-Linux-x86_64.sh
  9. # Anaconda安装过程...记得添加环境变量yes
  10. # 换清华源
  11. conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
  12. conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge
  13. conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
  14. # 设置搜索时显示通道地址
  15. conda config --set show_channel_urls yes
  16. # 创建keras环境
  17. conda create -n nsx_env python=3.7
  18. # 切换环境
  19. conda activate nsx_env
  20. # 在Ubuntu中提供编译c/c++的环境(可略)
  21. apt-get install build-essential -y
  22. # conda install cudatoolkit=10.1 cudnn=7.6.5
  23. conda install cudatoolkit=10.0 cudnn=7.6.5
  24. # 装完就完事了
  25. 写个程序跑一下,缺啥再pip

How to 查看容器?

  • 查看所有容器

    1. docker ps -a
  • 查看 在后台运行的容器

    1. docker ps -n 5

    ps: -n 表示显示前 n 个活跃容器

How to 删除容器呢?

  1. docker stop container-id
  2. docker rm container-id

如何 启动 容器?

上面介绍了 如何查看 容器,但是对于一些未启动的容器, 我们如何启动一个容器呢?

  1. docker start [-i] container-id

启动某个容器,必须是已经创建的。

如何 停止/重启 容器?

docker stop可以停止运行的容器。理解:容器在 docker host 中实际上是一个进程,docker stop命令本质上是向该进程发送一个SIGTERM信号。如果想要快速停止容器,可使用docker kill命令,其作用是向容器进程发送SIGKILL信号。

  1. docker stop container-id
  2. docker restart container-id

如何 进入 容器?

在使用 -d 参数时,容器启动后会进入后台,启动完容器之后会停在host端;某些时候需要进入容器进行操作,包括使用 docker attach 命令或 docker exec 命令,推荐大家使用 docker exec 命令,原因会在下面说明。

  • attach 命令

    1. $ docker run -dit ubuntu
    2. $ docker container ls
    3. $ docker attach $CONTAINER ID

    注意: 如果从这个 stdin 中exit回到host端,会导致容器的停止。

  • exec 命令 ```python $ docker run -dit ubuntu $ docker container ls

$ docker exec -i 69d1 /bin/bash $ docker exec -it 69d1 bash

  1. - -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上;
  2. - -i 则让容器的标准输入保持打开
  3. 注意:如果从这个 stdin exit回到host端,但不会导致容器的停止。这就是为什么推荐大家使用 docker exec 的原因。
  4. attach exec 的区别:
  5. 1. attach直接进入容器启动命令的终端,不会启动新的进程;
  6. 1. exec则是在容器中打开新的终端,并且可以启动新的进程;
  7. 1. 如果想直接在终端中查看命令的输出,用attach,其他情况使用exec
  8. <a name="HCqjK"></a>
  9. ### 如何 退出/离开 容器?
  10. 进入交互模式之后,怎么**退出**呢:
  11. - 想退出但是保持容器运行,按 CTRL+P && CTRL+Q
  12. - 退出,并关闭停止容器,按CTRL+D或者输入exit再回车
  13. <a name="i20CJ"></a>
  14. ### 导出和导入容器
  15. - **导出容器**
  16. 如果要导出本地某个容器,可以使用 **docker export** 命令,导出容器 1e560fca3906 快照到本地文件 ubuntu.tar
  17. ```python
  18. $ docker export 1e560fca3906 > ubuntu.tar
  • 导入容器快照

可以使用 docker import 从容器快照文件中再导入为镜像,以下实例将快照文件 ubuntu.tar 导入到镜像 test/ubuntu:v1:

  1. $ cat docker/ubuntu.tar | docker import - test/ubuntu:v1

Docker容器保存为镜像文件

https://zhuanlan.zhihu.com/p/348849578

运行一个docker container,然后在其中进行定制化(安装、配置服务等)之后,将其打包成镜像,方便迁移至其他机器,快速搭建回之前的环境!!

方法 1:docker commit(方便)

  1. # 将容器打包成镜像
  2. # docker commit 容器id 镜像起名:版本号
  3. docker commit d5944567401a mssql-2019-with-cimb:1.0
  4. # 将镜像保存为本地文件
  5. # docker save -o 本地文件名称 要打包的镜像名称:版本号
  6. docker save -o mssql-2019-with-cimb.tar mssql-2019-with-cimb
  7. # 从文件载入镜像
  8. docker load --input 本地文件名称
  9. docker images


方法 2:docker build (推荐)
使用 Dockerfile 文件自动化制作 image

  1. docker build -f ./Dockerfile -t 镜像名称:版本号

Docker jupyter notebook 服务 [力荐!]

1.如何创建自己的可以远程访问的容器:

  1. sudo nvidia-docker run -it -p 7777:8888 --ipc=host -v /data/ningshixian:/data/ningshixian --name nsx-notebook 90be7604e476

其中:

  • -it为直接进入交互式
  • -p 7777:8888是把主机的7777端口映射到容器的8888端口
  • -ipc=host可以让容器与主机共享内存
  • 还可以加一个—name xxxxx给容器定义一个个性化名字
  • -v /data/ningshixian:/data/ningshixian 可以将主机上的/data/ningshixian 地址挂载到容器里,并命名为/data/ningshixian 文件夹,这样这个文件夹的内容可以在容器和主机之间共享了。因为容器一旦关闭,容器中的所有改动都会清除,所以这样挂载一个地址可以吧容器内的数据保存到本地。
  • 90be7604e476则是你安装的jupyter镜像的id,可以在刚刚docker images命令后面查看,当然你也可以直接写全名ufoym/deepo:all-py36-jupyter

2.创建了容器之后,我们可以进而启动jupyter notebook:

  1. jupyter notebook --no-browser --ip=0.0.0.0 --allow-root --NotebookApp.token= --notebook-dir='/data/ningshixian'

其中:

  • —no-browser即不通过浏览器启动,—ip指定容器的ip,—allow-root允许root模型运行
  • —NotebookApp.token可以指定jupyter 登录密码,可以为空
  • —notebook-dir=’/data/ningshixian’ 指定jupyter的根目录

3.开启本地与服务器的端口映射,从而远程登录jupyter:

本地机器上,执行如下命令:

  1. ssh username@host-ip -L 1234:127.0.0.1:7777

这样,可以将本地的1234端口,映射到服务器的localhost的7777端口(即你前面创建jupyter容器时候的指定的服务器端口)
这样,你在本地电脑的浏览器里输入’localhost:1234’,即可登录到服务器上的jupyter notebook了!
2022-03-15-Docker教程 - 图4
2022-03-15-Docker教程 - 图5
既能远程访问高性能服务器,又可以像在本地一样便捷地操作,你说激动不激动你说激动不激动?

参考