centos7下docker1.10.3 rpm 原始碼編譯小記
下載rpm原始碼包
比如從https://cbs.centos.org/koji/buildinfo?buildID=16801上下載原始碼釋出包:docker-1.10.3-59.el7.centos.src.rpm
提取原始碼
通過如下命令將打了所有的patch後的原始碼輸出到/root/rpmbuild目錄下
rpm -ivh docker-1.10.3-59.el7.centos.src.rpm
執行以上命令後rpmbuild資料夾下產生的目錄結構如下:
[[email protected] rpmbuild]# tree . ├── SOURCES │ ├── 30bf0b874ebdda9b8d2a7adf36ce1dcbf5a67f1d.tar.gz │ ├── docker-cleanup.sh │ ├── docker-common.sh │ ├── docker-logrotate.sh │ ├── docker-lvm-plugin-bc03b53.tar.gz │ ├── docker-network.sysconfig │ ├── docker-novolume-plugin-c521254.tar.gz │ ├── docker-selinux-98617f3.tar.gz │ ├── docker.service │ ├── docker-storage-setup-0d53efa.tar.gz │ ├── docker-storage.sysconfig │ ├── docker.sysconfig │ ├── README-docker-common │ ├── README.docker-logrotate │ ├── v1.10-migrator-c417a6a.tar.gz │ └── v1.10-migrator-helper └── SPECS └── docker.spec 2 directories, 17 files
對原工程進行修改
主要是為了更快的編譯原始碼,避免採坑,加快速度。整個編譯流程從進入SPECS目錄開始,執行如下命令即可
rpmbuild -ba dokcker.spec
-
每次編譯時候都會去https://github.com/projectatomic/docker.git下載這個docker Git倉庫,而國內下載出奇的慢,可以提前下載好(下載的是rhel7-1.10.3分支程式碼),然後修改SPEC目錄下的docker.spec檔案,讓它每次做copy即可,具體改動如下:
%check [ ! -w /run/%{name}.sock ] || { mkdir test_dir pushd test_dir cp /root/docker.tar.gz ./ tar zxvf docker.tar.gz #git clone https://github.com/projectatomic/docker.git -b %{docker_branch} pushd %{name} make test popd popd }
-
編譯過程中會建立/root/rpmbuild/BUILD目錄,並且解壓SOURCES/30bf0b874ebdda9b8d2a7adf36ce1dcbf5a67f1d.tar.gz檔案到/root/rpmbuild/BUILD下,產生docker-30bf0b874ebdda9b8d2a7adf36ce1dcbf5a67f1d資料夾。然後根據 docker-30bf0b874ebdda9b8d2a7adf36ce1dcbf5a67f1d資料夾下的DockerFile的配置不斷根據centos7作為基礎映象去不斷的新增新的層構建新的映象。整個過程一共有50多步,由於國內防火牆的原因經常容易下載超時,或者下載網址失效導致構建映象失敗。經驗之談是在失敗的Step處修改DockerFile,這樣每次重新構建時候不會從頭開始構建(會using cache),否則又要重頭開始漫長的下載。
2.1 從DockerFile中刪除 OSX_SDK MacOSX10.11.sdk步驟,該步驟是跨平臺編譯Mac OS版本docker,由於 https://s3.dockerproject.org/darwin/網址失效,導致該構建步驟失敗
2.2 在構建過程中會提示pip command not found及jq command not found, 其實DockerFile中一開始就會批量安裝很多的依賴包,其中就包含了pip 和 jq,但是還是在後面構建過程中失敗,我的解決方式是在失敗的step前分別在新增RUN yum install jq -y和RUN yum install python-pi -y
2.3 整個50多層的映象構建成功後,生成centos-dev映象,開始利用該映象起容器,在容器內部build docker-1.10.3 二進位制檔案。然後會編譯各種平臺的docker bin 檔案。在編譯docker-1.10.3.exe 出錯。主要是缺少mingw64-gcc安裝包,該安裝包是linux跨平臺編譯Windows程式的編譯器,在DockerFile 加入RUN yum install mingw64-gcc -y,重新構建映象即可。
-
構建完映象,通過映象起容器,在容器內編譯bin檔案,容器內的bin檔案目錄會對映到宿主機/root/rpmbuildbak/BUILD/docker-30bf0b874ebdda9b8d2a7adf36ce1dcbf5a67f1d/bundles下。生成完bin檔案後開始單元測試。在進行單元測試時又會出錯,最快的辦法是跳過出錯的單元測試
3.1 比如在做test-integration-cli 單元測試時候,就會包如下錯誤:
---> Making bundle: .integration-daemon-setup (in bundles/1.10.3/test-integration-cli) ---> Making bundle: .detect-daemon-osarch (in bundles/1.10.3/test-integration-cli) ---> Making bundle: .ensure-emptyfs (in bundles/1.10.3/test-integration-cli) ++++ tar -cC bundles/1.10.3/test-integration-cli/emptyfs . ++++ docker load ---> Making bundle: .ensure-frozen-images (in bundles/1.10.3/test-integration-cli) ++++ tar -cC /docker-frozen-images . ++++ docker load Error response from daemon: ApplyLayer exit status 1 stdout: stderr: archive/tar: invalid tar header +++ bundle .integration-daemon-stop +++ local bundle=.integration-daemon-stop
網上查了半天各種方法嘗試了後都不好解決,然後直接進入docker-30bf0b874ebdda9b8d2a7adf36ce1dcbf5a67f1d檔案,將所有包含test-integration-cli關鍵字的spec,MakeFile檔案及shell檔案找出來,將test-integration-cli刪除,這樣就會跳過test-integration-cli單元測試。
3.2 test-docker-py單元測試也會出錯,同樣也是查詢關鍵字跳過該單元測試。
-
通過單元測試後,就會開始打rpm包,打包成功後會在/root/rpmbuild/ 目錄下多出一下幾個目錄,整個資料夾如下:
BUILD BUILDROOT RPMS SOURCES SPECS SRPMS
其中RPMS目錄下會生成多個rpm包:
[[email protected] RPMS]# tree . └── x86_64 ├── container-selinux-1.10.3-59.1.el7.centos.x86_64.rpm ├── docker-1.10.3-59.1.el7.centos.x86_64.rpm ├── docker-common-1.10.3-59.1.el7.centos.x86_64.rpm ├── docker-logrotate-1.10.3-59.1.el7.centos.x86_64.rpm ├── docker-lvm-plugin-1.10.3-59.1.el7.centos.x86_64.rpm ├── docker-novolume-plugin-1.10.3-59.1.el7.centos.x86_64.rpm ├── docker-unit-test-1.10.3-59.1.el7.centos.x86_64.rpm └── docker-v1.10-migrator-1.10.3-59.1.el7.centos.x86_64.rpm
SRPMS目錄下會生成當前編譯docker的原始碼包
安裝RPM包
線上安裝docker rpm包:複製docker-common-1.10.3-59.1.el7.centos.x86_64.rpm及docker-1.10.3-59.1.el7.centos.x86_64.rpm到需要安裝的機器上,執行如下命令,待安裝成功後重啟docker即可
rmp -Uvh *.rpm
更加快捷的編譯方式
無意中將編譯機docker daemon給停了後發現docker 編譯過程中不再去構建映象起容器,直接在宿主機上編譯,太神奇了,感覺前面倒騰半天,在物理機上很快就編譯完成了,沒有繁瑣的步驟。
高版本go編譯的坑
通過這種方式去編譯rpm包後,安裝到物理機上執行 docker version 就出錯。
提示如下:
faild to get docer version: An error occurred trying to connect : Get Http://%2Fvar%2Frun%2Fdocker.sock/version:EOF
網上查詢解決方法,都試過了還是不行。然後開始看docker log,log中有一段go panic的堆疊資訊,具體是getFdFromWriter方法觸發panic,然後在網上搜到該bug是由於go 版本過高觸發的panic(docker1.10.3預設採用go1.5.3版本編譯,而編譯機我安裝的是最新版本的go1.11),同時github上對於該bug也有相關提交,具體連結在此將該提交的程式碼copy到編譯機,重新編譯,打包 安裝,該問題得到修復。
後面編譯機go也調整到1.5.3,去掉剛才新增程式碼也沒有出問題。