Docker编译流程分析

395 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情

若看到相同文章,为本人其他平台

Docker编译流程分析

Docker整体编译打包教程

环境搭建

docker的编译,需要在宿主机预先安装docker软件。因为编译docker的源码时,会构建一个docker镜像并运行,在这个容器里面进行build操作。由于这个容器已经包含了go语言环境,故宿主机无须额外安装golang。 宿主机系统:uos 宿主机docker版本:Docker version 19.03.8, build 1b4342cd4c

下载编译源码

docker的github官方网站为:github.com/docker/dock… docker以每月发布一个版本的节奏进行开发。命名规则为:年份-月份-ce,其中ce表示社区版本。截至本文撰写时,最新版本为v17.12.0-ce,但下一版本v18.01.0-ce-dev已经处于开发阶段(带dev表示开发阶段),本文编译得到的版本即为v18.01.0-ce-dev。 发行版本下载地址:github.com/docker/dock… 本文在/home/latelee/docker/dev目录进行,请根据实际情况修改目录。 下载源码:

git clone https://github.com/docker/docker-ce
##或者
git clone https://gitee.com/ruog/docker-ce.git

进入docker-ce目录:

cd docker-ce

切换到最新的tag:

git checkout -b v18.01.0-ce

最后编译通过用的该命令:

在/home/hao/docker_work/docker-ce文件夹下执行该命令:

make  VERSION=18.01.0-ce-dev ENGINE_DIR=/home/hao/docker_work/docker-ce/components/engine CLI_DIR=/home/hao/docker_work/docker-ce/components/cli deb

make  VERSION=18.01.0-ce-dev ENGINE_DIR=/root/docker-ce/components/engine CLI_DIR=/root/docker-ce/components/cli deb

如果编译不通过,试试make clean.

命令解释: 该命令指定了版本号和docker组件的目录(VERSION、ENGINE、CLI分别指版本号、docker引擎、docker命令行),同时指定了要编译的系统版本(deb指编译所有debian平台包,ubuntu16.04代号为xenial).

大约经过半小时(github上下载速度为3m/s的情况下),编译成功。最终生成的deb包位于:components\packaging\deb\debbuild\ubuntu-xenial

和其他各deb下的版本文件夹中.

若因为github下载速度太慢导致不能编译通过时

修改下列文件,将文件中的github代码替换成gitee代码库:

./components/packaging/plugins/app.installer
./components/packaging/plugins/buildx.installer
./components/engine/hack/dockerfile/install/proxy.installer
./components/engine/hack/dockerfile/install/runc.installer
./components/engine/hack/dockerfile/install/tini.installer
./components/engine/hack/dockerfile/install/gotestsum.installer
./components/engine/hack/dockerfile/install/tomlv.installer
./components/engine/hack/dockerfile/install/golangci_lint.installer
./components/engine/hack/dockerfile/install/rootlesskit.installer
./components/engine/hack/dockerfile/install/dockercli.installer
./components/engine/hack/dockerfile/install/containerd.installer
./components/engine/hack/dockerfile/install/vndr.installer
./components/engine/hack/dockerfile/install/shfmt.installer

以./components/packaging/plugins/app.installer 为例, 修改为如下图所示代码库:

48.jpg

Docker-cli编译教程

下载docker-ce代码:

git clone https://github.com/docker/docker-ce
##或者
git clone https://gitee.com/ruog/docker-ce.git

进入docker-ce/components/cli/目录下执行下面命令,编译docker-cli的二进制文件.

make -f docker.Makefile binary

编译好的二进制文件在

docker-ce/components/cli/build/docker-linux-amd64

将docker-linux-amd64替换已经安装在/usr/bin/docker 再次运行docker就为新编译的docker程序.

可以使用docker version查看docker版本.

Docker-ce编译流程分析

从主目录Makefile分析得, 编译deb包,会跳转到/components/packaging/下执行make deb

PACKAGING_DIR:=$(CURDIR)/components/packaging
.PHONY: deb
deb: #### build deb packages
    $(MAKE) VERSION=$(VERSION) CLI_DIR=$(CLI_DIR) ENGINE_DIR=$(ENGINE_DIR) -C $(PACKAGING_DIR) deb

进入到components/packaging/下,查看Makefile, 发现检测cli和engine代码,同步分支.

创建src/github.com/docker/ 文件夹, 将components/cli拷贝到components/packaging/src/github.com/docker/下, 将components/engine/拷贝到components/packaging/src/github.com/docker/下,并改名成docker

49.png

然后进入到components/packaging/deb/下执行make deb

将components/packaging/src/github.com/docker/cli和engine打包成cli.tar.gz和engine.tar.gz放在components/packaging/deb/sources/下.

修改Dockerfile中github.com网站地址到gitee时,需要删除src/github.com/docker/文件夹下的docker. 和packaging/deb/sources/engine.tgz后,重新生成.

##编译脚本流程梳理:
components/packaging/deb/
    Makefile    
        运行ubuntu-xenial/Dockerfile  构建docker给环境.
        运行docker run 启动镜像并挂载组件代码.
        运行同目录下 build-deb脚本.

        components/packaging/deb/common/rules:  override_dh_auto_build: 
            ./hack/make.sh dynbinary
            ack/dockerfile/install/install.sh tini
            hack/dockerfile/install/install.sh proxy dynamic
            hack/dockerfile/install/install.sh rootlesskit dynamic
            运行engine下 ./hack/make.sh dynbinary
                运行engine/hack/install.sh 下的所有*.installer文件,安装组件.
        编译二进制并打包

修改记录

1.修改docker-ce/components/packaging/deb/Makefile文件, 将在创建docker时加入挂载本地组件代码:

##该地址需要修改成自己代码放置的绝对地址.
UOS_base=/home/hao/docker_work/docker-ce/components/

UOS_tini=$(UOS_base)tini
UOS_containerd=$(UOS_base)containerd
UOS_app=$(UOS_base)app
UOS_buildx=$(UOS_base)buildx
UOS_libnetwork=$(UOS_base)libnetwork
UOS_rootlesskit=$(UOS_base)rootlesskit
UOS_tine=$(UOS_base)tini
UOS_runc=$(UOS_base)runc
UOS_sh=$(UOS_base)sh
UOS_toml=$(UOS_base)toml
UOS_vndr=$(UOS_base)vndr

## Additional flags may be necessary at some point
RUN_FLAGS=
RUN?=docker run --rm \
    -e PLATFORM \
    -e EPOCH='$(EPOCH)' \
    -e DEB_VERSION=$(word 1, $(GEN_DEB_VER)) \
    -e VERSION=$(word 2, $(GEN_DEB_VER)) \
    -e CLI_GITCOMMIT=$(CLI_GITCOMMIT) \
    -e ENGINE_GITCOMMIT=$(ENGINE_GITCOMMIT) \
    -v $(CURDIR)/debbuild/$@:/build \
    -v $(UOS_tini):/UOS_Tini \
    -v $(UOS_containerd):/UOS_containerd \
    -v $(UOS_app):/UOS_app \
    -v $(UOS_buildx):/UOS_buildx \
    -v $(UOS_libnetwork):/UOS_libnetwork \
    -v $(UOS_rootlesskit):/UOS_rootlesskit \
    -v $(UOS_tine):/UOS_tine \
    -v $(UOS_runc):/UOS_runc \
    -v $(UOS_sh):/UOS_sh \
    -v $(UOS_toml):/UOS_toml \
    -v $(UOS_vndr):/UOS_vndr \
    $(RUN_FLAGS) \
    debbuild-$@/$(ARCH)

2.修改engine/hack/docker/install/目录下的:

./components/packaging/plugins/app.installer
./components/packaging/plugins/buildx.installer
./components/engine/hack/dockerfile/install/proxy.installer
./components/engine/hack/dockerfile/install/runc.installer
./components/engine/hack/dockerfile/install/tini.installer
./components/engine/hack/dockerfile/install/gotestsum.installer
./components/engine/hack/dockerfile/install/tomlv.installer
./components/engine/hack/dockerfile/install/golangci_lint.installer
./components/engine/hack/dockerfile/install/rootlesskit.installer
./components/engine/hack/dockerfile/install/dockercli.installer
./components/engine/hack/dockerfile/install/containerd.installer
./components/engine/hack/dockerfile/install/vndr.installer
./components/engine/hack/dockerfile/install/shfmt.installer

和packaging/plugins/目录下:

./components/packaging/plugins/app.installer
./components/packaging/plugins/buildx.installer

修改上述文件中使用git下载代码的命令, 修改后使用挂载的本地组件:

以app.installer为例,修改代码如下, 需要将上述文件全部修改.

50.jpg

自定义docker功能

这部分内容涉及公司工作内容,拒绝提供。

9.Docker源码分析

1.Docker整体架构分析

总体架构图:

56.jpg

DockerClient:

​ 发起docker的管理请求,命令执行后,发送请求到Dokcer Daemon,然后接受返回的请求响应并做出简单处理,为一次完整的生命周期.

DockerDaemon:

​ 1.Docker Server:监听和接收client发来的请求,然后解析请求,匹配相应的路由项,调用对应的Handler来处理,然后回复client响应.

​ 2.Engine:管理大部分Job的执行,通过handler配置相应的job.

​ 3.Job:类似内核中的进程,一个任务的抽象.

Docker Registry:

​ 分为共有registry和私有registry, docker hub就是最大的共有registry.

​ docker运行过程中有3中情况可能与docker registry通信,分别为搜索镜像,下载镜像,上传镜像.对应的3个job名称分别为:search,pull和push.

Graph:

​ 统一管理docker镜像,支持多种不同的镜像存储方式,同一种类型的镜像被称为一个repository.

Driver:

​ 1.graphdriver:主要完成容器镜像的管理.

​ 2.networkdriver:主要的作用完成docker容器网络环境的配置.

​ 3.execdricer:docker的执行驱动,负责创建容器运行时的命名空间,负责容器资源使用的统计与限制,负责容器内部进程的真正运行等.

libcontainer:

​ 提供一套接口来满足上层对容器管理的需求. 可以不依靠任何依赖,直接访问内核中与容器相关的系统调用.

​ docker可以直接调用libcontainer,而最终操作容器的namespaces,cgroups,apparmor,网络设备以及防火墙规则等.

Docker Container:

​ docker服务交付的最终体验形式.