宋宝华Docker-最初的2小时Docker从入门到入门

7次阅读

共计 6621 个字符,预计需要花费 17 分钟才能阅读完成。

本文系转载,著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。

作者:宋宝华

来源:微信公众号 linux 阅码场(id: linuxdev)

最初的 2 小时,你会爱上 Docker,对原理和使用流程有个最基本的理解,避免满世界无头苍蝇式找资料。本人反对暴风骤雨式多管齐下狂轰滥炸的学习方式,提倡迭代学习法,就是先知道怎么玩,有个感性认识,再深入学习高级用法,深层原理,一轮轮迭代。坚决反对一上来就搞几百页厚的东西把人脑子弄乱。

Docker 是什么?

KVM, Virtualbox, Vmware 是虚拟出机器,让每个实例看到一个单独的机器;而 Docker 是虚拟出操作系统,实现应用之间的隔离,让各个应用觉得自己有一个自己的操作系统,而且彼此之间隔离。假设没有 Docker,然后有进程 1 和进程 2,它们的运行将类似下图,进程 1 和进程 2 共享 kernel,它们是同一 OS 下 2 个进程,因此必须拥有不同 PID,但是又共享网卡,共享 IP 地址,看到一样的根文件系统(不 chroot 的情况下)等,可以用 Linux IPC 手段进程间通信。

有 Docker 的情况下,假设进程 1 和进程 2 运行于不同的容器,那么进程 1 和进程 2 都觉得自己和对方没有半毛钱关系,都觉得自己拥有自己的根文件系统,自己的网卡等,然后进程 1 和进程 2 的 PID 还可以一样,比如假设 2 个都是 100。但是,此 100 非彼 100。

Virtualbox 等虚拟机的思路则完全不一样,如果进程 1 和进程 2 运行于不同的虚拟机,则操作系统都是双份的,它们感觉自己在不同的虚拟电脑上面跑。

由于可见,Docker 达到了类似虚拟机的效果,但是又没有虚拟机的开销,它虚拟的层次更加高。Docker 不虚拟机器,仅仅虚拟应用的运行环境。

为什么 Docker 也可以“虚拟化”?

虚拟化,本质上一种虚幻,给你一种幻觉,让你觉得拥有的很多甚至拥有全世界,哪怕你实际是一只蝼蚁。

经过本人多年研究,虚拟化的技术分为 2 种,一种是虚拟一个世界,第二个是虚拟一个氛围。

比如我们在现实生活里面是个屌丝,但是在虚拟人生的游戏里面,我们可以是王思聪 ++,集美貌智慧财富正义于一生。虚拟人生的游戏,构建一个整个的新世界,这个世界,人人有房住,天下没有贼。那么这个就是硬件都变了,你的内核都变了。这个是 Virtualbox,KVM 这种虚拟出一个新世界的思路。

虚拟一个氛围,是 Docker 的做法。例如贵公司的 Linux 部门以前只有 3,4 个工程师,然后有一个 manager,后来有 30 个人了,你就可以分什么内核组、驱动组、应用组等更多的组,然后又多出几个 manager。这种组,类似于名称空间,在每一个单独名称空间的 manager,都觉得自己是个 manager,于是他会爽那么一点点。

最开始是这样的

后来是这样的

如果这样还不够,还可以搞声卡驱动组 manager,网卡驱动组 manager,反正可以不停地搞。大家在各自的 container 里面占山为王。

Docker 就是这样的名称空间让各自在同样的 Linux 平台上面各自暗爽,装到你自己的容器里面爽。

安装 Docker

如果是 Windows 主机,可以下载 docker-toolbox 一路安装,安装过程中如果提示什么错,可以把 360 等类似软件关闭。Windows 安装好 Docker 后,使用 Docker Quickstart Terminal 运行。

如果是 Ubuntu,可以按照 https://docs.docker.com/engin…。最简单的 Ubuntu 16.04 就是命令:sudo apt-get update&& apt-get install docker。

Ubuntu 安装 Docker 后,可以把当前用户加到 docker 用户组以便当前用户也有权限操作 docker client 和 host 之间的通信 socket(之后请重启 docker 相关服务):

sudo usermod -aG docker $USER

为了装逼需要,我们在 docker hub 网页注册一个用户名,我注册的用户名是 21cnbao。这样以后,就可以自己提交自己的 image 了。

