在mac环境下交叉编译ARM32版Docker

前言

  在把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

  现在可以将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

你可能感兴趣的:(树莓派)