Skip to content

Instantly share code, notes, and snippets.

@demon386
Last active May 26, 2017 07:37
Show Gist options
  • Save demon386/2da7b9db07d6a5342252d4dcfd92f293 to your computer and use it in GitHub Desktop.
Save demon386/2da7b9db07d6a5342252d4dcfd92f293 to your computer and use it in GitHub Desktop.
进阶:用 Docker 打造自己的开发环境

进阶:用 Docker 打造自己的开发环境

基本技巧

在预备课程当中,我们已经初步介绍过如何使用 Docker 启动 Tensorflow 环境,并把 Docker 内部的 jupyter notebook 端口暴露给本机。其中介绍的主要命令包括

docker run -it -p 8888:8888 tensorflow/tensorflow
用于以某个 image 为模板,启动一个 container (注意区分 image 和 container 的概念)
docker ps, docker ps -a
分别用于查看正在运行的 container,以及所有的 container(包括已经停止的)
docker start -i container_id
其中 container_id 是通过 docker ps -a 命令看到的,用于启动一个已经停止的 container
docker stop container_id
停止一个正在运行的 container

大家在使用 docker 的时候,可以把 image 理解成一张『操作系统』的光盘,container 就是一台用这张光盘装好系统的『虚拟计算机』。

常见的一个误区,是不断用 docker run 重新建立 container。这样会消耗一些硬盘资源,长时间之后,在 docker ps -a 中会看到大量停止的 container。正确的方法应该是用 docker start -i container_id 来『启动』之前停止的 container。

使用 Docker 的好处

大家可能发现,Docker 在镜像已经下载好之后,建立 container 的速度非常快。因此 Docker 相对常规的虚拟机更加轻量级。使用 Docker 可以避免很多环境不一致问题,同时保证你的宿主操作系统干净。

docker 启动参数更改

一些同学可能会发现,虽然 docker start -i 可以重新『启动』之前的 container,但是 docker start 的参数似乎不如 docker run 丰富,比如我想增加一个端口映射,或者多 mount 本地的一个目录。这时候会发现 start 没有办法增加这些参数

docker start -p 1234:1234 -i container_id
这样运行,会显示 unknown shorthand flag: 'p' in -p1234:1234

这个其实是目前 docker 的一些限制,那么假如我想要增加一个端口,或者 mount 一个新目录。是不是就得重新用 docker run 生成一个新的 container 呢?这样的话,已有的环境可能用了一段时间,积累的东西也比较多了,似乎有点浪费。

容器变镜像

Docker 提供了一个命令,可以把自己当前运行的某个容器,变成一个新的镜像。如果自己折腾过系统安装的同学,应该用过 Ghost,这个软件可以把当前某个硬盘备份成一个 image 文件,然后我们把这个 image 文件刻录到光盘里,就可以带着这个光盘到处『复制』我们自己的操作系统了。

Docker 提供的这个命令是 docker commit container_id image_namecontainer_id 通过 docker ps -a 查看。注意要先 stop 这个 container,才能 commit 为一个 image。

commit 成功之后,可以通过 docker images 去看系统中已有的 image,就会发现自己刚刚建设好的 image 了。

有了新 image 之后,用这个新 image 作为参数重新 run ,就可以以新的参数启动 container 了。这时候加端口映射,mount 本地目录都不是问题。

  • Tips: 通过提供多个 -p, -v 参数,可以分别映射多个端口,mount 多个目录。 如 docker start -p 1234:1234 -p 8888:8888 -i container_id
  • Tips: 可以不断地 commit 到同一个 image 名字上,新的 commit 会覆盖旧的

Ubuntu 环境打造

为了节省资源,一般的 Docker 镜像都安装了一个非常简洁的系统。官方的 tensorflow 镜像是基于 ubuntu 的,其 image 构建的逻辑感兴趣的话可以参考 https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tools/docker/Dockerfile

假设我们希望把自己的开发环境变得更强大,希望长期用这个 container 做一些开发的话,我们可以在这个简洁的系统上动一些手术。

常规来说,一个 Container 只会执行一个主程序,我们的 tensorflow 容器执行的是 jupyter notebook。

如果要执行更多的程序,比如进入容器的 bash,可以用 exec 的方式执行

  • docker exec -it container_id echo hello
  • docker exec -it container_id /bin/bash

进入之后,就可以用 ubuntu 的一些命令安装自己需要的软件。默认的 apt 镜像用的是国外的服务器,下载软件会比较慢。我们可以换成网易的镜像。

vi /etc/apt/sources.list 。把文件内容更换成

deb http://mirrors.163.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-backports main restricted universe multiverse

之后执行 apt-get update ,然后就可通过 apt-get install 来安装软件,如 apt-get install vim git

  • Tips: 如果想在 docker exec 之后使用 tmux, screen 之类的终端软件, 目前似乎 docker 有问题不支持 ( lh),可以参见下面直接 docker run 启动 bash 的方案。

更改 Docker 启动命令

假设我们更进一步,把容器当成一个 linux 来用。即启动时不直接启动 tensorflow,而是进入 bash,应该怎么做呢?

首先 commit 来将现在的 container 做成 image,然后重新启动一个新的 container。这时在启动时在尾部加一个新参数 /bin/bash

  • docker run -it -p 8888:8888 image_name /bin/bash

这样就更改了 container 的启动命令。在这个 bash 之下,你可以自由地做各种事情。而且这个 bash 里面可以启动 tmux, screen 之类的多终端工具。

这样这个环境启动的就是 bash 而不是 jupyter notebook 了。这时候需要自行运行 jupter notebook 来启动服务。

Docker 镜像的保存与恢复

如果需要将一台机器里的容器『转移』到另一台机器,可以先把容器 commit 成镜像,然后将镜像导出成压缩文件。

docker save image_name | gzip -c > image_name.tgz

在另一台机器读取

gunzip -c image_name.tgz | docker load
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment