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,可以跑通,看到:
就说明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时,如果看到:
恭喜,安装成功了!
3. 深度学习镜像的安装
我这里使用镜像是deepo一款咱们中国人做出来的深度学习镜像,包含了现在多数流行的深度学习框架,而且版本也很新,所以我这个小白第一次就选择了这个。
链接:https://hub.docker.com/r/ufoym/deepo
只要安装好了前面的docker和nvidia-docker,这里就很方便了。
直接通过命令docker pull ufoym/deepo就可以把各种框架都下载下来。但是这样比较大,费时较长,所以教程里面也提供了只安装其中某一种框架的方式:
docker pull ufoym/deepo:tensorflow
另外,还提供了jupyter notebook版的镜像,我这里就是安装的这个,因为我日常基本都是使用jupyter notebook,这里贴一下我的命令:
sudo docker pull ufoym/deepo:all-jupyter-py36-cu100
这里的all-jupyter-py36-cu100也是deepo提供的jupyter notebook镜像的tag。
安装好之后,通过docker images命令,可以查看已经下载好的镜像:
好了,该装的东西都装好了,下面进入操作部分了!
PS: Docker 拉取镜像比较慢的解决方法
解决方法是 在/etc/docker文件夹下 修改daemon.json ,如果不存在这样的文件 新建一个即可.
cd /etc/docker
sudo vim daemon.json
然后编辑文件内容
{
"registry-mirrors":[
"https://9cpn8tt6.mirror.aliyuncs.com",
"https://registry.docker-cn.com"
]
}
sudo service docker restart
sudo systemctl status docker
# 以下命令还未尝试过
sudo systemctl enable docker # 开机自动启动docker
sudo systemctl start docker # 启动docker
sudo systemctl restart docker # 重启dokcer
sudo systemctl daemon-reload
重新试下docker pull 绝对速度飞起来~
镜像入门篇
如何获取镜像呢?
Docker 一般会将一些镜像放到 Docker Hub 上面,那么我们怎么才能获取到这些镜像呢?可以 采用以下命令获取镜像:
$ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
docker pull 属于基本命令
[Docker Registry 地址[:端口号]:这个为 Docker 镜像仓库地址,默认地址为 Docker Hub(docker.io);
仓库名[:标签]:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。
- 实例
注:上面的命令中没有给出 Docker 镜像仓库地址,因此将会从 Docker Hub (docker.io)获取镜像。而镜像名称是 ubuntu:18.04,因此将会获取官方镜像 library/ubuntu 仓库中标签为 18.04 的镜像。docker pull 命令的输出结果最后一行给出了镜像的完整名称,即: docker.io/library/ubuntu:18.04。docker pull ubuntu:18.04
docker pull nvidia/cuda:10.0-base nvcc --version
如何 展示 镜像内容?
可以 采用 以下命令 对想要的内容镜像内容进行查看
# 方式一
$ docker image ls
# 方式二
$ docker images
>>> output
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 8e428cff54c8 2 weeks ago 72.9MB
ubuntu 18.04 3339fde08fc3 2 weeks ago 63.3MB
hello-world latest d1165f221234 5 weeks ago 13.3kB
alpine/git latest a939554ad0d0 7 weeks ago 25.1MB
注:在 上面内容中,我们可以查看 我们所下载的 镜像【REPOSITORY】,版本【TAG】,镜像 ID 【IMAGE ID】 ,镜像创建时间【CREATED】 和 大小【SIZE】
如何删除本地镜像?
我们可以采用以下 四种方式 删除镜像
# 方式一:输入 长 id
$ docker image rm 8e428cff54c8
# 方式二:输入 短 id
$ docker image rm 8e4
注:一般可以用镜像的完整 ID,也称为 长ID,来删除镜像。使用脚本的时候可能会用长 ID,但是人工输入就太累了,所以更多的时候是用 短ID 来删除镜像。
Docker容器入门
How to 新建容器?
docker run hello-world
docker run -it -d -p 10086:10086 --name nsx_cuda -v /data/ningshixian:/data/ningshixian 镜像id /bin/bash
nvidia-docker run -it -d -p 10086:10086 --name=nsx_cuda -v /data/ningshixian:/data/ningshixian 镜像id /bin/bash
# --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。
新建好容器之后,就可以进行自定义的环境配置了:
# 进入容器后执行
apt-get update
# apt-get upgrade
apt-get install vim git
wget https://repo.anaconda.com/archive/Anaconda3-2020.11-Linux-x86_64.sh
wget -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2020.11-Linux-x86_64.sh
# 进入下载目录...
sudo bash Anaconda3-2020.11-Linux-x86_64.sh
# Anaconda安装过程...记得添加环境变量yes
# 换清华源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
# 设置搜索时显示通道地址
conda config --set show_channel_urls yes
# 创建keras环境
conda create -n nsx_env python=3.7
# 切换环境
conda activate nsx_env
# 在Ubuntu中提供编译c/c++的环境(可略)
apt-get install build-essential -y
# conda install cudatoolkit=10.1 cudnn=7.6.5
conda install cudatoolkit=10.0 cudnn=7.6.5
# 装完就完事了
写个程序跑一下,缺啥再pip
How to 查看容器?
查看所有容器
docker ps -a
查看 在后台运行的容器
docker ps -n 5
ps: -n 表示显示前 n 个活跃容器
How to 删除容器呢?
docker stop container-id
docker rm container-id
如何 启动 容器?
上面介绍了 如何查看 容器,但是对于一些未启动的容器, 我们如何启动一个容器呢?
docker start [-i] container-id
启动某个容器,必须是已经创建的。
如何 停止/重启 容器?
docker stop可以停止运行的容器。理解:容器在 docker host 中实际上是一个进程,docker stop命令本质上是向该进程发送一个SIGTERM信号。如果想要快速停止容器,可使用docker kill命令,其作用是向容器进程发送SIGKILL信号。
docker stop container-id
docker restart container-id
如何 进入 容器?
在使用 -d 参数时,容器启动后会进入后台,启动完容器之后会停在host端;某些时候需要进入容器进行操作,包括使用 docker attach 命令或 docker exec 命令,推荐大家使用 docker exec 命令,原因会在下面说明。
attach 命令
$ docker run -dit ubuntu
$ docker container ls
$ 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
- -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上;
- -i 则让容器的标准输入保持打开
注意:如果从这个 stdin 中 exit回到host端,但不会导致容器的停止。这就是为什么推荐大家使用 docker exec 的原因。
attach 和 exec 的区别:
1. attach直接进入容器启动命令的终端,不会启动新的进程;
1. exec则是在容器中打开新的终端,并且可以启动新的进程;
1. 如果想直接在终端中查看命令的输出,用attach,其他情况使用exec;
<a name="HCqjK"></a>
### 如何 退出/离开 容器?
进入交互模式之后,怎么**退出**呢:
- 想退出但是保持容器运行,按 CTRL+P && CTRL+Q
- 退出,并关闭停止容器,按CTRL+D或者输入exit再回车
<a name="i20CJ"></a>
### 导出和导入容器
- **导出容器**
如果要导出本地某个容器,可以使用 **docker export** 命令,导出容器 1e560fca3906 快照到本地文件 ubuntu.tar
```python
$ docker export 1e560fca3906 > ubuntu.tar
- 导入容器快照
可以使用 docker import 从容器快照文件中再导入为镜像,以下实例将快照文件 ubuntu.tar 导入到镜像 test/ubuntu:v1:
$ cat docker/ubuntu.tar | docker import - test/ubuntu:v1
Docker容器保存为镜像文件
运行一个docker container,然后在其中进行定制化(安装、配置服务等)之后,将其打包成镜像,方便迁移至其他机器,快速搭建回之前的环境!!
方法 1:docker commit(方便)
# 将容器打包成镜像
# docker commit 容器id 镜像起名:版本号
docker commit d5944567401a mssql-2019-with-cimb:1.0
# 将镜像保存为本地文件
# docker save -o 本地文件名称 要打包的镜像名称:版本号
docker save -o mssql-2019-with-cimb.tar mssql-2019-with-cimb
# 从文件载入镜像
docker load --input 本地文件名称
docker images
方法 2:docker build (推荐)
使用 Dockerfile 文件自动化制作 image
docker build -f ./Dockerfile -t 镜像名称:版本号
Docker jupyter notebook 服务 [力荐!]
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:
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:
在本地机器上,执行如下命令:
ssh username@host-ip -L 1234:127.0.0.1:7777
这样,可以将本地的1234端口,映射到服务器的localhost的7777端口(即你前面创建jupyter容器时候的指定的服务器端口)
这样,你在本地电脑的浏览器里输入’localhost:1234’,即可登录到服务器上的jupyter notebook了!
既能远程访问高性能服务器,又可以像在本地一样便捷地操作,你说激动不激动你说激动不激动?