pos 启动过程 要求 第一次 cgroups head 单体 ...
下面的内容是对 docker 的简单操作,包括启动 docker,下载 image,运行 image,查看容器的详细信息、在容器中安装新程序,保持刚刚修改的容器,发布自己的镜像到 docke Hub 上。所有操作步骤是一步一步进行的,能够让初学者直观地感受一下 docker 的作用。
说明:
1、在看本博客之前,请先确认您已经安装好了 docker。本人的 docker 运行在 win 上面。
2、为了提高写博客的效率,本文统一复制 CMD 中的内容,替代截图。效果是一样的。
- Status: Downloaded newer image for hello-world:latest
- Hello from Docker!
- This message shows that your installation appears to be working correctly.
- To generate this message, Docker took the following steps:
- 1. The Docker client contacted the Docker daemon.
- 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
- 3. The Docker daemon created a new container from that image which runs the
- executable that produces the output you are currently reading.
- 4. The Docker daemon streamed that output to the Docker client, which sent it
- to your terminal.
- [email protected]/* */ MINGW64 ~
- $ docker run hello-world
- Unable to find image 'hello-world:latest' locally
- latest: Pulling from library/hello-world
- 78445dd45222: Pull complete
- Digest: sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
- Status: Downloaded newer image for hello-world:latest
- Hello from Docker!
- This message shows that your installation appears to be working correctly.
- To generate this message, Docker took the following steps:
- 1. The Docker client contacted the Docker daemon.
- 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
- 3. The Docker daemon created a new container from that image which runs the
- executable that produces the output you are currently reading.
- 4. The Docker daemon streamed that output to the Docker client, which sent it
- to your terminal.
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $ docker run -it ubuntu bash
- Unable to find image 'ubuntu:latest' locally
- latest: Pulling from library/ubuntu
- 8aec416115fd: Pull complete
- 695f074e24e3: Pull complete
- 946d6c48c2a7: Pull complete
- bc7277e579f0: Pull complete
- 2508cbcde94b: Pull complete
- Digest: sha256:71cd81252a3563a03ad8daee81047b62ab5d892ebbfbf71cf53415f29c130950
- Status: Downloaded newer image for ubuntu:latest
- //这里已经进入ubuntu操作系统中了
- root@8532da118b07:/# ls
- bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
- root@8532da118b07:/# whoami
- root
- root@8532da118b07:/# uname -a
- Linux 8532da118b07 4.4.43-boot2docker #1 SMP Wed Jan 18 18:33:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
- root@8532da118b07:/# exit
- exit
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $
- [email protected]/* */ MINGW64 ~
- $ docker run ubuntu apt-get update
- Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB]
- Get:2 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]
- Get:3 http://archive.ubuntu.com/ubuntu xenial-security InRelease [102 kB]
- Get:4 http://archive.ubuntu.com/ubuntu xenial/main Sources [1103 kB]
- Get:5 http://archive.ubuntu.com/ubuntu xenial/restricted Sources [5179 B]
- Get:6 http://archive.ubuntu.com/ubuntu xenial/universe Sources [9802 kB]
- Get:7 http://archive.ubuntu.com/ubuntu xenial/main amd64 Packages [1558 kB]
- Get:8 http://archive.ubuntu.com/ubuntu xenial/restricted amd64 Packages [14.1 kB]
- Get:9 http://archive.ubuntu.com/ubuntu xenial/universe amd64 Packages [9827 kB]
- Get:10 http://archive.ubuntu.com/ubuntu xenial-updates/main Sources [276 kB]
- Get:11 http://archive.ubuntu.com/ubuntu xenial-updates/restricted Sources [1866 B]
- Get:12 http://archive.ubuntu.com/ubuntu xenial-updates/universe Sources [150 kB]
- Get:13 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 Packages [585 kB]
- Get:14 http://archive.ubuntu.com/ubuntu xenial-updates/restricted amd64 Packages [11.7 kB]
- Get:15 http://archive.ubuntu.com/ubuntu xenial-updates/universe amd64 Packages [486 kB]
- Get:16 http://archive.ubuntu.com/ubuntu xenial-security/main Sources [66.9 kB]
- Get:17 http://archive.ubuntu.com/ubuntu xenial-security/restricted Sources [1866 B]
- Get:18 http://archive.ubuntu.com/ubuntu xenial-security/universe Sources [20.5 kB]
- Get:19 http://archive.ubuntu.com/ubuntu xenial-security/main amd64 Packages [252 kB]
- Get:20 http://archive.ubuntu.com/ubuntu xenial-security/restricted amd64 Packages [11.7 kB]
- Get:21 http://archive.ubuntu.com/ubuntu xenial-security/universe amd64 Packages [87.2 kB]
- Fetched 24.7 MB in 5min 58s (68.9 kB/s)
- Reading package lists...
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $ docker ps -l
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 50ecefedccba ubuntu "apt-get update" 21 minutes ago Exited (0) 14 minutes ago priceless_boyd
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $ docker commit 50e learn/update
- sha256:d3905d6682b23c0fbe79af0257f92f48d219bca8ce1a8405d1f35ac0fa1b1b5a
- [email protected]/* */ MINGW64 ~
- $ docker run learn/update apt-get install -y inetutils-ping
- Reading package lists...
- Building dependency tree...
- Reading state information...
- The following additional packages will be installed:
- 、、、
- Setting up isc-dhcp-client (4.3.3-5ubuntu12.6) ...
- Setting up isc-dhcp-common (4.3.3-5ubuntu12.6) ...
- Setting up libxtables11:amd64 (1.6.0-2ubuntu3) ...
- Setting up netbase (5.3) ...
- Setting up inetutils-ping (2:1.9.4-1build1) ...
- Processing triggers for libc-bin (2.23-0ubuntu5) ...
- Processing triggers for systemd (229-4ubuntu13) ...
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $ docker ps -l
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 53e26efb86af learn/update "apt-get install -y i" About a minute ago Exited (0) 39 seconds ago laughing_wiles
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $ docker commit 53e26efb86af ubuntu/ping
- sha256:3aff8e300c6dca187ea2c6192acc0b85b73d59cc2ba569e40a912570939855ee
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $ docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- ubuntu/ping latest 3aff8e300c6d 33 seconds ago 174.4 MB
- learn/update latest d3905d6682b2 6 minutes ago 169.1 MB
- ubuntu latest f49eec89601e 4 days ago 129.5 MB
- [email protected]/* */ MINGW64 ~
- $ docker run ubuntu/ping ping baidu.com
- PING baidu.com (111.13.100.91): 56 data bytes
- 64 bytes from 111.13.100.91: icmp_seq=0 ttl=50 time=57.687 ms
- 64 bytes from 111.13.100.91: icmp_seq=1 ttl=49 time=54.970 ms
- 64 bytes from 111.13.100.91: icmp_seq=2 ttl=49 time=58.235 ms
- 64 bytes from 111.13.100.91: icmp_seq=3 ttl=49 time=59.382 ms
- [email protected]/* */ MINGW64 ~
- $
通过上面这个过程,我们发现总共有三个镜像文件,分别是最初的 ubuntu、learn/update 和 ubuntu/ping。这体现了 docker 所采用的 copy on write 的思想。
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $ docker ps
- CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 1312ac6459c0 ubuntu/ping "ping baidu.com" 16 minutes ago Up 16 minutes happy_almeida
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $ docker inspect 1312
- [
- {
- "Id": "1312ac6459c0b93907e3e2a72c59be22a3be89b53cd097226355bd81b56a932d",
- "Created": "2017-01-25T15:07:20.801240028Z",
- "Path": "ping",
- "Args": [
- "baidu.com"
- ],
准备工作:注册一个 docker 账号。这里我的用户名是 liangyhgood。
- [email protected]/* */ MINGW64 ~
- $ docker login
- Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
- Username (liangyhgood): liangyhgood
- Password:
- Login Succeeded
- [email protected]/* */-GE1EJH4 MINGW64 ~
- $ docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- hello-world latest 48b5124b2768 12 days ago 1.84 kB
- [email protected]/* */-GE1EJH4 MINGW64 ~
- $ docker tag 48b5124b2768 learn/helloworld:latest
- [email protected]/* */-GE1EJH4 MINGW64 ~
- $ docker push learn/helloworld
- The push refers to a repository [docker.io/learn/helloworld]
- 98c944e98de8: Preparing
- denied: requested access to the resource is denied
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $ docker tag 48b5124b2768 liangyhgood/helloworld:latest
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $ docker push liangyhgood/helloworld
- The push refers to a repository [docker.io/liangyhgood/helloworld]
- 98c944e98de8: Pushed
- latest: digest: sha256:2075ac87b043415d35bb6351b4a59df19b8ad154e578f7048335feeb02d0f759 size: 524
- liangyh@DESKTOP-GE1EJH4 MINGW64 ~
- $
停止所有的 Container
docker stop $(docker ps -a -q)
删除所有 container
docker rm $(docker ps -a -q)
删除全部 image
docker rmi $(docker images -q)
docker 容器重新启动之后沿用 docker run 命令时制定的参数来运行
docker attach containerName
使用一个数组来指定要运行的命令和传递给该命令的每个参数。
RUN ["apt-get", "install", "-y", "nginx"]
学习 Docker 的源码并不是一个枯燥的过程,反而可以从中理解 Docker 架构的设计原理。Docker 对使用者来讲是一个 C/S 模式的架构,而 Docker 的后端是一个非常松耦合的架构,模块各司其职,并有机组合,支撑 Docker 的运行。
在此,先附上 Docker 总架构,如图 3.1。
图 3.1 Docker 总架构图
如图 3.1,不难看出,用户是使用 Docker Client 与 Docker Daemon 建立通信,并发送请求给后者。
而 Docker Daemon 作为 Docker 架构中的主体部分,首先提供 Server 的功能使其可以接受 Docker Client 的请求;而后 Engine 执行 Docker 内部的一系列工作,每一项工作都是以一个 Job 的形式的存在。
Job 的运行过程中,当需要容器镜像时,则从 Docker Registry 中下载镜像,并通过镜像管理驱动 graphdriver 将下载镜像以 Graph 的形式存储;当需要为 Docker 创建网络环境时,通过网络管理驱动 networkdriver 创建并配置 Docker 容器网络环境;当需要限制 Docker 容器运行资源或执行用户指令等操作时,则通过 execdriver 来完成。
而 libcontainer 是一项独立的容器管理包,networkdriver 以及 execdriver 都是通过 libcontainer 来实现具体对容器进行的操作。
当执行完运行容器的命令后,一个实际的 Docker 容器就处于运行状态,该容器拥有独立的文件系统,独立并且安全的运行环境等。
接下来,我们将从 Docker 总架构图入手,抽离出架构内各个模块,并对各个模块进行更为细化的架构分析与功能阐述。主要的模块有:Docker Client、Docker Daemon、Docker Registry、Graph、Driver、libcontainer 以及 Docker container。
Docker Client 是 Docker 架构中用户用来和 Docker Daemon 建立通信的客户端。用户使用的可执行文件为 docker,通过 docker 命令行工具可以发起众多管理 container 的请求。
Docker Client 可以通过以下三种方式和 Docker Daemon 建立通信:tcp://host:port,unix://path_to_socket 和 fd://socketfd。为了简单起见,本文一律使用第一种方式作为讲述两者通信的原型。与此同时,与 Docker Daemon 建立连接并传输请求的时候,Docker Client 可以通过设置命令行 flag 参数的形式设置安全传输层协议 (TLS) 的有关参数,保证传输的安全性。
Docker Client 发送容器管理请求后,由 Docker Daemon 接受并处理请求,当 Docker Client 接收到返回的请求相应并简单处理后,Docker Client 一次完整的生命周期就结束了。当需要继续发送容器管理请求时,用户必须再次通过 docker 可执行文件创建 Docker Client。
Docker Daemon 是 Docker 架构中一个常驻在后台的系统进程,功能是:接受并处理 Docker Client 发送的请求。该守护进程在后台启动了一个 Server,Server 负责接受 Docker Client 发送的请求;接受请求后,Server 通过路由与分发调度,找到相应的 Handler 来执行请求。
Docker Daemon 启动所使用的可执行文件也为 docker,与 Docker Client 启动所使用的可执行文件 docker 相同。在 docker 命令执行时,通过传入的参数来判别 Docker Daemon 与 Docker Client。
Docker Daemon 的架构,大致可以分为以下三部分:Docker Server、Engine 和 Job。Daemon 架构如图 4.1。
图 4.1 Docker Daemon 架构示意图
Docker Server 在 Docker 架构中是专门服务于 Docker Client 的 server。该 server 的功能是:接受并调度分发 Docker Client 发送的请求。Docker Server 的架构如图 4.2。
图 4.2 Docker Server 架构示意图
在 Docker 的启动过程中,通过包 gorilla/mux,创建了一个 mux.Router,提供请求的路由功能。在 Golang 中,gorilla/mux 是一个强大的 URL 路由器以及调度分发器。该 mux.Router 中添加了众多的路由项,每一个路由项由 HTTP 请求方法(PUT、POST、GET 或 DELETE)、URL、Handler 三部分组成。
若 Docker Client 通过 HTTP 的形式访问 Docker Daemon,创建完 mux.Router 之后,Docker 将 Server 的监听地址以及 mux.Router 作为参数,创建一个 httpSrv=http.Server{},最终执行 httpSrv.Serve() 为请求服务。
在 Server 的服务过程中,Server 在 listener 上接受 Docker Client 的访问请求,并创建一个全新的 goroutine 来服务该请求。在 goroutine 中,首先读取请求内容,然后做解析工作,接着找到相应的路由项,随后调用相应的 Handler 来处理该请求,最后 Handler 处理完请求之后回复该请求。
需要注意的是:Docker Server 的运行在 Docker 的启动过程中,是靠一个名为 "serveapi" 的 job 的运行来完成的。原则上,Docker Server 的运行是众多 job 中的一个,但是为了强调 Docker Server 的重要性以及为后续 job 服务的重要特性,将该 "serveapi" 的 job 单独抽离出来分析,理解为 Docker Server。
Engine 是 Docker 架构中的运行引擎,同时也 Docker 运行的核心模块。它扮演 Docker container 存储仓库的角色,并且通过执行 job 的方式来操纵管理这些容器。
在 Engine 数据结构的设计与实现过程中,有一个 handler 对象。该 handler 对象存储的都是关于众多特定 job 的 handler 处理访问。举例说明,Engine 的 handler 对象中有一项为:{"create": daemon.ContainerCreate,},则说明当名为 "create" 的 job 在运行时,执行的是 daemon.ContainerCreate 的 handler。
一个 Job 可以认为是 Docker 架构中 Engine 内部最基本的工作执行单元。Docker 可以做的每一项工作,都可以抽象为一个 job。例如:在容器内部运行一个进程,这是一个 job;创建一个新的容器,这是一个 job,从 Internet 上下载一个文档,这是一个 job;包括之前在 Docker Server 部分说过的,创建 Server 服务于 HTTP 的 API,这也是一个 job,等等。
Job 的设计者,把 Job 设计得与 Unix 进程相仿。比如说:Job 有一个名称,有参数,有环境变量,有标准的输入输出,有错误处理,有返回状态等。
Docker Registry 是一个存储容器镜像的仓库。而容器镜像是在容器被创建时,被加载用来初始化容器的文件架构与目录。
在 Docker 的运行过程中,Docker Daemon 会与 Docker Registry 通信,并实现搜索镜像、下载镜像、上传镜像三个功能,这三个功能对应的 job 名称分别为 "search","pull" 与 "push"。
其中,在 Docker 架构中,Docker 可以使用公有的 Docker Registry,即大家熟知的 Docker Hub,如此一来,Docker 获取容器镜像文件时,必须通过互联网访问 Docker Hub;同时 Docker 也允许用户构建本地私有的 Docker Registry,这样可以保证容器镜像的获取在内网完成。
Graph 在 Docker 架构中扮演已下载容器镜像的保管者,以及已下载容器镜像之间关系的记录者。一方面,Graph 存储着本地具有版本信息的文件系统镜像,另一方面也通过 GraphDB 记录着所有文件系统镜像彼此之间的关系。Graph 的架构如图 4.3。
图 4.3 Graph 架构示意图
其中,GraphDB 是一个构建在 SQLite 之上的小型图数据库,实现了节点的命名以及节点之间关联关系的记录。它仅仅实现了大多数图数据库所拥有的一个小的子集,但是提供了简单的接口表示节点之间的关系。
同时在 Graph 的本地目录中,关于每一个的容器镜像,具体存储的信息有:该容器镜像的元数据,容器镜像的大小信息,以及该容器镜像所代表的具体 rootfs。
Driver 是 Docker 架构中的驱动模块。通过 Driver 驱动,Docker 可以实现对 Docker 容器执行环境的定制。由于 Docker 运行的生命周期中,并非用户所有的操作都是针对 Docker 容器的管理,另外还有关于 Docker 运行信息的获取,Graph 的存储与记录等。因此,为了将 Docker 容器的管理从 Docker Daemon 内部业务逻辑中区分开来,设计了 Driver 层驱动来接管所有这部分请求。
在 Docker Driver 的实现中,可以分为以下三类驱动:graphdriver、networkdriver 和 execdriver。
graphdriver 主要用于完成容器镜像的管理,包括存储与获取。即当用户需要下载指定的容器镜像时,graphdriver 将容器镜像存储在本地的指定目录;同时当用户需要使用指定的容器镜像来创建容器的 rootfs 时,graphdriver 从本地镜像存储目录中获取指定的容器镜像。
在 graphdriver 的初始化过程之前,有 4 种文件系统或类文件系统在其内部注册,它们分别是 aufs、btrfs、vfs 和 devmapper。而 Docker 在初始化之时,通过获取系统环境变量 "DOCKER_DRIVER" 来提取所使用 driver 的指定类型。而之后所有的 graph 操作,都使用该 driver 来执行。
graphdriver 的架构如图 4.4:
图 4.4 graphdriver 架构示意图
networkdriver 的用途是完成 Docker 容器网络环境的配置,其中包括 Docker 启动时为 Docker 环境创建网桥;Docker 容器创建时为其创建专属虚拟网卡设备;以及为 Docker 容器分配 IP、端口并与宿主机做端口映射,设置容器防火墙策略等。networkdriver 的架构如图 4.5:
图 4. 5 networkdriver 架构示意图
execdriver 作为 Docker 容器的执行驱动,负责创建容器运行命名空间,负责容器资源使用的统计与限制,负责容器内部进程的真正运行等。在 execdriver 的实现过程中,原先可以使用 LXC 驱动调用 LXC 的接口,来操纵容器的配置以及生命周期,而现在 execdriver 默认使用 native 驱动,不依赖于 LXC。具体体现在 Daemon 启动过程中加载的 ExecDriverflag 参数,该参数在配置文件已经被设为 "native"。这可以认为是 Docker 在 1.2 版本上一个很大的改变,或者说 Docker 实现跨平台的一个先兆。execdriver 架构如图 4.6:
图 4.6 execdriver 架构示意图
libcontainer 是 Docker 架构中一个使用 Go 语言设计实现的库,设计初衷是希望该库可以不依靠任何依赖,直接访问内核中与容器相关的 API。
正是由于 libcontainer 的存在,Docker 可以直接调用 libcontainer,而最终操纵容器的 namespace、cgroups、apparmor、网络设备以及防火墙规则等。这一系列操作的完成都不需要依赖 LXC 或者其他包。libcontainer 架构如图 4.7:
图 4.7 libcontainer 示意图
另外,libcontainer 提供了一整套标准的接口来满足上层对容器管理的需求。或者说,libcontainer 屏蔽了 Docker 上层对容器的直接管理。又由于 libcontainer 使用 go 这种跨平台的语言开发实现,且本身又可以被上层多种不同的编程语言访问,因此很难说,未来的 Docker 就一定会紧紧地和 Linux 捆绑在一起。而于此同时,Microsoft 在其著名云计算平台 Azure 中,也添加了对 Docker 的支持,可见 Docker 的开放程度与业界的火热度。
暂不谈 Docker,由于 libcontainer 的功能以及其本身与系统的松耦合特性,很有可能会在其他以容器为原型的平台出现,同时也很有可能催生出云计算领域全新的项目。
Docker container(Docker 容器)是 Docker 架构中服务交付的最终体现形式。
Docker 按照用户的需求与指令,订制相应的 Docker 容器:
Docker 容器示意图如图 4.8:
图 4.8 Docker 容器示意图
上一章节着重于 Docker 架构中各个部分的介绍。本章的内容,将以串联 Docker 各模块来简要分析,分析原型为 Docker 中的 docker pull 与 docker run 两个命令。
docker pull 命令的作用为:从 Docker Registry 中下载指定的容器镜像,并存储在本地的 Graph 中,以备后续创建 Docker 容器时的使用。docker pull 命令执行流程如图 5.1。
图 5.1 docker pull 命令执行流程示意图
如图,图中标记的红色箭头表示 docker pull 命令在发起后,Docker 所做的一系列运行。以下逐一分析这些步骤。
(1) Docker Client 接受 docker pull 命令,解析完请求以及收集完请求参数之后,发送一个 HTTP 请求给 Docker Server,HTTP 请求方法为 POST,请求 URL 为 "/images/create?"+"xxx";
(2) Docker Server 接受以上 HTTP 请求,并交给 mux.Router,mux.Router 通过 URL 以及请求方法来确定执行该请求的具体 handler;
(3) mux.Router 将请求路由分发至相应的 handler,具体为 PostImagesCreate;
(4) 在 PostImageCreate 这个 handler 之中,一个名为 "pull" 的 job 被创建,并开始执行;
(5) 名为 "pull" 的 job 在执行过程中,执行 pullRepository 操作,即从 Docker Registry 中下载相应的一个或者多个 image;
(6) 名为 "pull" 的 job 将下载的 image 交给 graphdriver;
(7) graphdriver 负责将 image 进行存储,一方创建 graph 对象,另一方面在 GraphDB 中记录 image 之间的关系。
docker run 命令的作用是在一个全新的 Docker 容器内部运行一条指令。Docker 在执行这条命令的时候,所做工作可以分为两部分:第一,创建 Docker 容器所需的 rootfs;第二,创建容器的网络等运行环境,并真正运行用户指令。因此,在整个执行流程中,Docker Client 给 Docker Server 发送了两次 HTTP 请求,第二次请求的发起取决于第一次请求的返回状态。Docker run 命令执行流程如图 5.2。
图 5.2 docker run 命令执行流程示意图
如图,图中标记的红色箭头表示 docker run 命令在发起后,Docker 所做的一系列运行。以下逐一分析这些步骤。
(1) Docker Client 接受 docker run 命令,解析完请求以及收集完请求参数之后,发送一个 HTTP 请求给 Docker Server,HTTP 请求方法为 POST,请求 URL 为 "/containers/create?"+"xxx";
(2) Docker Server 接受以上 HTTP 请求,并交给 mux.Router,mux.Router 通过 URL 以及请求方法来确定执行该请求的具体 handler;
(3) mux.Router 将请求路由分发至相应的 handler,具体为 PostContainersCreate;
(4) 在 PostImageCreate 这个 handler 之中,一个名为 "create" 的 job 被创建,并开始让该 job 运行;
(5) 名为 "create" 的 job 在运行过程中,执行 Container.Create 操作,该操作需要获取容器镜像来为 Docker 容器创建 rootfs,即调用 graphdriver;
(6) graphdriver 从 Graph 中获取创建 Docker 容器 rootfs 所需要的所有的镜像;
(7) graphdriver 将 rootfs 所有镜像,加载安装至 Docker 容器指定的文件目录下;
(8) 若以上操作全部正常执行,没有返回错误或异常,则 Docker Client 收到 Docker Server 返回状态之后,发起第二次 HTTP 请求。请求方法为 "POST",请求 URL 为 "/containers/"+container_ID+"/start";
(9) Docker Server 接受以上 HTTP 请求,并交给 mux.Router,mux.Router 通过 URL 以及请求方法来确定执行该请求的具体 handler;
(10)mux.Router 将请求路由分发至相应的 handler,具体为 PostContainersStart;
(11) 在 PostContainersStart 这个 handler 之中,名为 "start" 的 job 被创建,并开始执行;
(12) 名为 "start" 的 job 执行完初步的配置工作后,开始配置与创建网络环境,调用 networkdriver;
(13)networkdriver 需要为指定的 Docker 容器创建网络接口设备,并为其分配 IP,port,以及设置防火墙规则,相应的操作转交至 libcontainer 中的 netlink 包来完成;
(14)netlink 完成 Docker 容器的网络环境配置与创建;
(15) 返回至名为 "start" 的 job,执行完一些辅助性操作后,job 开始执行用户指令,调用 execdriver;
(16)execdriver 被调用,初始化 Docker 容器内部的运行环境,如命名空间,资源控制与隔离,以及用户命令的执行,相应的操作转交至 libcontainer 来完成;
(17)libcontainer 被调用,完成 Docker 容器内部的运行环境初始化,并最终执行用户要求启动的命令。
上面 docker 架构内容来自:http://www.infoq.com/cn/articles/docker-source-code-analysis-part1/
docker 基本学习
来源: http://www.bubuko.com/infodetail-2273078.html