准备环境

准备一台Linux主机,并在上面安装好docker-ce,安装好make,git就可以开始编译工作了。对,就是如此简单,可能你会对此感到异或为啥要装docker,我不是准备编译这个玩意么,为啥不装go,docker不是用go开发的么? 这些疑问会在后面的步骤中解答。

# docker-ce 安装参考
# FROM: https://developer.aliyun.com/article/110806
# Ubuntu 14.04 16.04 (使用apt-get进行安装)
# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# step 2: 安装GPG证书
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装 Docker-CE
sudo apt-get -y update
sudo apt-get -y install docker-ce 注意:其他注意事项在下面的注释中
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# apt-cache madison docker-ce
# docker-ce | 17.03.1~ce-0~ubuntu-xenial | http://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# docker-ce | 17.03.0~ce-0~ubuntu-xenial | http://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# Step 2: 安装指定版本的Docker-CE: (VERSION 例如上面的 17.03.1~ce-0~ubuntu-xenial)
# sudo apt-get -y install docker-ce=[VERSION] # 通过经典网络、VPC网络内网安装时,用以下命令替换Step 2、Step 3中的命令
# 经典网络:
# curl -fsSL http://mirrors.aliyuncs.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyuncs.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# VPC网络:
# curl -fsSL http://mirrors.cloud.aliyuncs.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# sudo add-apt-repository "deb [arch=amd64] http://mirrors.cloud.aliyuncs.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# CentOS 7 (使用yum进行安装)
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装 Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 开启Docker服务
sudo service docker start 注意:其他注意事项在下面的注释中
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,你可以通过以下方式开启。同理可以开启各种测试版本等。
# vim /etc/yum.repos.d/docker-ce.repo
# 将 [docker-ce-test] 下方的 enabled=0 修改为 enabled=1
#
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
# Loading mirror speeds from cached hostfile
# Loaded plugins: branch, fastestmirror, langpacks
# docker-ce.x86_64 17.03.1.ce-1.el7.centos docker-ce-stable
# docker-ce.x86_64 17.03.1.ce-1.el7.centos @docker-ce-stable
# docker-ce.x86_64 17.03.0.ce-1.el7.centos docker-ce-stable
# Available Packages
# Step2 : 安装指定版本的Docker-CE: (VERSION 例如上面的 17.03.0.ce.1-1.el7.centos)
# sudo yum -y install docker-ce-[VERSION]
# 注意:在某些版本之后,docker-ce安装出现了其他依赖包,如果安装失败的话请关注错误信息。例如 docker-ce 17.03 之后,需要先安装 docker-ce-selinux。
# yum list docker-ce-selinux- --showduplicates | sort -r
# sudo yum -y install docker-ce-selinux-[VERSION] # 通过经典网络、VPC网络内网安装时,用以下命令替换Step 2中的命令
# 经典网络:
# sudo yum-config-manager --add-repo http://mirrors.aliyuncs.com/docker-ce/linux/centos/docker-ce.repo
# VPC网络:
# sudo yum-config-manager --add-repo http://mirrors.could.aliyuncs.com/docker-ce/linux/centos/docker-ce.repo
# 安装其他工具, 以centos7为例子
yum install -y make git

获取源码

git clone https://github.com/moby/moby.git

其实如果你有对docker二次开发的需求了,我这边也不用再多费口舌在moby这个奇怪的项目名称上

其实就个人而言对docker改名这件事也是颇有微词的,docker公司愿意开源docker-ce固然是好事,但是直接换个名称明摆着是想把docker早期创造出来的名声都让公司的付费产品“docker”

上,而不是所谓的moby(docker-ce)。

编译前的准备工作

如果你工作网络环境足够优秀(可以稳定的访问到dockerhub和各种操作系统的源)可以跳过这一小节,肉身在国外的一般没有这种烦恼。而对于大部分国内的开发者则需要通过代理完成这个开发环境的构建,一下的步骤仅供参考。

添加dockerd的代理

docker的镜像拖取工作是由dockerd完成的(而不是你平常使用的docker命令行工具),而dockerd一般挂在systemd的进程下(如果有老哥头铁从命令行运行dockerd那么当我没说,这样也能读到代理的环境变量)。如果要为dockerd添加代理的话可以参考如下操作

# 修改为你自己的http代理地址
cat > /etc/systemd/system/docker.service.d/http-proxy.conf << EOF
[Service]
Environment="HTTP_PROXY=http://192.168.144.1:10811"
Environment="HTTPS_PROXY=http://192.168.144.1:10811"
EOF systemctl daemon-realod
systemctl restart docker

到这一步只是为镜像的拖取操作添加了代理,但是在开发环境中资源的拖取问题还是没有办法解决,这点我们稍微修改Makefile可以处理,参考如下操作

1. 在Makefile文件头部增加"include .env"
2. Makefile同目录创建.env文件并写入你的环境变量,参考如下
BUILD_PROXY := --build-arg "http_proxy=http://192.168.144.1:10811" --build-arg "https_proxy=http://192.168.144.1:10811"
3. 追加参数到指定的构建参数变量,修改Makefile, 在BUILD_OPTS := *后面的一行增加
BUILD_OPTS += $(BUILD_PROXY)

开始编译

ntpdate ntp1.aliyun.com # 同步时间,如果时间误差过大会导致部分源依赖获取失效,非必须
make BIND_DIR=. shell

构建过程由于或需要拖取镜像和资源耗时一般比较长(即使在网络条件较好的情况下),一般要10分钟左右。

如果构建成功你回进入如下的一个容器内终端

root@3cede98051a6:/go/src/github.com/docker/docker#

这个便是makefile通过dockerfile为你构建的docker-ce的编译环境,这个环境中你开发和调试的工具应有尽有,如你还有特殊的需求可以通过修改dockerfile重新构建(别担心,由于之前构建的缓存文件,你第二次构建只会构建新增部分,不会花太多的时间),项目的根目录挂载到主机目录,所以你在此路径下构建出的二进制文件也会写入到宿主机。

接下来我们开始编译

hack/make.sh binary

编译完成

root@3cede98051a6:/go/src/github.com/docker/docker# hack/make.sh binary

Removing bundles/

---> Making bundle: binary (in bundles/binary)
Building: bundles/binary-daemon/dockerd
GOOS="" GOARCH="" GOARM=""
Created binary: bundles/binary-daemon/dockerd
Copying nested executables into bundles/binary-daemon
Building: bundles/binary-daemon/docker-proxy
GOOS="" GOARCH="" GOARM=""
Created binary: bundles/binary-daemon/docker-proxy root@3cede98051a6:/go/src/github.com/docker/docker#

安装测试

# 还是在容器内
make install

启动测试

/usr/local/bin/dockerd -D

你也可以在容器内下载镜像,启动容器

# 在宿主机另开一个终端,并进入容器
[root@localhost moby]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3cede98051a6 docker-dev "hack/dind bash" 8 minutes ago Up 8 minutes condescending_swanson
dae301c0f728 yandex/clickhouse-server "/entrypoint.sh" 33 hours ago Up 33 hours 0.0.0.0:8123->8123/tcp, :::8123->8123/tcp, 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp, 9009/tcp ch-server
[root@localhost moby]# docker exec -it 3ced /bin/bash
root@3cede98051a6:/go/src/github.com/docker/docker#
# 下载镜像,启动容器
root@3cede98051a6:/go/src/github.com/docker/docker# docker pull centos:7
7: Pulling from library/centos
Digest: sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4
Status: Image is up to date for centos:7
root@3cede98051a6:/go/src/github.com/docker/docker# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 7 eeb6ee3f44bd 15 months ago 204MB
root@3cede98051a6:/go/src/github.com/docker/docker# docker run --rm -it eeb /bin/bash
[root@26c12cba6431 /]# exit
exit

使用Delve调试

