我的docker隨筆12:docker源碼編譯

因工作需要從源碼編譯docker,本文對此進行介紹。

一、環境搭建

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表示社區版本。截至本文撰寫時,最新版本爲v17.12.0-ce,但下一版本v18.01.0-ce-dev已經處於開發階段(帶dev表示開發階段),本文編譯得到的版本即爲v18.01.0-ce-dev
發行版本下載地址:https://github.com/docker/docker-ce/releases
本文在/home/latelee/docker/dev目錄進行,請根據實際情況修改目錄。
下載源碼:

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

進入docker-ce目錄:

cd docker-ce

切換到最新的tag:

git checkout -b v18.01.0-ce

三、編譯過程

本節工作目錄爲/home/latelee/docker/dev/docker-ce目錄。

修改Dockerfile

執行下面小節編譯命令時會發生一個錯誤,因此需要預先修改Dockerfile文件。
編譯時會構建一個docker鏡像來編譯,實際執行的命令是(來自components/packaging/deb的makefile,並經過解析生成的):docker build -t debbuild-ubuntu-xenial/x86_64 -f /home/latelee/docker/dev/docker-ce/components/packaging/deb/ubuntu-xenial/Dockerfile.x86_64 .
分析components/packaging/deb/ubuntu-xenial/Dockerfile.x86_64文件,知道其在構建過程會下載golang編譯器,因golang.org訪問不了,最後會構建失敗。因此需要更新下載源。解決方法:找一個國內可下載的網站。如https://dl.gocn.io/
修改components/packaging/deb/ubuntu-xenial/Dockerfile.x86_64文件。
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz"; | tar xzC /usr/local修改爲:RUN curl -fSL "https://dl.gocn.io/golang/${GO_VERSION}/go${GO_VERSION}.linux-amd64.tar.gz"; | tar xzC /usr/local
最終會構建出鏡像:debbuild-ubuntu-xenial/x86_64
注意,這個鏡像在後面的編譯中會繼續使用,因此不需要刪除。

編譯

進入目錄:

cd components/packaging/deb

deb目錄下的Makefile指定了編譯得到的是deb包。
執行編譯命令:

make  VERSION=18.01.0-ce-dev ENGINE_DIR=/home/latelee/docker/dev/docker-ce/components/engine CLI_DIR=/home/latelee/docker/dev/docker-ce/components/cli ubuntu-xenial

命令解釋:
該命令指定了版本號和docker組件的目錄(VERSION、ENGINE、CLI分別指版本號、docker引擎、docker命令行),同時指定了要編譯的系統版本(ubuntu16.04代號爲xenial),這是因爲,本文只針對一個系統版本進行編譯,而不是編譯所有的版本。

生成文件

大約經過半小時,編譯成功。最終生成的deb包位於:components\packaging\deb\debbuild\ubuntu-xenial
deb文件爲:docker-ce_18.01.0~ce~dev~git20171228.105814.0.486a48d-0~ubuntu_amd64.deb

安裝

將得到的deb包存放到本機或其它ubuntu系統上,執行以下命令進行安裝:

# dpkg -i docker-ce_18.01.0~ce~dev~git20171228.105814.0.486a48d-0~ubuntu_amd64.deb

驗證其版本號:

# docker -v
Docker version 18.01.0-ce-dev, build 486a48d

到此,docker的編譯結束。

四、docker源碼目錄剖析

docker-ce源碼目錄如下:

.
├── CHANGELOG.md
├── components  # 組件目錄
│   ├── cli
│   ├── engine
│   └── packaging
├── components.conf
├── CONTRIBUTING.md
├── Makefile # 編譯所需
├── README.md # 說明文件
└── VERSION # 版本文件

4 directories, 6 files

其中組件目錄包含三個子目錄:cli、engine、packaging。前2個爲go代碼所在目錄,packaging是構建最終二進制文件的目錄。內容如下:

.
├── deb
│   ├── build-deb
│   ├── common
│   ├── debbuild
│   ├── debian-buster
│   ├── debian-jessie
│   ├── debian-stretch
│   ├── debian-wheezy
│   ├── Makefile
│   ├── raspbian-jessie
│   ├── raspbian-stretch
│   ├── README.md
│   ├── systemd
│   ├── ubuntu-artful
│   ├── ubuntu-trusty
│   └── ubuntu-xenial
├── Jenkinsfile
├── Makefile
├── README.md
├── rpm
│   ├── centos-7
│   ├── fedora-26
│   ├── fedora-27
│   ├── gen-rpm-ver
│   ├── Makefile
│   ├── README.md
│   └── systemd
└── static
    ├── hash_files
    └── Makefile

其中deb目錄是編譯生成deb文件的,區別不同的系統版本(如ubuntu和debian,而ubuntu又以代號區別不同版本,其中trusty表示14.04,xenial表示16.04,等等)。比如ubuntu-xenial目錄包括了基於16.04的不同平臺的Dockerfile。build-deb是運行於前面提到的容器的編譯腳本。
詳細分析將在後續文檔給出。

附錄

如果下載release版本進行編譯,將得到如此錯誤:

# WARNING! I don't seem to be running in a Docker container.
# The result of this command might be an incorrect build, and will not be
# officially supported.
#
# Try this instead: make all
#
error: .git directory missing and DOCKER_GITCOMMIT not specified
  Please either build with the .git directory accessible, or specify the
  exact (--short) commit hash you are building using DOCKER_GITCOMMIT for
  future accountability in diagnosing build issues.  Thanks!
make[1]: *** [override_dh_auto_buil

解決方法:
使用git下載代碼倉庫,然後切換到發佈版本分支,再進行編譯。

由於docker版本更新非常快,本文所述,僅供參考。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章