Docker是个好东西,或者说容器是个好东西。
毕竟回忆里的昨天,我再也回不去。
但容器可以。
Docker存储方式
还是先说一下Docker容器的储存结构,容器镜像采用的是分层存储的方式,下面是一个Ubuntu16.04的镜像结构。

也可以在命令行观察,在拉取的时候也可以看到结果:
1 2 3 4 5 6 7 8 9
| $ ▶ docker pull ubuntu:16.04 16.04: Pulling from library/ubuntu 3b37166ec614: Already exists 504facff238f: Already exists ebbcacd28e10: Already exists c7fb3351ecad: Already exists 2e3debadcbf7: Already exists Digest: sha256:45ddfa61744947b0b8f7f20b8de70cbcdd441a6a0532f791fd4c09f5e491a8eb Status: Downloaded newer image for ubuntu:16.04
|
其中,每层表示的是与上一层的差异,而不是直接操作底层镜像,这样,当使用其他基于此镜像制作的镜像时,就不必整个拉取或者复制过来,因为它们很多的底层镜像是一样的。Docker镜像采用的是共享存储方式,当拉取一个镜像时,会首先获取所有层的信息,如果该镜像层本地已经有了,就不用下载,只需要下载所需要的镜像层。

在使用镜像建立容器时候,会在最上面一层镜像上建立一个可写层,即容器层。当在容器中所有的操作都会被保存在这个可写层,如果直接删除容器,则可写层就会被删除,即使利用相同镜像重新建立容器,之前的所有操作也不会被保存。镜像层都是只读的,基于此安全性,所有的容器都可以访问底层镜像,所以一次可以利用同一镜像建立多个容器。最后完成修改封装成新的容器的时候,也只是在原来的镜像层之上又加了一层而已。镜像的这种共享存储方式可以极大地提高资源利用效率,而差异存储也是文件管理的主流之选。
说到这个,想起来目前有个PWD(Play with Docker)的网站,可以直接在里面体验docker,地址在这。进去就可以创建一个Docker playground。

利用Docker运行CUDA和TensorFlow
在电脑上配置CUDA或者TensorFlow啥的,经常因为各种版本不同导致一大堆问题,于是就想看看可不可以利用Docker去解决这个问题,每次直接打开封装好的镜像就行了,让Docker里的环境去使用GPU,不用去配环境,也不用在电脑上装啥别的软件。然后发现NVIDIA也在Docker上稍微封装了一下,弄了个Nvidia-docker命令,基本命令与docker命令一样,唯一的区别是普通的Docker无法使用GPU,所以Nvidia-docker等效于命令docker --runtime=nvidia。
要使用GPU,首先也要安装好显卡驱动,怎么安装这里不做赘述,通常安装成功是可以看到的。

当然,Docker肯定要先装好。
Nvidia Docker
然后就是安装Nvidia封装的Docker来调用GPU了,具体可以参照NVIDIA/nvidia-docker页面。

如果之前有安装1.0版本的Nvidia-docker的,需要先卸载:
1 2 3
| # If you have nvidia-docker 1.0 installed: we need to remove it and all existing GPU containers docker volume ls -q -f driver=nvidia-docker | xargs -r -I{} -n1 docker ps -q -a -f volume={} | xargs -r docker rm -f sudo apt-get purge -y nvidia-docker
|
没有的话可以直接略过。然后添加仓库地址重定向到镜像源文件中,再更新软件源。
1 2 3 4 5 6 7
| # Add the package repositories curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ sudo apt-key add - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -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
|
然后直接安装即可。
1 2 3
| # Install nvidia-docker2 and reload the Docker daemon configuration sudo apt-get install -y nvidia-docker2 sudo pkill -SIGHUP dockerd
|
CUDA测试
首先运行一个cuda的镜像,进入bash中,
1 2 3
| docker run --runtime=nvidia -it --name cuda --rm nvidia/cuda:9.0-base /bin/bash root@c1d523d61051:/# root@c1d523d61051:/#
|
这里将容器命名为cuda方便操作,需要选择runtime为nvidia,或者直接使用nvidia-docker命令。然后输入nvidia-smi就可以看到是否成功调用显卡了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| root@c1d523d61051:/# nvidia-smi Thu Oct 11 07:51:19 2018 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 384.130 Driver Version: 384.130 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 GeForce GTX 1080 Off | 00000000:01:00.0 On | N/A | | 0% 44C P8 14W / 200W | 867MiB / 8110MiB | 0% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| +-----------------------------------------------------------------------------+
|
TensorFlow测试
刚刚也说了,如果要使用GPU,需要在docker命令中加上–runtime=nvidia或者直接使用nvidia-docker命令。这里就直接使用nvidia-docker命令了,
1 2
| $ ▶ nvidia-docker run -it -d --name tensor -p 8888:8888 tensorflow/tensorflow 9c7db93b36788acf61a20f52cb187f32e0d6018f7e8da031a30fa135252a4896
|
查看容器内信息,
1 2 3 4 5 6 7 8 9 10 11
| docker logs tensor [I 08:01:55.452 NotebookApp] Writing notebook server cookie secret to /root/.local/share/jupyter/runtime/notebook_cookie_secret [I 08:01:55.465 NotebookApp] Serving notebooks from local directory: /notebooks [I 08:01:55.465 NotebookApp] The Jupyter Notebook is running at: [I 08:01:55.465 NotebookApp] http://(9c7db93b3678 or 127.0.0.1):8888/?token=64e73aaba8febd5539fae22201c7b7cea1b8578cc1413850 [I 08:01:55.465 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). [C 08:01:55.466 NotebookApp] Copy/paste this URL into your browser when you connect for the first time, to login with a token: http://(9c7db93b3678 or 127.0.0.1):8888/?token=64e73aaba8febd5539fae22201c7b7cea1b8578cc1413850
|
打开浏览器窗口,输入localhost:8888/?token=64e73aaba8febd5539fae22201c7b7cea1b8578cc1413850,可以看到一个Jupyter的界面。

在里面可以编辑及运行python程序,或者使用终端操作:
1 2 3 4 5 6 7 8 9 10
| $ ▶ docker exec -it tensor /bin/bash root@9c7db93b3678:/notebooks# ls 1_hello_tensorflow.ipynb 2_getting_started.ipynb 3_mnist_from_scratch.ipynb BUILD LICENSE root@9c7db93b3678:/notebooks# python python python2 python2.7 python3 python3.5m python-config python2-config python2.7-config python3.5 python3m root@9c7db93b3678:/notebooks# python Python 2.7.12 (default, Dec 4 2017, 14:50:18) [GCC 5.4.0 20160609] on linux2 Type "help", "copyright", "credits" or "license" for more information.
|
关于Docker的Runtime
一个容器运行需要制定规范、Runtime、管理和定义工具、镜像仓库、运行OS等环节。容器的Runtime是容器运行时的一些规范,主要任务是和操作系统的kernel协作来提供容器的运行环境,由OCI(Open Container Initiative,由Google,Docker、CoreOS、IBM、微软、红帽等于2015年联合发起的组织)维护。主要包括容器的文件系统包(Filesystem Bundle),容器的运行和生存周期Runtime and Lifecycle),容器配置文件(Container Configuration file),以及Linux的运行和配置文件(Linux Runtime, Linux Container Configuration)等。目前Linux上最原始的容器Runtime是LXC,即Linux Container,最初Docker也是用LXC作为Runtime,后来Docker基于libcontainer开发了自己的Runtime,即runC。谷歌也基于Docker的Runtime发布了Kubernetes,后来CoreOS开发了独立的rkt作为运行容器的Runtime。
而与容器相对的就是虚拟机了,目前虚拟机的Runtime如runV,看名字就知道是要与runC分庭抗礼的。此外Intel也弄了一个Clear containers的Runtime,也可以对接容器。基于Hyper runV和Clear containers,Openstack又新起了一个Kata Containers,目前已经可以在snap商店看到了,才出来没多久,地址在这。
利用Docker搭建私有云盘
安装
这里使用的是一个开源的云存储方案OwnCloud来搭建私有云盘。
首先可以搜一下Dockerhub中的镜像,docker search owncloud可以看到结果:

其中第一个就是官方的镜像了,直接docker pull owncloud:8.1拉取就行。或者也可以直接docker run,本地没有它会去Dockerhub下载。
1
| docker run -d -p 80:80 owncloud:8.1
|
其中,-d表示后台运行,-p用来映射端口。也可以直接用-it前台打开tty直接操作。
这时候可以在浏览器中看到了,输入localhost就可以看到登陆界面,大致是下面的样子:

运行配置
其中数据保存在/var/www/html/data目录中,默认是使用SQLite用于数据存储,但对于较大的或者使用桌面客户端同步文件时,并不推荐SQLite,可以考虑最流行的MySQL。其他数据库需要外部安装。
在运行时可以使用-v选项来将本地磁盘挂载到容器中数据保存的位置,即/var/www/html/中。
1
| -v /<mydatalocation>:/var/www/html
|
分的更细一点,可以添加三项,设置命令:
1 2 3
| -v /<mydatalocation>/apps:/var/www/html/apps installed / modified apps -v /<mydatalocation>/config:/var/www/html/config local configuration -v /<mydatalocation>/data:/var/www/html/data the actual data of your ownCloud
|
数据库配置
外部数据库配置有几种方法,第一个是使用Owncloud自己提供的OCC工具(OwnCloud Console)来配置,使用docker exec执行:
1
| docker exec -u www-data some-owncloud php occ status
|
另外的就是用Docker的工具了,Docker Stack或者Docker Compose来配置。首先需要编辑一个yml配置文件,如stack.yml或compose.yml,名字随便起,然后加入数据库配置:
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
| # ownCloud with MariaDB/MySQL # # Access via "http://localhost:8080" (or "http://$(docker-machine ip):8080" if using docker-machine) # # During initial ownCloud setup, select "Storage & database" --> "Configure the database" --> "MySQL/MariaDB" # Database user: root # Database password: example # Database name: pick any name # Database host: replace "localhost" with "mysql" version: '3.1' services: owncloud: image: owncloud:8.1 restart: always ports: - 8080:80 volumes: - "/home/newdee/Downloads/owncloud/:/var/www/html/" mysql: image: mysql:5.6 restart: always environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: owncloud MYSQL_USER: first MYSQL_PASSWORD: 123456
|
最后运行docker stack deploy -c stack.yml owncloud (or docker-compose -f compose.yml up)即可。
此时可以发现有两个容器正在运行:
1 2 3 4
| $ ▶ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8499dc015bc8 owncloud:8.1 "/entrypoint.sh apac…" 15 minutes ago Up 12 minutes 0.0.0.0:8080->80/tcp owncloud_owncloud_1 6e145ebcca20 mysql:5.6 "docker-entrypoint.s…" 15 minutes ago Up 12 minutes 3306/tcp owncloud_mysql_1
|
然后在浏览器输入http://localhost:8080可以看到登陆界面,登录信息填yml文件中的信息就行。

登陆成功就可以看到登陆界面了。然后就可以网页上传下载了,还可以生成分享链接。上传下载地址位于挂载的目录中。没有机子也可以去试试VPS,自己搭一个私有云盘用来平时备份下载。
