简介:面向需要在无外网或内网隔离环境中部署容器服务的运维与开发人员,该压缩包提供一套可直接落地的离线 Docker 环境部署方案。资源标签聚焦 docker,整体基于 RPM 系系统设计,尤其适配 CentOS 7 等常见服务器版本。包内共 22 个文件,主要由 20 个 RPM 依赖包、1 个 docker-compose 可执行文件和 1 个 install.sh 安装脚本组成,总大小约 120.91MB,结构清晰便于按需核对。依赖包不仅包含 docker-ce、docker-ce-cli、containerd.io 等核心组件,还收齐了 libcgroup、slirp4netns、fuse-overlayfs 等容易缺失的系统支持库,能显著降低内网安装时的依赖排查成本。使用者无需预先配置外部 YUM 源,将压缩包传输到目标机器后,运行安装脚本即可自动完成依赖校验、组件安装与 Compose 部署,整个安装过程对操作者友好。资源目前已有 4696 人学习下载,对需要离线交付容器运行环境的运维团队有较高参考价值。 我去年给一家制造业客户做服务器交付时,被一个很不起眼的需求卡了整整两天:机房在内网,服务器不允许连接外网,但业务方要求在上面跑一套容器化应用。当时我以为最快的方式是拿U盘拷几个rpm包过去装一下,结果发现docker的依赖链比想象中长得多,装到一半不是缺这个库就是缺那个so,最后只好老老实实把整套离线安装方案梳理了一遍。今天把这套过程完整记录下来,专门给同样需要在隔离网络里装docker和docker-compose的朋友做个参考。
1. 为什么"拷个安装包过去"在真实内网里行不通
很多人第一次接触内网部署时,第一反应是:docker安装包不就一个rpm或者deb文件吗?拷过去装上不就行了。如果你面对的是docker-engine那种老版本,可能确实可以这么干,但现在docker官方仓库里的docker-ce是一个完整软件包集合,你只拷一个主包过去,安装时会立刻被一堆依赖按在地上摩擦。
1.1 一条yum命令背后发生的事情
在能上网的机器上执行yum install docker-ce,yum会先去检查docker-ce这个包依赖了哪些其他包,比如container-selinux、containerd.io、docker-ce-cli、docker-buildx-plugin、docker-compose-plugin,然后再自动去源里把这些依赖包全部拉下来一起安装。这个解析过程在内网环境里完全没有,你拿过去一个孤零零的docker-ce rpm,系统告诉你需要container-selinux >= 2.103,你上哪儿找去?
1.2 内网安装真正的三个障碍
第一个障碍是依赖包缺失,这是最普遍的。第二个障碍是GPG密钥验证,直接rpm -ivh安装时,如果没有导入docker官方的GPG key,会有warning但一般能装,但如果你用yum本地仓库去装,源配置文件里没有gpgcheck=0或者没有导入key,yum直接拒绝安装。第三个障碍是系统架构和内核模块,别忘了docker依赖iptables、overlayfs、device-mapper这些底层能力,不是光有二进制文件就能跑起来的。
所以正确的思路是:在一台和服务器同样系统版本、同样架构的联网机器上,把docker-ce及其全部依赖一次性地完整拉下来,打造一个"离线软件包仓库",然后把这个仓库整体搬运到内网。版本一定要锁死,不要在内网用yum去自动解决依赖,那样十有八九会把系统搞乱。
2. 在能上网的机器上一次性备齐离线物料
离线的第一步是在联网环境里"打包",这一步做扎实了,后面到内网就是复制粘贴的活了。建议找一台和服务器同发行版、同大版本、同架构的机器,比如目标服务器是CentOS 7.9 x86_64,那你的打包机最好也是CentOS 7系列。
2.1 基于RPM的离线包制作(CentOS/RHEL系列)
先配置好docker官方源,然后使用yumdownloader把所有依赖包下载到指定目录,关键命令如下:
# 安装yum-utils,提供yumdownloader工具 yum install -y yum-utils # 添加docker官方源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 创建目录存放rpm包 mkdir -p /opt/docker-offline/rpms # 下载docker-ce及其全部依赖,--resolve会拉取依赖包 yumdownloader --resolve --destdir=/opt/docker-offline/rpms docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin如果你也想把docker-compose的独立二进制一起备好(后面细说两条路线),这一步可以先把docker compose插件版本下载好,因为docker-compose-plugin这个rpm包会随着docker-ce一起被拉下来。执行完yumdownloader之后,检查一下/opt/docker-offline/rpms目录,正常会有十几个到二十几个rpm文件,不要觉得多,这些都是必须的。
2.2 基于Debian系(Ubuntu/Debian)的离线包制作
Ubuntu服务器做离线安装更简单粗暴,用apt-get download配合apt-cache depends递归解析依赖,不过手动处理依赖比较繁琐,更推荐直接用apt-offline工具,或者用下面的脚本思路:在一台联网Ubuntu机器上把docker相关的deb包连同依赖全部下载到/opt/docker-offline/debs。
apt-get update apt-get install -y apt-utils mkdir -p /opt/docker-offline/debs cd /opt/docker-offline/debs # 下载docker-ce、docker-ce-cli、containerd.io及相关依赖 apt-get download docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin apt-cache depends docker-ce | grep Depends | awk '{print $2}' | xargs apt-get download到了内网之后,直接执行dpkg -i *.deb即可,如果提示依赖缺失,再用apt-get -f install修复一下。不过要提醒你:内网机器如果也没有配置本地apt源,apt-get -f install可能会失败,所以下载deb包时dependency一定要拉全,宁多勿缺。
2.3 把打包目录变成可用的本地源
这一步对RPM系尤其重要。在内网机器上,光靠rpm -ivh /path/*.rpm是可以装的,但docker的rpm包之间有严格的依赖顺序,手动一个个装很容易踩坑。更稳的做法是把rpm包目录做成一个本地yum源,让系统自己处理依赖顺序。
在打包机上先安装createrepo,对目录做索引:
yum install -y createrepo createrepo /opt/docker-offline/rpms这样/opt/docker-offline/rpms目录下会生成一个repodata子目录,整个目录就是完整的本地源了。把这整个目录传到内网服务器后,新建一个repo文件指向它:
cat > /etc/yum.repos.d/docker-local.repo << 'EOF' [docker-local] name=Docker Local Repository baseurl=file:///opt/docker-offline/rpms enabled=1 gpgcheck=0 EOF之后内网机器上执行yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin,它会先从本地源里把依赖关系理清楚,按正确顺序装好。这是我实测最稳的一条路,比手动rpm -ivh挨个敲省心太多。
3. 内网服务器的安装实战与初始化配置
物料备齐之后,就该进内网干活了。把整个/opt/docker-offline目录通过内网传输工具(scp、sftp、或者直接U盘拷贝)搬到目标服务器上,然后开始安装。
3.1 上传与本地yum安装过程
假设内网服务器也是CentOS 7.9,把docker-offline目录放到/opt下,然后执行:
cd /opt/docker-offline cp rpms/repodata /opt/docker-offline/rpms/ cat > /etc/yum.repos.d/docker-local.repo << 'EOF' [docker-local] name=Docker Local Repository baseurl=file:///opt/docker-offline/rpms enabled=1 gpgcheck=0 EOF yum clean all yum makecache yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这里解释一下为什么gpgcheck=0:离线状态下没有docker官方的GPG key,开启校验反而会导致安装失败。如果你对安全有更高要求,可以把打包机上/etc/pki/rpm-gpg里的docker公钥文件一并拷过来,在repo文件里配置gpgkey=file:///path/to/RPM-GPG-KEY-docker,这样既保留校验又不会失败。实际内网项目里为了快速交付,绝大多数都是gpgcheck=0,这个看你们公司的安全策略来定。
3.2 Docker配置初始化与systemd启动
安装完成后,直接systemctl start docker很大概率能起来,但建议先做几步配置再启动,省得后面反复重启。
先创建一个/etc/docker/daemon.json,内网环境下最常见的配置如下:
{ "data-root": "/data/docker", "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" }, "storage-driver": "overlay2" }>systemctl daemon-reexec systemctl enable docker systemctl start docker
systemctl enable docker这步一定要做,内网服务器一旦重启,如果docker没有设置开机自启,你不在现场的时候就只能远程喊人处理了。
3.3 安装后的验证清单
启动完成后,挨个检查这几项:
docker version,确认Client和Server都有输出,Server部分有输出说明dockerd正常。docker info,检查Storage Driver是否为overlay2,Cgroup版本是否符合预期。systemctl status docker,确认active (running)。docker run --rm hello-world,如果你离线环境没有hello-world镜像也别慌,可以跳过,后面用业务镜像验证即可。- 检查
/etc/docker/daemon.json里的配置是否在docker info里生效。
如果你发现Server能启动但容器起不来,大概率是SELinux或者内核模块有问题,这个我在后面单独列一节细说。
4. docker-compose离线部署的两条路线与选择逻辑
docker-compose的离线安装,网上教程五花八门,核心其实只有两条路线:一条是装docker compose v2插件,一条是装docker-compose独立二进制。这两条路线并不冲突,但新手很容易搞混。
4.1 路线一:docker compose v2插件(推荐)
在rpm包打包的时候,我们特意把docker-compose-plugin这个包也下载了,它安装之后会在/usr/libexec/docker/cli-plugins/或/usr/local/lib/docker/cli-plugins/目录下放一个docker-compose二进制文件。装好之后,使用命令是docker compose(注意中间有空格),不需要额外下载任何东西。
验证方式:
docker compose version如果rpm包里已经包含了这个插件,这么一条命令就完成了compose的离线安装。这是目前docker官方推荐的用法,和docker CLI集成得非常紧密,不要再去折腾独立二进制了。
4.2 路线二:docker-compose独立二进制(老环境兼容)
如果你负责的是老版本docker服务器(比如docker 18.x、19.x),或者内网环境对docker-compose这个带横杠的命令有硬性要求,那就需要下载独立二进制文件。下载时要特别注意版本和架构,官方GitHub Releases页面里有docker-compose-linux-x86_64和docker-compose-linux-aarch64这类的文件名,千万别下错。
# 在联网机器上下载,假设是x86_64架构 curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64" -o docker-compose # 传到内网服务器后 chmod +x docker-compose mv docker-compose /usr/local/bin/ docker-compose versionchmod +x这步很多人会忘,不然执行的时候会报Permission denied。独立二进制的优势是只依赖libc和内核,基本是"拷过去就能用",但缺点是它不再随docker-ce的rpm包自动更新,版本相对容易落后。
4.3 版本匹配与依赖细节
如果你使用独立二进制路线,docker-compose和docker server之间没有严格的版本绑定,但老版本compose对新的compose file spec支持度有限。比如compose v1(1.29.x)就不支持deploy.resources里的一些新字段。所以尽量下载较新的v2版本。这里有个小提醒:国内网络访问GitHub时经常超时,可以提前把二进制文件下载好存在共享网盘或者对象存储里,内网传输时再用内网工具拉取,效率会高很多。
另外,无论哪条路线,compose文件里指定的镜像都需要能被内网docker拉到,这就要用到下一节的内容。如果镜像拉不到,compose配置得再完美也是白搭。
5. 内网环境的镜像分发:离线镜像怎么进内网
docker和docker-compose装好之后,最核心的问题变成了:内网机器上没有任何镜像,业务容器用什么跑?这一步才是整个内网交付的真正大头。
5.1 最直接的docker save/load方案
在联网机器上先把需要的镜像全部docker pull下来,然后通过docker save打包成tar文件:
# 在联网机器上 docker pull mysql:8.0 docker pull redis:7.0 docker pull nginx:1.24 # 打包成单个tar文件 docker save -o /opt/images/base-images.tar mysql:8.0 redis:7.0 nginx:1.24把tar文件传到内网机器后,docker load -i base-images.tar就完了。docker save和docker export很容易混,这里特别提醒一下:docker save保存的是镜像,可以用来重新load后创建容器;docker export导出的是容器文件系统,再import之后只是一个普通镜像,不会保留原来的CMD、ENTRYPOINT等元数据,业务镜像必须用save/load。
5.2 搭建内网镜像仓库(image registry)
如果你要管理几十上百个镜像,或者后续有版本更新迭代,一个个save/load显然不现实。这种情况建议直接在任意一台内网服务器上部署一个Harbor或者轻量的registry。Harbor本身也可以用docker-compose来启动,正好能用上前面装的docker-compose。
离线部署Harbor的方式是:在联网机器上把Harbor的离线安装包( harbor-offline-installer-v2.x.x.tgz )下载下来,传到内网解压后修改harbor.yml,然后执行./install.sh。Harbor离线包里自带了所需镜像,它会自动docker load。装好之后,其他内网服务器在大文件/etc/docker/daemon.json里配置"insecure-registries"指向Harbor地址,就可以直接docker pull了。Harbor的地址如果用的是HTTP而不是HTTPS,必须在daemon.json里配置insecure-registries,否则docker会拒绝拉取。
5.3 避免踩"镜像版本漂移"的坑
镜像在联网机器上打好包之后,强烈建议记录一下镜像的sha256摘要。离线环境下没有外网校验,镜像文件在U盘拷贝或者内网传输过程中如果损坏了一个layer,load的时候会报错。先用docker images --digests记录一下,到内网load完再对比一次,能及时发现传输问题。另外,业务方如果有多个环境要求,尽量在同一个联网机器上同时打好所有环境的镜像tar包,避免不同机器来源导致镜像版本不一致。
6. 我在多次内网部署里踩过的坑(经验清单)
最后把这些年做内网环境docker交付时踩过的坑集中整理一下。有些问题当时排查了好几个小时,回头一看原因特别简单,但就是会卡住你。
6.1 SELinux和防火墙是头号敌人
CentOS 7/8默认SELinux是enforcing状态。docker安装后第一次启动容器,如果报Permission denied或cannot open directory,大概率是SELinux在捣乱。最简单的处置方案是:
setenforce 0 sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config改成permissive而不是disabled,是因为有些安全基线检查工具会认为disabled是不合规的。另外,如果内网服务器开了firewalld,记得放行docker需要用到的端口,否则容器映射出来的服务从外部访问不通:
firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --reload内网环境没有外网流量,很多人会忽略防火墙,但目标服务器上的iptables策略往往很严格,该放行的端口一个都不能少。
6.2 overlay2存储驱动和内核版本
docker默认推荐存储驱动是overlay2,如果docker info显示Storage Driver是devicemapper,通常说明内网机器的内核太老(比如3.10以下),或者overlay内核模块没加载。在CentOS 7上,overlayfs模块一般是内置的,确认一下:
lsmod | grep overlay modprobe overlay如果内核确实太老,比如CentOS 6或者特别精简的定制内核,那就得考虑升级内核或者换用vfs存储驱动。但vfs性能很差,不建议生产环境使用。
6.3 cgroup v2兼容性
如果你面对的是比较新的系统(CentOS 9、Ubuntu 22.04及以上),系统默认启用了cgroup v2。这里有个历史坑:docker-ce 20.10以下版本在cgroup v2下可能无法正常限制容器资源。解决方法是升级docker到新版本,或者在启动参数里加上systemd.unified_cgroup_hierarchy=0来临时切回cgroup v1。我在一次Ubuntu 22.04内网交付中遇到过dockerd能起来但docker run卡住的问题,查到最后就是cgroup v2和旧docker的兼容性问题。
6.4 磁盘空间规划要提前做
docker的数据目录最好单独规划。容器镜像、容器日志、挂载数据卷都放在/var/lib/docker下,如果在根分区只有20GB的服务器上跑几个大镜像,分分钟写满。建议把style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />