本文与前面文章相同,但多了一些分析的步骤。

一、环境搭建

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

docker -v
Docker version 17.10.0-ce, build f4ffd25

二、下载源码

docker的github官方网站为:https://github.com/docker/docker-ce/。
docker以每月发布一个版本的节奏进行开发。命名规则为:年份-月份-ce,其中ce表示社区版本。截至本文撰写时,最新版本为v18.02.0-ce,但下一版本v18.03.0的rc版本已经释放出来了,主分支的版本号为v18.03.0-ce-dev(带dev表示开发阶段),本文编译得到的版本即为v18.03.0-ce-dev
发行版本下载地址:
https://github.com/docker/docker-ce/releases
本文编译的源码,无实际路径无关。
下载源码:

git clone https://github.com/docker/docker-ce

进入docker-ce目录:

cd docker-ce

三、编译过程

本节编译docker-ce主分支代码,经过分析后,对其编译脚本进行了修改、调整,以加速编译时间。

Makefile分析

这里先跟踪顶层Makefile到具体平台的编译Makefile文件。
首先是工程目录docker-ce的Makefile,由于是ubuntu系统,因此编译的是deb包,相关命令:

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

从命令看到,调用的是components\packaging\deb目录的Makefile(默认情况下,执行的是Makefile文件), 该Makefile文件关于deb的编译命令如下:

deb: ubuntu debian raspbian

而ubuntu平台又涉及2个发行版本:

ubuntu: ubuntu-xenial ubuntu-trusty

关于ubuntu-xenial,编译命令:

ubuntu-xenial: ## build ubuntu xenial deb packagesdocker build -t debbuild-$@/$(ARCH) -f $(CURDIR)/$@/Dockerfile.$(ARCH) .docker run --rm -i \-e DEB_VERSION=$(DEB_VERSION) \-e VERSION=$(VERSION) \-e DOCKER_GITCOMMIT=$(GITCOMMIT) \-v $(CURDIR)/debbuild/$@:/build \-v $(ENGINE_DIR):/engine \-v $(CLI_DIR):/cli \-v $(CURDIR)/systemd:/root/build-deb/systemd \debbuild-$@/$(ARCH)$(CHOWN) -R $(shell id -u):$(shell id -g) debbuild/$@

大意是先用docker build构建一个镜像(涉及到Dockerfile,后文再提及),然后运行这个镜像,运行命令需要设置环境变量(VERSION等),还有挂载目录($(ENGINE_DIR):/engine等),执行的命令是docker镜像默认的命令。构建docker镜像命令如下:

docker build -t debbuild-$@/$(ARCH) -f $(CURDIR)/$@/Dockerfile.$(ARCH) .

针对ubuntu16.04(代号为ubuntu-xenial),其中编译生成的镜像名称为debbuild-@/@/@/(ARCH),展开宏定义,则变成debbuild-ubuntu-xenial/x86_64,而由-f指定Dockerfile,则为ubuntu-xenial/ Dockerfile.x86_64
ockerfile.x86_64需要访问https://golang.org下载go语言安装包,该网站国内一般无法访问,因此需要想其它方法。

编译流程

Dockerfile.x86_64看出,默认执行脚本为build-deb,该文件位于Makefile同一目录,大致内容为进行4个组件的编译,再编译docker源码,然后拷贝生成的文件到指定目录。
具体细节本文不展开。

修改编译流程

在编译docker源码过程中,每次都会构建docker镜像,而在docker里面,每次都需要从github.com上克隆4个必要的组件源码(并进行编译),这个过程在起初时是必要的,但如果在实际开发中只需要修改个别源码进行编译的话,跑完整个流程就显示比较繁琐了。修改思路有:
预先制作好包含go语言环境的docker(已经制作好singula/docker-dev),基于这个docker镜像再次制作编译所需镜像。
将编译的组件源码目录挂载到主机目录,这样不需要每次都从网络上下载了。

修改工程目录Makefile,参考原来的deb,新加mydeb编译:

# build mydeb for ubuntu-xenial(16.04)
.PHONY: mydeb
mydeb: ## build deb packages$(MAKE) VERSION=$(VERSION) CLI_DIR=$(CLI_DIR) ENGINE_DIR=$(ENGINE_DIR) -C $(PACKAGING_DIR)/deb -f myMakefile ubuntu-xenial

components\packaging\deb目录,参考Makefile,新建myMakefile,关键内容:

.PHONY: xenial_docker
xenial_docker: ## build the dockerdocker build -t debbuild-ubuntu-xenial/$(ARCH) -f $(CURDIR)/ubuntu-xenial/myDockerfile.$(ARCH) ..PHONY: ubuntu-xenial
ubuntu-xenial: ## build ubuntu xenial deb packagesmkdir -p $(CURDIR)/src/tini $(CURDIR)/src/libnetwork \$(CURDIR)/src/runc $(CURDIR)/src/containerddocker run --rm -i \-e DEB_VERSION=$(DEB_VERSION) \-e VERSION=$(VERSION) \-e DOCKER_GITCOMMIT=$(GITCOMMIT) \-v $(CURDIR)/debbuild/$@:/build \-v $(ENGINE_DIR):/engine \-v $(CLI_DIR):/cli \-v $(CURDIR)/systemd:/root/build-deb/systemd \-v $(CURDIR)/src/tini:/go/tini \-v $(CURDIR)/src/libnetwork:/go/src/github.com/docker/libnetwork \-v $(CURDIR)/src/runc:/go/src/github.com/opencontainers/runc \-v $(CURDIR)/src/containerd:/go/src/github.com/containerd \debbuild-$@/$(ARCH) /root/build-deb/mybuild-deb$(CHOWN) -R $(shell id -u):$(shell id -g) debbuild/$@cp $(CURDIR)/debbuild/$@/*.deb $(TOP_DIR)

该文件将构建docker和编译拆分出来,编译部分,将编译所需的组件目录挂载位于deb同级目录的src目录。最后将生成的deb包拷贝到工程目录。
参考编译脚本build-deb新建mybuild-deb文件。将TMP_GOPATH="/go" hack/dockerfile/install/install.sh $component修改为TMP_GOPATH="/go" hack/dockerfile/myinstall/install.sh $component
components\engine\hack\dockerfile目录下,拷贝install为myinstall,修改其中的文件:
containerd.installer、proxy.installer、runc.installer、tini.installer。修改git clone的处理逻辑。
以tini.installer为例,原来内容为:

TINI_COMMIT=949e6facb77383876aeff8a6944dde66b3089574install_tini() {echo "Install tini version $TINI_COMMIT"git clone https://github.com/krallin/tini.git "$GOPATH/tini"cd "$GOPATH/tini"git checkout -q "$TINI_COMMIT"cmake .make tini-staticmkdir -p ${PREFIX}cp tini-static ${PREFIX}/docker-init
}

修改后为

TINI_COMMIT=949e6facb77383876aeff8a6944dde66b3089574install_tini() {echo "Install tini version $TINI_COMMIT"if [ ! -d $GOPATH/tini/.git ]; thenecho "will clone tini..."git clone https://github.com/krallin/tini.git "$GOPATH/tini"elseecho "tini exist..."ficd "$GOPATH/tini"git checkout -q "$TINI_COMMIT"cmake .make tini-staticmkdir -p ${PREFIX}cp tini-static ${PREFIX}/docker-init
}

即,判断tini是否被下载,如果是,则不再下载。如否,则下载之。
其它文件同理。

编译及生成文件

在docker-ce目录输入make mydeb即可进行编译。最后生成的安装包位于同一目录下。
如果从未编译过docker-ce,编译耗时约在20~30分钟(大约数,根据网络和机器性能而定),如果已编译过docker-ce,修改源码后,再次编译,则只需要几分钟到十几分钟即可。大减少编译时间。
安装
将得到的deb包存放到本机或其它ubuntu系统上,执行以下命令进行安装:

# dpkg -i docker-ce_18.04.0~ce~dev~git20180312.035344.0.37dff31-0~ubuntu_amd64.deb

验证其版本号:

# docker -v
Docker version 18.04.0-ce-dev, build 2b42807

到此,docker的编译结束。

备注

本文所用方法,考虑了与官方docker源码不发生冲突,但在合并时,还是要注意本文提到的修改的文件。至于是否有其它更好的办法,则待后面发现时再尝试。

我的docker随笔13:docker源码编译进阶篇相关推荐

  1. 团队环境搭建:使用docker快速架构AOSP源码编译环境(谷歌原版)

    文章目录 1. 篇首语 2. 多环境的实现方案 3. docker 部署的基本步骤 4. docker 基础安装 4.1 前置知识 4.2 docker 引擎安装 4.3 添加用户到docker Gr ...

  2. flink1.13.2源码编译遇到的坑1.Failed to execute goal org.apache.rat:apache-rat-plugin:0.12

    1. 问题:Failed to execute goal org.apache.rat:apache-rat-plugin:0.12:check (default) on project flink- ...

  3. flink1.13.2源码编译遇到的坑(三)Browserslist: caniuse-lite is outdated. Please run next command `npm update

    问题:Browserslist: caniuse-lite is outdated. Please run next command npm update 解决办法:先删了node_modules/c ...

  4. 代码工程 /Qt /5.9.3源码编译

    文章目录 概述 小试牛刀 安装Perl configure 执行编译 执行安装 再试牛刀 CMD导致的杯具 正式使用新环境 Qt 安装版(exe文件) 目录基本说明 一个小插曲 重新来过 编译环境 P ...

  5. 我的docker随笔12:docker源码编译

    因工作需要从源码编译docker,本文对此进行介绍. 一.环境搭建 docker的编译,需要在宿主机预先安装docker软件.因为编译docker的源码时,会构建一个docker镜像并运行,在这个容器 ...

  6. centos 访问网页重启php_php项目上线基于docker运行php+源码编译实现Nginx+阿里云RDS连接实现...

    项目背景: 公司项目上线要求运维把上线工作做好,并实现稳定性运行,活不多说,干! 环境要求: CentOS Linux release 7.2.1511 (Core) docker 版本:19.03. ...

  7. Docker源码编译(二)

    这是根据自己项目修改而记录的过程,对他人不具有参考性 一.按照以下教程,搭建docker编译环境:Docker源码编译和开发环境搭建 二.由于我对docker源码的修改导入了mysql数据库的包,如下 ...

  8. docker push 过程 distribution源码 分析

    docker push 过程 distribution源码分析 承接上一篇"distribution structure and start up 分析"本文分析一下distrib ...

  9. Docker源码编译

    官方建议docker源码编译在docker容器内进行,因为官方提供的容器内已经继承了编译需要的环境,如果非要自己搭建编译环境也不是不可以,就是稍微有些繁琐.以下以1.8.2版本为例. 1.pull d ...

最新文章

  1. jquery ready 与资源加载顺序
  2. lustre1.6.5+drbd主备切换
  3. 在线应用的 Serverless 实践
  4. shell的if判断比较
  5. 网络:NAT使用场景
  6. mysql 变量生命周期_Go: 延长变量的生命周期
  7. 类与对象、引用传递、封装、构造方法、匿名对象笔记
  8. PBRT 学习:安装编译
  9. php.ini 没有pdo,检查了启用的php.ini文件“ extension = php_pdo_mysql.dll”,但仍然出错...
  10. CAS(Central Authentication Service)——windows上简单搭建及測试
  11. Android4开发入门经典 之 第四部分:用户界面
  12. imagej 基本操作
  13. CSS常用基础效果---文字与图片并排+导航栏
  14. 启动计算机实现5秒开机,win10提高开机速度的设置教程 电脑五秒开机优化步骤...
  15. 栅格数据矢量化(附有完整代码)
  16. java word书签_java和javascript获取word的 书签位置
  17. Frefox安装AeroFox皮肤插件后菜单字体的美化
  18. 关于微信小程序跳转到H5,然后从H5又跳回微信小程序问题的资料
  19. [渝粤教育] 西南科技大学 仓储与配送管理 在线考试复习资料
  20. 5、隐私计算--同态加密

热门文章

  1. Reddit前CEO黄易山:马斯克不懂言论自由的挑战
  2. “金嗓子”宣布退市!曾因罗纳尔多代言争议爆红,广告词家喻户晓…
  3. 上海一公司向苹果索赔100亿,要求停售iPhone
  4. 小米“618”战报:全平台支付金额破190亿,同比增长90%
  5. 全球破300万!小米11系列高端市场地位稳了
  6. 重庆木叶村,每天被忍者迷骚扰500次
  7. 史上最贵!iPhone 12S系列9月亮相,全系标配激光雷达
  8. 奥迪公布未来五年计划:将在电动汽车方面投资120亿欧元
  9. 小米史上最“短命”旗舰机:年初发布,官网已正式下架
  10. 还是原来的配方和味道!《英雄联盟》手游界面再曝光...