Skip to main content

Command Palette

Search for a command to run...

Docker Run的背后流程

Published
3 min read

如果你想启动一个nginx容器,你可能会在命令行输入以下命令

~ docker run -d nginx

然后满怀期望等待奇迹发生,结果看到输出

f021105c2da60f1f3930070e917668c7ffcabc45e2cf64c622a2d68f216d0c2b

注意

-d, --detach Run container in background and print container ID

然后我们发现系统里面多了一个nginx容器,这个过程的背后究竟发生了什么?我们来一探究竟

docker

docker - Docker image and container command line interface

docker是镜像和命令行接口

docker本身其实是一个C/S模型的架构

image.png image.png

它主要由三部分组成

  • 一个Server服务端作为后台守护进程
  • 跟Server端通信的REST API
  • 一个Client客户端工具也就是我们上面用到的docker

run这个命令是告诉docker: 我要新创建一个容器, nginx代表这个容器的启动镜像

第一个接口请求

HEAD /_ping HTTP/1.1
Host: docker
User-Agent: Docker-Client/19.03.4 (darwin)

请求响应

HTTP/1.1 200 OK
Api-Version: 1.40
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 0
Content-Type: text/plain; charset=utf-8
Date: Fri, 08 Nov 2019 05:40:58 GMT
Docker-Experimental: false
Ostype: linux
Pragma: no-cache
Server: Do

从功能上来讲,是一个探活接口,看看服务端是否正在运行

创建镜像

服务端运行正常,接下来可以发起创建镜像的请求

POST /v1.40/containers/create HTTP/1.1
Host: docker
User-Agent: Docker-Client/19.03.4 (darwin)
Content-Length: 1514
Content-Type: application/json