都从源码构建了,总不可能单纯奔着纯安装去的吧,多少是想对docker做点简单的定制化,这里就可以使用Delve来调试我们编译出来的dockerd二进制程序了。

dlv /usr/local/bin/dockerd -- -D

哎,咋报错了

2022-12-14T09:10:43Z error layer=debugger error loading binary "/usr/local/bin/dockerd": could not parse .eh_frame section: pointer encoding not supported 0x9b at 0x3150
could not launch process: could not parse .eh_frame section: pointer encoding not supported 0x9b at 0x3150

这个报错是由于默认的hack/make.sh中的这一段(我所编译的版本在105)

IAMSTATIC='true'
if [ -z "$DOCKER_DEBUG" ]; then
LDFLAGS='-w'
fi

在编译时加了-w参数删除了调试信息,所以在编译时添加参数或者写到环境变量里就行啦

# 在容器创建时添加debug参数
DOCKER_DEBUG=1 make BIND_DIR=. shell
# 在编译时添加参数
DOCKER_DEBUG=1 hack/make.sh binary

以上两种方法都可以,之后就可以使用dlv来调试docekrd了

root@f42403397fa5:/go/src/github.com/docker/docker# dlv exec --check-go-version=false /usr/local/bin/dockerd -- -D
WARNING: undefined behavior - version of Delve is too old for Go version 1.19.4 (maximum supported version 1.18)
Type 'help' for list of commands.
(dlv)

至于为什么加上 --check-go-version=false 这个参数,如果你是使用开发中的分支,docker的开发者可能忽略了更新dlv的版本,导致dlv的版本有那么一丝落后于go的版本。如果你要解决这个问题可以通过修改Dockerfile中的 Delve镜像拖取的版本,像是如下这样,把AELVE_VERSION修改为1.9.1即可。

ARG DELVE_VERSION=v1.8.1
# Delve on Linux is currently only supported on amd64 and arm64;
# https://github.com/go-delve/delve/blob/v1.8.1/pkg/proc/native/support_sentinel.go#L1-L6
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
case $(dpkg --print-architecture) in \
amd64|arm64) \
GOBIN=/build/ GO111MODULE=on go install "github.com/go-delve/delve/cmd/dlv@${DELVE_VERSION}" \
&& /build/dlv --help \
;; \
*) \
mkdir -p /build/ \
;; \
esac

至于delve调试工具如何使用就不在本文里细述,可通过help的方式知道如何使用,类似于gdb,上手十分的简单。

参考

https://github.com/moby/moby/tree/master/docs/contributing
https://github.com/moby/moby/blob/master/docs/contributing/debug.md
https://github.com/moby/moby/blob/master/docs/contributing/set-up-dev-env.md

从源码构建docker-ce的更多相关文章

  1. java开源即时通讯软件服务端openfire源码构建

    java开源即时通讯软件服务端openfire源码构建 本文使用最新的openfire主干代码为例,讲解了如何搭建一个openfire开源开发环境,正在实现自己写java聊天软件: 编译环境搭建 调试 ...

  2. Flink源码分析 - 源码构建

    原文地址:https://mp.weixin.qq.com/s?__biz=MzU2Njg5Nzk0NQ==&mid=2247483692&idx=1&sn=18cddc1ee ...

  3. vue源码分析—Vue.js 源码构建

    Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下.(Rollup 中文网和英文网) 构建脚本 通常一个基于 NPM 托管的项目都会有一个 package.j ...

  4. Elasticsearch源码分析 - 源码构建

    原文地址:https://mp.weixin.qq.com/s?__biz=MzU2Njg5Nzk0NQ==&mid=2247483694&idx=1&sn=bd03afe5a ...

  5. centos7 源码构建、安装dubbo-monitor

    按照官方文档 ,发现dubbo-monitor-simple-x.x.x-assembly.tar.gz  下载不下来(地址访问不了),那么就自己下载源码构建吧. 我的zookeeper,hadoop ...

  6. Vue.js 源码构建(三)

    Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下. 构建脚本 通常一个基于 NPM 托管的项目都会有一个 package.json 文件,它是对项目的描述文 ...

  7. 从源码构建Vim

    从源码构建Vim 引言 事情是介样滴,因为我是个Vim 重度使用者了差不多.. 但在大部分系统上能安装到的或者自带的都是比较老的版本,可能是7.x 之类的.也或者是你需要使用到Vim 的某些特性或者功 ...

  8. 最新版 源码编译 docker

    前言: 最近想研究 docker 源码,那么要研究源码第一步就是学会通过源码编译.然后在网上查找了很多,都是比较老的版本.目前官最新的版本是 18.09.经过一番探索之后,终于成功编译了 下面我把我的 ...

  9. Docker-Java限制cpu和内存及浅析源码解决docker磁盘挂载失效问题

    需求 之前工作流的运行都是用的docker-java提供的api拉起的docker容器直接跑服务,但是最新线上的新业务资源消耗较大,单个容器如果不加控制,CPU和内存都会拉满,导致服务器莫名宕机事故的 ...

  10. Dubbo源码构建

    代码签出 通过以下的这个命令签出最新的项目源码: git clone https://github.com/apache/incubator-dubbo.git dubbo 分支 我们使用 maste ...