Docker 的架构

Docker 中可能涉及到 3 个机器或者更多机器,一个运行 docker 命令的 client,一个包含 images 并以容器 (container) 形式运行 image 的主机,一个 docker 的 images 仓库。client 与 docker host 上面的 docker daemon 通信。当然 docker client 和 host 可以运行于一台机器(我们做实验的时候是一台),默认的 docker 仓库是 Docker Hub。

一般的流程中,client 发 pull 命令从仓库把 image 拉到 docker host,然后通过 run 命令指挥 image 到 host 上面弄一个 container 来跑这个 image。

当然也可以是相反的流程,client 通过 build 命令在 host 上面创建一个自己的 image,然后通过 push 命令把 image 推到仓库。之后这个 image 可以被别的人或者自己 pull。

image 到底是个什么鬼?

Docker 镜像是一个特殊的文件系统,提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。image 为特定目的而生,比如弄了个 nginx 的 image 后,这个 image 就把 nginx 的东西包罗万象了,无论是张三、王五、六麻子还是七癞子,无论它是什么电脑,什么操作系统,只要支持 docker,它把这个 nginx 的 image 下载下来后,拿 docker run 命令就可以弄容器跑 nginx 了。这样,用户就不用装 nginx 以及它依赖的一切包了(通常装一个软件弄依赖也能把你弄地烦躁死了)。这样看起来,Docker 实在是居家旅行,杀人越货之必备良器也!

镜像构建时,会一层层叠加,前一层是后一层的基础。

每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。所以这个很类似 git 里面这一次提交相对于上一次提交的 diff:

$git diff
 layout/book_index_template.html                    |    8 ++-
 text/05_Installing_Git/0_Source.markdown           |  14 ++++++
 text/05_Installing_Git/1_Linux.markdown            |  17 +++++++
 text/05_Installing_Git/2_Mac_104.markdown          |  11 +++++
 text/05_Installing_Git/3_Mac_105.markdown          |   8 ++++
 text/05_Installing_Git/4_Windows.markdown          |   7 +++
 .../1_Getting_a_Git_Repo.markdown                  |    7 +++-
 .../0_Comparing_Commits_Git_Diff.markdown        |   45 +++++++++++++++++++-
 .../0_Hosting_Git_gitweb_repoorcz_github.markdown |   4 +-
 9files changed, 115 insertions(+), 6 deletions(-)

## 一次完整的 docker 实作

说了那么多后,我们必须亲自动手玩了。下面把 pull,run,build,push 都玩一次,破除神秘感。一个典型的运行流程如下:

一、client 用 pull 命令从仓库把 image 拉到 docker host

docker pull 的格式是:

docker pull[选项] [Docker Registry 地址] < 仓库名 >:< 标签名 >

默认地址是 DockerHub。仓库名:这里的仓库名是两段式名称,既 /,“/”前面一般是用户名。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

下载 Ubuntu14.04 的 image(以 Ubuntu 为例):

baohua@ubuntu:~$docker pull ubuntu:14.04
14.04:Pulling from library/ubuntu
c60055a51d74:Downloading [>] 539.8 kB/65.69 MB
755da0cdb7d2:Download complete
969d017f67e6:Download complete
37c9a9113595:Download complete
a3d9f8479786:Download complete                                                                
…

运行 docker images 命令看看下载的 images:

$docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu            ml 14.04              b969ab9f929b        4 weeksago         188 MB

二、在 docker host 上面运行 Ubuntu 14.04 于 containers

我们现在运行 Ubuntu14.04 中的 bash shell,因为 docker 运行 image 于容器时,需要指定主进程(本例的主进程为 bash)。

在终端 1 上面运行

docker run -it --rm ubuntu:14.04 bash

在终端 2 上面运行

docker run -it --rm ubuntu:14.04 bash

这样我们就运行了 ubuntu14.04 这个 image 的 2 次实例(得到 2 个容器), Linux 下面的 ps 命令是看进程的,docker 下面就是看 image 的实例容器了。

$ docker ps
CONTAINER ID       IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
e3a913872698       ubuntu:14.04       "bash"              11seconds ago      Up 10 seconds                           wizardly_elion
db1c25753e97       ubuntu:14.04       "bash"              21seconds ago      Up 21 seconds                           adori