{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false"
...

事实上我是使用以下dtruss命令来跟踪docker的执行进程

dtruss -saL docker run -d nginx 2> ~/Desktop/dockerrun.log

是的,没错,就是大名鼎鼎的DTrace的Mac版,(但是打印出来的POST请求内容不全,目前还不知道如何完整打印,猜测应该是参数过多,尴尬。)

HTTP/1.1 404 Not Found
Api-Version: 1.40
Content-Length: 42
Content-Type: application/json
Date: Fri, 08 Nov 2019 05:40:58 GMT
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.4 (linux)

{"message":"No such image: nginx:latest"}

从响应结果看客户端向服务器查询是否有nginx:latest的镜像存在,然而并没有

系统信息

接下来有一次系统信息的接口调用

GET /v1.40/info HTTP/1.1
Host: docker
User-Agent: Docker-Client/19.03.4 (darwin)

响应如下

HTTP/1.1 200 OK
Api-Version: 1.40
Content-Type: application/json
Date: Fri, 08 Nov 2019 05:40:58 GMT
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.4 (linux)
Transfer-Encoding: chunked

914
{"ID":"A2GJ:TQBK:V4H5:GFXT:KGB7:QRV5:GWJ7
...

这一步是获取系统信息,比如docker镜像的根目录这些,为镜像下载做准备(虽然多数情况下docker的C/S是在一台机器上,但是这种设计本身就具有比较好的扩展性,C、S两端可以分离,这跟我们本地使用MySQL的客户端服务端都是在本地一样)

镜像下载

HTTP/1.1 200 OK
Api-Version: 1.40
Content-Type: application/json
Date: Fri, 08 Nov 2019 05:41:02 GMT
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.4 (linux)
Transfer-Encoding: chunked

37
{"status":"Pulling from library/nginx","id
...

当然这之前自然少不了读取本地docker的配置文件,获取镜像仓库地址(默认为:https://index.docker.io/v1/),然后开始下载,直到下载完成 再次发起创建容器请求,比较奇怪的是只拿到响应信息,尴尬了

再次创建容器

POST /v1.40/containers/create HTTP/1.1
Host: docker
User-Agent: Docker-Client/19.03.4 (darwin)
Content-Length: 1514
Content-Type: application/json

{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false
...

镜像已存在

HTTP/1.1 201 Created
Api-Version: 1.40
Content-Length: 88
Content-Type: application/json
Date: Fri, 08 Nov 2019 05:41:03 GMT
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.4 (linux)

容器同名ID检查

接下来这一步比较奇怪

POST /v1.40/containers/f021105c2da60f1f3930070e917668c7ffcabc45e2cf64c622a2d68f216d0c2b/wait?condition=next-exit HTTP/1.1
Host: docker
User-Agent: Docker-Client/19.03.4 (darwin)
Content-Length: 0
Content-Type: text/plain

这个接口的功能是等待idf021105c2da60f1f3930070e917668c7ffcabc45e2cf64c622a2d68f216d0c2b的容器退出 这一步应该是为了避免重复创建同名的容器 容器的ID生成代码GenerateRandomID的实现如下,是一段64位的随机字符串,有可能会重复?

func GenerateRandomID() string {
    b := make([]byte, 32)
    for {
        if _, err := rand.Read(b); err != nil {
            panic(err) // This shouldn't happen
        }
        id := hex.EncodeToString(b)
        // if we try to parse the truncated for as an int and we don't have
        // an error then the value is all numeric and causes issues when
        // used as a hostname. ref #3869
        if _, err := strconv.ParseInt(TruncateID(id), 10, 64); err == nil {
            continue
        }
        return id
    }
}

因为没有同名的容器,所以返回正常

HTTP/1.1 200 OK
Api-Version: 1.40
Content-Type: application/json
Date: Fri, 08 Nov 2019 05:41:03 GMT
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.4 (linux)
Transfer-Encoding: chunked

启动容器

此时可以启动容器了

POST /v1.40/containers/f021105c2da60f1f3930070e917668c7ffcabc45e2cf64c622a2d68f216d0c2b/start HTTP/1.1
Host: docker
User-Agent: Docker-Client/19.03.4 (darwin)
Content-Length: 0
Content-Type: text/plain

返回启动成功的响应

HTTP/1.1 204 No Content
Api-Version: 1.40
Date: Fri, 08 Nov 2019 05:41:04 GMT
Docker-Experimental: false
Ostype: linux
Server: Docker/19.03.4 (linux)

至此,容器启动完成

总结

以下是我整理的接口调用流程

image.png

可以看到,整个流程是非常简洁清晰而且严谨的,尤其是REST API的接口设计,非常规范,实在是很有借鉴意义,另外,第一次使用dtruss,真的是神器。

Refer

25 views

More from this blog

2025: 祛魅 灰度 念头通达

今天是2025年的最后一天,当大家都在准备下班的时候,好巧不巧的,我刚好发现了一个不大不小的问题,大胆猜想,小心求证,向上反馈,暴露风险,作为2025年工作注解,实在是再有趣不过了。 今年的工作,从结果上看,还算平稳,至于过程,有太多不可言说的部分。厂里打镙丝的牛马,有工资可拿,理应知足了,至于其它的,与己无关,也没那么重要了。 祛魅 近距离观察大厂,才发现一些违背常识/直觉的事实:路人以为的高大

Feb 28, 20261 min read21

大厂祛魅:破碎的专注力

毁掉一个人最直接的方法,就是毁掉ta的专注力。 这句话的出处已然模糊,但放在大厂环境中,却显得格外深刻。 围城 大厂宛如一座围城。城外的人满怀憧憬,目之所及皆是光鲜;城内的人却如困笼之鸟,翅膀日渐退化,每日挣扎求生。 高大上 不可否认,大厂的硬件设施确实令人艳羡:宽敞的独立园区内,来往穿梭的人群中,几乎人人手握智能设备。这看似现代化的景象背后,却藏着一个无奈的事实:在工作时段,每台电脑都被严密监控,连听音乐都成奢望。于是,工作之余玩手机,成了许多人难得的解压方式。 大厂的品牌效应确实强大。外界对...

Jul 29, 20251 min read138

Black Swan

黑天鹅理论 是指极不可能发生,实际上却又发生的事件 来到大厂打工已经满一个月了,从一开始的手足无措,到逐渐度过不适期,也算是适应了吧。 不适应 刚入职时,不适应的地方还是挺多的。 第一次只使用台式机工作,这就限制了我一天中的绝大部分时间,都必须呆在自己的工位上,好在工位足够大。只是人与人的沟通少了很多,有问题只能在工位上通过 IM 呼对方,有种魔幻又现实的感觉 第一次只能用 Windows,也不能 WSL,这给我的工作效率带来了很大影响,不能用熟悉的软件,就连写代码用的 VSCode 的...

Jan 24, 20251 min read74

2024年: 逐渐平静

这个世界是一面镜子,会把你的感受反射给你 2024 开端: 相由心生 那时,还带着一着愤懑,因为拿到了低绩效,虽然内心知道这是公司经营困难,想让我离开的一种策略,但仍然感受到自己那可笑的自尊受到了践踏。自那之后,非必要不加班,只做份内事,尽可能地不去涉及份外之事。 2024 年中: 与人为善 组里的项目眼见不行了,我被迫去支援 AI 项目,久违地写起了 python,项目接近完成时,意外收到通知:我拿到大礼包了。在这之前,架构师因故裸辞。在我离开之后不到两周,我的 TL 也裸辞了,直到同事告诉...

Jan 9, 20251 min read92

企业软件之殇

殇 动词 未成年而死。 名词 战死者。 笔者经历了两家打着云原生旗号的企业软件/解决方案公司,都是中途加入,项目都以解(失)散(败)告终。 云原生解决方案 NB 公司:一个传统的 IDC 小厂,想着借云原生的热度,进军企业软件市场。 在加入这个项目之前,笔者考取了 CKAD 认证,彼时对 K8s 相当着迷。先简要介绍一下这个项目背景: 基于 Rancher (换皮肤)的二次开发项目,名字叫:HCaaS ,在笔者加入这个团队之前,项目已经开发近两年了,除了 TL 之外,其它人之前都...

Jul 1, 20241 min read103

just for fun

57 posts

I'm a Software Engineer