在把docker迁移至树莓派时,需要进行源码编译,记录一下迁移过程及docker开发环境搭建的流程。这个博客是基于17.05.0-ce-rc1分支进行的。
我已经把所有的编译环境制作了镜像,可以直接通过:
docker run --rm -i --privileged -e BUILDFLAGS -e KEEPBUNDLE -e DOCKER_BUILD_GOGC -e DOCKER_BUILD_PKGS -e DOCKER_CLIENTONLY -e DOCKER_DEBUG -e DOCKER_EXPERIMENTAL -e DOCKER_GITCOMMIT -e DOCKER_GRAPHDRIVER=devicemapper -e DOCKER_INCREMENTAL_BINARY -e DOCKER_REMAP_ROOT -e DOCKER_STORAGE_OPTS -e DOCKER_USERLANDPROXY -e TESTDIRS -e TESTFLAGS -e TIMEOUT -v “./bundles:/go/src/github.com/docker/docker/bundles” -t “talkliu/docker-arm:17.05”
直接进入镜像,通过hack/make.sh binary交叉编译。
现在网上的大部分教程都比较老了,现在docker的主项目已经从之前的docker/docker迁移到了新的/moby/moby目录中,同时除了docker以外还需要其他几个应用的支持,总共需要clone的项目如下:
1、docker:docker主项目。包含docker及dockerd执行程序。
git clone https://github.com/moby/moby.git
2、containerd:docker的镜像管理程序,从之前的主项目剥离出来成为独立的项目。包含docker-containerd、docker-containerd-ctr、docker-containerd-shim执行程序。
git clone https://github.com/docker/containerd.git
3、runc:最终启动容器的工具,是整个容器的核心,实际上没有 dockerd 也是发送命令到containerd containerd 再 启动 containd-shim containerd-shim 再调用runc 来启动容器 停止容器等容器运行生命周期的各种操作。其实没有前几个进程,可以直接发送数据给runc 启动容器。包含docker-runc执行程序。
git clone https://github.com/opencontainers/runc.git
4、tini:保护宿主机出现僵尸进程导致内存耗尽等情况发生。包含docker-init执行程序。
git clone https://github.com/krallin/tini.git
5、proxy:用于配制docker端口的管理。包含docker-proxy
git clone https://github.com/docker/libnetwork.git
在clone出moby项目进行make时,会根据如下的Dockerfile生成编译用的docker镜像,所以在编译之前系统需要安装docker以支持moby项目的编译。
make BIND_DIR=. shell
在执行完这个命令后,make会根据Dockerfile生成一个基于debian:jessie的镜像,并自动安装golang等其他应用支持包,如果在国内的话,因为各种墙的问题,失败的几率非常高,所以可以直接pull一个官方的镜像进行改造编译,这里直接使用的是17.05的镜像版本。
docker pull dockercore/docker:17.05
官方指定的镜像以通过CMD的形式关联了编译脚本hack/make.sh,但是作为交叉编译,需要进入镜像进行改造,通过以下方式进入镜像,并通过-v的形式将一个bundles文件夹关联到镜像内部,以接收编译最终生成的产物:
docker run --rm -i --privileged -e BUILDFLAGS -e KEEPBUNDLE -e DOCKER_BUILD_GOGC -e DOCKER_BUILD_PKGS -e DOCKER_CLIENTONLY -e DOCKER_DEBUG -e DOCKER_EXPERIMENTAL -e DOCKER_GITCOMMIT -e DOCKER_GRAPHDRIVER=devicemapper -e DOCKER_INCREMENTAL_BINARY -e DOCKER_REMAP_ROOT -e DOCKER_STORAGE_OPTS -e DOCKER_USERLANDPROXY -e TESTDIRS -e TESTFLAGS -e TIMEOUT -v "../bundles:/go/src/github.com/docker/docker/bundles" -t "dockercore/docker:17.05" bash
##设置编译环境
因为官方默认的是64位程序的编译,在之前的项目中,我们或许还可以通过官方给出的Dockerfile.armhf来生成armhf的交叉编译镜像,但最新的项目中已经把其抛弃掉了,所以我们需要进行如下的准备工作:
1、设置环境变量:
#因为docker是golang进行编译的所以直接声明目标平台架构
export GOARCH=arm
#打开CGO支持
export CGO_ENABLED=1
#声明目标平台系统
export GOOS=linux
#声明编译工具
export CC=arm-linux-gnueabihf-gcc
#声明编译docker的版本
export DOCKER_GITCOMMIT=89658be
2、准备编译工具:
编译工具可以使用树莓派官方提供的tools工具包,也可以是使用debian依赖安装的gcc-arm-linux-gnueabihf,但debian:jessie镜像的源不包含,所以使用时需要将源添加至source.list.
#下载树莓派官方提供的交叉编译包
git clone git://github.com/raspberrypi/tools.git
#使用debian官方提供的gcc-arm-linux-gnueabihf
echo "deb http://ftp.de.debian.org/debian sid main" >> /etc/apt/sources.list
apt-get update
apt-get install gcc-arm-linux-gnueabihf
3、交叉编译支持库:
docker编译会有两个选择,binary/dynbinary即静态编译与动态编译,所以需要提供的arm库的数量也不同:
#静态编译提供的dev如下:
libapparmor-dev
libdevmapper-dev
libseccomp-dev
#动态编译提供的dev如下:
libapparmor-dev
libdevmapper-dev
libseccomp-dev
libltdl-dev
libattr1-dev
libcap-dev
intltool
libtinfo-dev
util-linux
expat
dbus
ffi
zlib
glib-2.0
libsystemd-dev
因为依赖关系,在编译过程中需要按照顺序进行,在编译完成后,即可通过hack/make.sh进行编译。
4、交叉编译runc、tini、proxy、proxy四个执行程序:
在官方的镜像中有自动编译这四个执行程序的脚本,只要设置了环境变量,可以自动编译出ARM平台下的执行程序:
#清理x64环境下的执行程序
rm -rf /usr/local/bin/docker-*
#编译执行程序
sh /go/src/github.com/docker/docker/hack/dockerfile/install-binaries.sh runc tini proxy containerd
5、编译docker
使用hack/make.sh脚本进行编译docker与dockerd执行程序。
#编译静态包
hack/make.sh binary
#编译动态包
hack/make.sh dynbinary
在编译完后,会将docker、dockerd及其他应用程序复制到bundles文件夹下,并形成如下文件结构:
17.05.0-ce-rc1
├── binary-client
│ ├── docker -> docker-17.05.0-ce-rc1
│ ├── docker-17.05.0-ce-rc1
│ ├── docker-17.05.0-ce-rc1.md5
│ └── docker-17.05.0-ce-rc1.sha256
└── binary-daemon
├── docker-containerd
├── docker-containerd-ctr
├── docker-containerd-ctr.md5
├── docker-containerd-ctr.sha256
├── docker-containerd.md5
├── docker-containerd.sha256
├── docker-containerd-shim
├── docker-containerd-shim.md5
├── docker-containerd-shim.sha256
├── dockerd -> dockerd-17.05.0-ce-rc1
├── dockerd-17.05.0-ce-rc1
├── dockerd-17.05.0-ce-rc1.md5
├── dockerd-17.05.0-ce-rc1.sha256
├── docker-init
├── docker-init.md5
├── docker-init.sha256
├── docker-proxy
├── docker-proxy.md5
├── docker-proxy.sha256
├── docker-runc
├── docker-runc.md5
└── docker-runc.sha256
2 directories, 26 files
同时通过file命令检查所有的执行程序,是否为arm环境:
pi@raspberrypi:~$ file 17.05.0-ce-rc1/binary-daemon/dockerd-17.05.0-ce-rc1
17.05.0-ce-rc1/binary-daemon/dockerd-17.05.0-ce-rc1: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, not stripped
现在可以将docker-daemon和docker-client目录下的docker可以执行文件复制到目标系统的/usr/bin/目录下,并且启动:
sudo dockerd &
检查下docker是否可用:
pi@raspberrypi:~$ docker version
Client:
Version: 17.05.0-ce-rc1
API version: 1.29
Go version: go1.7.5
Git commit: 89658be
Built: Sat Sep 29 08:12:34 2018
OS/Arch: linux/arm
Server:
Version: 17.05.0-ce-rc1
API version: 1.29 (minimum version 1.12)
Go version: go1.7.5
Git commit: 89658be
Built: Sat Sep 29 08:12:34 2018
OS/Arch: linux/arm
Experimental: false
到目前已经成功启动docker