image 和 container 之间的关系类似程序与进程之间的关系,一个静若处子,一个动如脱兔。比如程序 QQ,运行一次就是 1 个 QQ 进程,再运行一个 QQ 就是第 2 个 QQ 进程。同样道理,一个 image 也可以运行多份 container。

三、构建自己的 image

现在想在 Ubuntu 14.04 中增加 vim 和 gcc,构建一个增量 image,因为目前的 Ubuntu image 里面没有这样的命令:

root@e3a913872698:/# vim
bash: vim: command not found

于是在 Ubuntu 14.04 这个 image 基础上面,叠加一层,然后把它提交到 docker hub 的 21cnbao 的仓库。

我们需要在客户端电脑上面创建一个 Dockerfile 文件(该文件用于描述 image),以实现在现有的 Ubuntu 14.04 上面做增量的目的。

$ mkdir myubuntu
$ cd myubuntu/
$ touch Dockerfile

用 vim 编辑 Dockerfile,添加如下内容:

# ubuntu 14.04 with vim and gcc
FROM ubuntu:14.04
MAINTAINER Barry Song<21cnbao@gmail.com>
RUN apt-get update && apt-getinstall –y vim gcc

RUN 指令的含义是在指定在源 image 内执行一条命令,本例更新 APT 缓存,并且安装 vim 和 gcc 以形成一个增量 image。

下面 build 这个 image:

$ docker build -t 21cnbao/myubuntu:14.04 .
time="2017-02-21T06:48:07+08:00"level=info msg="Unable to use system certificate pool: crypto/x509: systemroot pool is not available on Windows"
Sending build context to Docker daemon2.048 kB
Step 1/3 : FROM ubuntu:14.04
 ---> b969ab9f929b
Step 2/3 : MAINTAINER Barry Song<21cnbao@gmail.com>
 ---> Running in f1449746b58c
 ---> 5dacd7a6ee5d
Removing intermediate containerf1449746b58c
Step 3/3 : RUN apt-get update &&apt-get install vim gcc
 ---> Running in b1469caf3509
Ign http://archive.ubuntu.com trustyInRelease
Get:1 http://archive.ubuntu.comtrusty-updates InRelease [65.9 kB]
Get:2 http://archive.ubuntu.comtrusty-security InRelease [65.9 kB]
Get:3 http://archive.ubuntu.com trustyRelease.gpg [933 B]
Get:4 http://archive.ubuntu.com trustyRelease [58.5 kB]
Get:5 http://archive.ubuntu.comtrusty-updates/main Sources [485 kB]
…

下面运行 21cnbao/myubuntu 14.04 这个镜像:

docker run -it --rm 21cnbao/myubuntu:14.04 bash

发现 gcc 和 vim 都有了:

$ docker run -it --rm 21cnbao/myubuntu:14.04 bash
root@f33ee07caf43:/#gcc
gcc: fatal error: no input files
compilation terminated.
root@f33ee07caf43:/#

四、通过 docker push 把 image 提交到仓库

在 docker hub 上面创建一个仓库 myubuntu,该仓库创建后,全名将为 21cnbao/myubuntu。

下面 push 这个 image 到 docker hub,之前我们需要登录到 docker hub:

$ docker login --username=21cnbao --email=21cnbao@gmail.com
Flag--email has been deprecated, will be removed in 1.14.
Password:
Login Succeeded

下面开始 push:

$ docker push 21cnbao/myubuntu
time="2017-02-21T07:17:59+08:00"level=info msg="Unable to use system certificate pool: crypto/x509: systemroot pool is not available on Windows"
The pushrefers to a repository [docker.io/21cnbao/myubuntu]
87157b68b121:Pushing [>] 1.109 MB/134.7 MB
c9fc7024b484:Pushing [==================================================>] 3.072 kB
ca893d4b83a6:Pushing [==================================================>] 4.608 kB
153bd22a8e96:Pushing 7.168 kB
83b575865dd1:Pushing [==================================================>] 209.9 kB
918b1e79e358:Waiting
…

通过 docker hub 进哥的仓库看一眼,发现大功告成了。

2 小时结束,相信你已经爱上 Docker。相爱容易相处难,痛苦才刚刚开始。人生若只如初见,何事秋风悲画扇。等闲变却故人心,却道故人心易变。

更多精彩更新中……欢迎关注账号:linux 阅码场(id: linuxdev)

正文完
 0