为什么会在centos7上编译docker的代码呢?因为我们准备在线上使用centos7来运行docker,并且我们需要自己维护docker的代码版本。下面就自己在编译代码过程中遇到的问题和解决方案做简单说明。

在编译docker代码之前肯定需要研究一下docker的代码结构以及官方推荐的方式,因为docker是开源的,所以很多第三方开发者参与。那么官方肯定会给出开发环境搭建的文档,所以拿到代码肯定先研究官方的编译方法。通过文档和代码了解到docker官方推荐的是在docker本身的容器里面搭建环境和编译,官方给出的是一个基于ubuntu的dockerfile。不过正是这个dockerfile可以清楚的知道需要为了编译准备哪些依赖环境,为我们后面自己编译提供了环境搭建的基础。然后就尝试了官方的编译方案,结果各种网络问题导致编译通不过,当然网上也有相应的解决方案,基本上就是替换一些依赖源(国外的被墙了)。但是就算编译通过了也只是一个基于ubuntu的二进制文件,只能在ubuntu的相应的系统上运行。我们需要的是一个可以在centos7上运行的二进制文件,关键要搭建一个可以持续开发和编译测试的环境。当然也可以制作一个centos7的dockerfile文件,对照着官方的ubuntu的dockerfile也很简单。但是这些都是还需要有一个前提,就是需要先安装一个以前版本的docker来启动这个环境涩,好处也是杠杠的,可以在任何一台能够运行docker的系统上进行开发和测试,而且可以进行持续集成。不过对于我们来说能够编译出一个稳定运行在centos7上的二进制文件即可,所以就尝试直接在本地进行编译,而不是通过docker的容器进行。

经过研究docker的官方编译脚步,发现本地编译也很简单,只需要在docker源码的目录下执行如下命令即可:

./hack/make.sh binary

上面这条命令就只会生成docker的二进制文件,不过肯定不会这么顺利的,执行这个命令你就会发现错误。如果第一次执行报的错误应该是找不到相应的go依赖包。那么现在就开始解决第一个问题,go依赖包。

解决go依赖包最直接的方法就一个一个去github或者其他地方去下载到本地,但是这样做很麻烦,docker依赖的go语言包很多,然后依赖包可能又依赖其他包。这里有一个简单实用的办法,也是go语言管理项目的方便之处。通过go get命令来自动下载,例如发现报错的是docker某一个目录下的依赖包,那么可以如下执行:

go get -v ./src/github.com/docker/docker/...

这条命令执行以后整个docker目录下源文件依赖的包都会被自动下载。如果发现其他目录下源文件也报同样的错误,可以按照次方法解决。不过这里需要强调一点, 这些下载都是会下载最新的包,如果编译老的docker肯定会出问题 ,如果编译最新的docker代码肯定不会有问题,因为官方的编译是这种方式。

上面执行的命令都是建立在go语言环境建立成功的基础上,我安装的go遇到是1.3.3版本的,采用源码方式安装。安装在/export/servers/go下面,然后所有的go语言工程源码目录放在 /export/servers/gopath。然后配置环境变量在用户的根目录下的.bashrc文件里面如下:

export GOPATH=/export/servers/gopathexport GOROOT=/export/servers/goexport GOARCH=amd64
export GOOS=linux

然后docker的代码目录如下:/export/servers/gopath/src/github.com/docker/docker。这样才能在gopath下面进行依赖包的下载。通过上面的方法把所有依赖包下载完以后就可以进行编译了。

在继续编译的过程中还会遇到缺少c语言依赖包缺少的问题,主要有三个,(1)sqlite3;(2)device-mapper;(3)btrfs.

第一个sqlite3可以使用如下命令安装依赖:yum install sqlite-devel.x86_64

第二个在官方的dockerfile文件里面有解决方案,执行如下命令:

git clone --no-checkout https://git.fedorahosted.org/git/lvm2.git /usr/local/lvm2 && cd /usr/local/lvm2 && git checkout -q v2_02_103
cd /usr/local/lvm2 && ./configure --enable-static_link && make device-mapper && make install_device-mapper

第三个btrfs使用如下安装依赖: yum install btrfs-progs。

这些依赖都解决了就继续编译,这个时候可能会出现ld连接错误,提示找不到库。因为docker编译的方式完全是static,所以所有依赖的库必须还要有相应的静态库(.a),而不是动态库(.so)。刚才通过 yum install sqlite-devel.x86_64安装了sqlite3的依赖,但是最后发现里面没有静态库,所以编译ld的时候出错了。我的解决办法就是重新到sqlite3的官方网站下载了源码包,然后编译安装即可。

编译完成以后,就会在docker源码目录下的bundles/1.3.1/binary/目录有如下文件:

docker  docker-1.3.1  docker-1.3.1.md5  docker-1.3.1.sha256

docker-1.3.1这个文件就是我们需要的二进制文件了,docker是一个软连接到docker-1.3.1的文件。

到此就成功完成编译了,以后修改了代码重新支持编译脚步即可:

./hack/make.sh binary