前期准备:在线环境下的资源收集
离线编译的核心在于“万事俱备”,即在有网络访问权限的“准备机”上,下载并打包所有编译所需的源代码、工具链及依赖库,准备机的操作系统版本和架构(如CentOS 7.x, x86_64)应与目标离线机保持一致,以避免兼容性问题。
获取Docker源代码
从GitHub克隆Docker的官方源代码仓库,建议选择一个稳定的版本标签,而不是直接使用master
分支,以确保编译的稳定性。
# 克隆Docker源码仓库 git clone https://github.com/docker/docker.git # 进入项目目录并切换到指定版本(例如v20.10.17) cd docker git checkout v20.10.17
下载编译工具与系统依赖
Docker的编译依赖于一系列基础开发工具和库,在CentOS上,我们可以使用yumdownloader
命令(由yum-utils
包提供)来下载这些依赖的RPM包,而不进行安装。
# 安装yum-utils以使用yumdownloader sudo yum install -y yum-utils # 创建一个目录用于存放所有依赖包 mkdir -p ~/docker-offline-deps cd ~/docker-offline-deps # 下载核心编译工具和依赖库 yumdownloader --resolve git make gcc libtool lvm2 device-mapper-devel libseccomp-devel pkgconfig systemd-devel
为了清晰起见,以下表格列出了部分关键依赖项及其作用:
依赖包名称 | 作用 |
---|---|
git | 版本控制,用于获取和管理源代码 |
make , gcc | 基础编译工具套件 |
libtool | 提供一个通用的库支持脚本 |
lvm2 , device-mapper-devel | Docker存储驱动devicemapper的核心依赖 |
libseccomp-devel | 提供安全计算模式支持,用于限制容器系统调用 |
systemd-devel | 用于与systemd服务管理器集成 |
下载Go语言环境
Docker主要由Go语言编写,因此必须准备Go语言的编译环境,访问Go语言官方下载页面,获取与Docker版本兼容的Go版本(通常在Docker源码的go.mod
文件中有明确要求)。
# 下载Go语言安装包(以go1.18.9.linux-amd64.tar.gz为例) wget https://go.dev/dl/go1.18.9.linux-amd64.tar.gz
下载Go模块依赖
这是离线编译最关键的一步,Go语言使用模块来管理依赖,我们需要在准备机上下载所有必需的模块,并将其打包。
# 回到Docker源码目录 cd ~/docker # 设置Go模块代理(国内用户可使用代理加速) export GOPROXY=https://goproxy.cn,direct # 下载所有Go模块依赖到本地缓存 go mod download # 打包Go模块缓存目录,该目录通常位于 $GOPATH/pkg/mod # 默认GOPATH在~/go,具体路径可通过 go env GOPATH 查看 tar -czf go-mod-cache.tar.gz -C ~/go/pkg/mod .
至此,我们已获得所有必需资源:Docker源码、系统依赖RPM包、Go语言环境包以及Go模块依赖缓存包,将docker
源码目录、docker-offline-deps
目录、go1.18.9.linux-amd64.tar.gz
和go-mod-cache.tar.gz
通过U盘或内部网络传输到目标离线CentOS服务器上。
离线编译与安装
在目标离线机上,我们将依次安装环境、解压依赖、执行编译并最终部署Docker。
安装编译环境
安装之前下载的系统依赖和Go环境。
# 创建工作目录并进入 mkdir -p ~/docker-build cd ~/docker-build # 假设所有资源已上传至此目录 # 安装所有系统依赖RPM包 sudo rpm -ivh docker-offline-deps/*.rpm --nodeps --force # 解压并安装Go语言环境 sudo tar -C /usr/local -xzf go1.18.9.linux-amd64.tar.gz # 配置Go环境变量 echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc source ~/.bashrc # 验证Go是否安装成功 go version
恢复Go模块依赖
将Go模块缓存恢复到正确的位置,这是编译能够成功的关键。
# 创建Go模块缓存目录 mkdir -p ~/go/pkg/mod # 解压之前打包的模块缓存 tar -xzf go-mod-cache.tar.gz -C ~/go/pkg/mod
执行编译
环境准备就绪,现在可以开始编译Docker了,为了减少运行时依赖,推荐进行静态编译。
# 进入Docker源码目录 cd docker # 执行静态编译,生成二进制文件 # DOCKER_BUILD_PKGS=static 表示进行静态链接 make binary DOCKER_BUILD_PKGS=static
编译过程会持续一段时间,具体时长取决于服务器的性能,编译成功后,二进制文件会生成在bundles/binary-daemon/
(服务端)和bundles/binary-client/
(客户端)目录中。
安装与配置Docker
将编译好的二进制文件复制到系统路径,并配置为系统服务。
# 复制Docker客户端和服务端二进制文件 sudo cp bundles/binary-client/docker /usr/local/bin/ sudo cp bundles/binary-daemon/dockerd /usr/local/bin/ # 创建Docker的systemd服务文件 sudo tee /etc/systemd/system/docker.service > /dev/null <<EOF [Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target docker.socket firewalld.service Wants=network-online.target [Service] Type=notify ExecStart=/usr/local/bin/dockerd ExecReload=/bin/kill -s HUP $MAINPID LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity TasksMax=infinity TimeoutStartSec=0 Delegate=yes KillMode=process Restart=on-failure StartLimitBurst=3 StartLimitInterval=60s [Install] WantedBy=multi-user.target EOF # 重新加载systemd配置,启动并设置Docker开机自启 sudo systemctl daemon-reload sudo systemctl start docker sudo systemctl enable docker # 验证Docker是否安装并运行成功 docker version
如果docker version
命令能正常返回客户端和服务端的版本信息,说明离线编译安装已圆满完成。
相关问答FAQs
Q1: 编译过程中如果出现网络相关的错误(如“module not found”或“dial tcp: connection refused”)该怎么办?
A1: 这个错误几乎总是因为Go模块依赖未完全下载或路径不正确,请务必确认:第一,在准备机上的go mod download
命令成功执行,没有网络错误;第二,go-mod-cache.tar.gz
被打包时包含了~/go/pkg/mod
目录下的所有内容;第三,在离线机上解压时,目标路径~/go/pkg/mod
是正确的,并且当前用户对该目录有读写权限,Go编译器会严格在此路径下查找模块,任何偏差都会导致失败。
Q2: 通过这种方式编译出的Docker版本和官方发布的二进制版本有什么主要区别?
A2: 主要区别在于维护渠道和定制化程度,官方发布的二进制版本经过了更广泛的测试,包含了针对特定发行版的优化和补丁,并通过官方渠道提供安全更新,而从源码自编译的版本,虽然功能上完全等价,但属于“自维护”版本,这意味着当需要升级或修复安全漏洞时,你需要重复上述编译流程,自编译的最大优势在于可以深度定制,例如修改Docker的默认行为、集成特定的补丁或进行性能调优,这对于有特殊需求的企业级环境非常有价值。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复