1. 程式人生 > >centos7下docker1.10.3 rpm 原始碼編譯小記

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
  1. 每次編譯時候都會去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
    }
    
  2. 編譯過程中會建立/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,重新構建映象即可。

  3. 構建完映象,通過映象起容器,在容器內編譯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單元測試也會出錯,同樣也是查詢關鍵字跳過該單元測試。

  4. 通過單元測試後,就會開始打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,去掉剛才新增程式碼也沒有出問題。