随机推荐

  1. 持续集成指南:GitLab 的 CI/CD 工具配置与使用

    前言 写代码这项工作,本质就是将工作自动化,减少手工操作提供效率,因为人的本质都是懒狗,程序员也不能例外,为了各种意义的效率提升(懒),我们需要持续集成工具,将代码测试.编译.发布这些重复性很高的工作 ...

  2. Java之POI导出Excel(一):单sheet

    相信在大部分的web项目中都会有导出导入Excel的需求,今天我们就来看看如何用Java代码去实现 用POI导出Excel表格. 一.pom引用 pom文件中,添加以下依赖 查看代码  <!-- ...

  3. .Net Framework中的AppDomain.AssemblyResolve事件的常见用法、问题,以及解决办法

    一.简述 本文简要的介绍.NET Framework中System.AppDomain.AssemblyResolve事件的用法.使用注意事项,以及复杂场景下AssemblyResolve事件的污染问 ...

  4. 小程序 wx.navigateTo和 wx.redirectTo区别

    wx.navigateTo 官方解释: 意思就是说. A页面跳转B页面 B页面做了操作,点击保存,再跳转回A页面 此时,如果点击左上返回按钮,仍然可以跳转回B页面,而且里面的数据是操作之前的数据 wx ...

  5. java集合框架复习----(2)List

    文章目录 三.List集合 listIterator:迭代器 List实现类 1.泛型类 2.泛型接口 三.List集合 特点 有序,打印输出的顺序和添加时的顺序一致(不会帮你自动排序) 有下标,可以 ...

  6. 【vue2】Style和Class,条件,列表渲染,双向数据绑定,事件处理

    目录 1.style和class 2. 条件渲染 2.1 指令 2.2 案例 3. 列表渲染 3.1 v-for:放在标签上,可以循环显示多个此标签 3.2 v-for 循环数组,循环字符串,数字,对 ...

  7. java简易两数计算器

    public class calculator { public static void main(String[] args) { Scanner scanner = new Scanner(Sys ...

  8. HTML躬行记(3)——WebRTC视频通话

    WebRTC 在创建点对点(P2P)的连接之前,会先通过信令服务器交换两端的 SDP 和 ICE Candidate,取两者的交集,决定最终的音视频参数.传输协议.NAT 打洞方式等信息. 在完成媒体 ...

  9. 真正“搞”懂HTTP协议03之时间穿梭

    上一篇我们简单的介绍了一下DoD模型和OSI模型,还着重的讲解了TCP的三次握手和四次挥手,让我们在空间层面,稍稍宏观的了解了HTTP所依赖的底层模型,那么这一篇,我们来追溯一下HTTP的历史,看一看 ...

  10. [leetcode] 713. Subarray Product Less Than K

    题目 Given an array of integers nums and an integer k, return the number of contiguous subarrays where ...