简介:本资源专为内网隔离环境下的Linux系统运维人员设计,解决无外网连接时无法在线安装Docker及Docker-Compose的核心痛点,适用于政企、金融、科研等强安全管控场景的CentOS 7离线部署需求。压缩包共22个文件,含20个适配el7的RPM依赖包(涵盖containerd.io、docker-ce、docker-ce-cli、fuse-overlayfs、slirp4netns等核心组件及SELinux、Python基础依赖),1个可执行安装脚本install.sh实现一键自动化部署,以及1个预编译的docker-compose-linux-x86_64二进制文件,开箱即用。资源大小120.91MB,结构精简、依赖完整,避免手动逐个解决rpm冲突与版本兼容问题。目前已有4708人学习下载,读者可直接获取经验证的离线安装方案、清晰的依赖层级关系说明、以及面向生产环境的最小化组件集合,显著降低内网Docker平台搭建门槛与排错成本。
1. 内网离线安装 Docker 与 docker-compose:没有外网、没有包管理器,也能把容器环境稳稳立住
你手头有一台刚上架的生产服务器,物理隔离在核心机房——没网线、没代理、连 ping 都不通外网;运维同事甩来一句:“这台机器要跑三个微服务,用容器部署,今天下班前上线。”你打开终端,apt update报错,yum install docker-ce提示“无法解析域名”,curl -fsSL get.docker.com直接卡死在 DNS 查询阶段……别慌,这不是玄学现场,而是典型内网交付场景。这份离线安装方案,就是专为这种“断网但不能断服务”的硬需求设计的:它不依赖任何在线仓库、不调用远程脚本、不触发自动更新机制,所有二进制、依赖库、配置模板、验证脚本全部打包就绪,解压即用,安装即验。适合安全合规要求高、网络策略严苛、或临时应急接管老旧设备的一线工程师。它解决的不是“能不能装”,而是“装完能不能立刻跑起来、出问题能不能快速定位、后续升级要不要重走一遍流程”这三个真实痛点。
2. 为什么必须离线?从 Docker 架构拆解离线安装的不可替代性
2.1 Docker 运行时本质:不是单个程序,而是一组强耦合的二进制+内核模块+用户态守护进程
Docker 并非一个可直接chmod +x && ./docker启动的单一可执行文件。它的最小可靠运行单元包含:
dockerd:主守护进程,负责镜像管理、容器生命周期、网络驱动加载、存储驱动初始化(如 overlay2);containerd:独立于 dockerd 的容器运行时,处理 OCI 容器创建、启停、状态监控;runc:符合 OCI 规范的底层容器运行时,真正调用clone()、pivot_root()等系统调用启动进程;docker-cli:命令行客户端,通过 Unix Socket 与 dockerd 通信;containerd-shim:每个容器对应的 shim 进程,隔离 containerd 主进程与容器进程树;- 内核模块支持:
overlay(或overlay2)、br_netfilter、ip_tables等需提前加载; - systemd 服务单元文件:控制启停、日志重定向、资源限制。
提示:若只拷贝
docker命令行二进制,docker run hello-world必然失败——因为dockerd没启动,containerd不在路径中,内核模块未加载。离线安装必须覆盖全链路组件,缺一不可。
2.2 为什么不能用--download-only或apt download?根源在于依赖图的不可控爆炸
以 Ubuntu 22.04 为例,apt download docker-ce docker-ce-cli containerd.io表面只下 3 个 deb,但实际依赖树深度达 5 层:
docker-ce依赖containerd.io (>= 1.6.24);containerd.io依赖libseccomp2 (>= 2.4.0)、libsystemd0;libseccomp2又依赖libc6 (>= 2.34);- 而
libc6是基础库,其版本与系统内核 ABI 强绑定,跨发行版或跨版本apt download下来的.deb在目标机器上dpkg -i会报dependency problems - leaving unconfigured。
更致命的是:apt download不下载systemd单元文件、不生成/etc/docker/daemon.json默认配置、不处理iptables规则初始化。这些缺失项导致即使二进制装上了,systemctl start docker仍会因Failed to load environment files或cgroup driver mismatch失败。
2.3 离线方案的核心设计原则:二进制分发 + 静态依赖 + 配置即代码
我们放弃包管理器的“智能依赖解析”,转而采用工程化交付思路:
- 二进制分发:直接从 download.docker.com 官方仓库按目标架构(amd64/arm64)下载
docker-ce-cli,docker-ce,containerd.io的.deb或.rpm包(非源码),解压提取usr/bin/下所有可执行文件; - 静态依赖:将
libseccomp.so.2,libsystemd.so.0等关键 so 文件,从同版本基础镜像(如ubuntu:22.04)中find /usr/lib -name "lib*.so*"提取,统一放入离线包lib/目录,并通过patchelf --set-rpath '$ORIGIN/../lib'重写二进制动态链接路径; - 配置即代码:提供预校验的
daemon.json(禁用live-restore、显式指定storage-driver: overlay2、设置log-driver: json-file)、docker.servicesystemd 单元(含ExecStartPre=/sbin/modprobe overlay)、以及iptables初始化脚本; - 验证闭环:内置
verify-docker.sh,自动检测dockerd进程、containerdsocket、runc version、docker info输出字段、docker run --rm hello-world执行结果,任一失败即退出并打印定位线索。
这套逻辑不追求“一键全自动”,而追求“每一步都可审计、可回退、可复现”。当你在客户机房面对审计员提问“这个二进制来源是否可信”,你能直接打开sha256sum.txt指向官方 release 页面的 checksum 列表——这才是离线方案真正的底气。
3. 完整离线安装包结构与各组件作用详解
3.1 离线包标准目录树(以docker-offline-v24.0.7-amd64.tar.gz为例)
docker-offline-v24.0.7-amd64/ ├── bin/ # 所有可执行二进制(已 patchelf 重设 rpath) │ ├── dockerd │ ├── docker │ ├── containerd │ ├── containerd-shim │ └── runc ├── lib/ # 静态依赖库(libseccomp.so.2, libsystemd.so.0 等) ├── etc/ │ ├── docker/ │ │ └── daemon.json # 预配置的守护进程参数 │ └── systemd/ │ └── system/ │ └── docker.service # systemd 单元文件(含 modprobe 和 iptables 初始化) ├── scripts/ │ ├── install.sh # 主安装脚本(复制二进制、创建用户、启用服务) │ ├── verify-docker.sh # 验证脚本(检查进程、socket、hello-world) │ └── cleanup.sh # 卸载脚本(停止服务、删除二进制、清理用户) ├── docs/ │ └── README.md # 版本说明、校验方法、已知限制 └── sha256sum.txt # 所有文件的 SHA256 校验值(对应官网 release 页面)注意:该结构刻意避开
/usr/bin路径,全部安装到/opt/docker-offline/bin/,避免与系统包管理器冲突。install.sh会创建符号链接/usr/local/bin/docker→/opt/docker-offline/bin/docker,确保PATH中优先使用离线版。
3.2 关键配置文件深度解析:daemon.json为什么这样写?
{ "data-root": "/var/lib/docker-offline", "storage-driver": "overlay2", "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" }, "live-restore": false, "default-ulimits": { "nofile": { "Name": "nofile", "Hard": 65536, "Soft": 65536 } }, "insecure-registries": ["192.168.100.0/24"], "registry-mirrors": ["https://mirror.example.com"] }"data-root": "/var/lib/docker-offline":强制指定数据目录,避免与可能存在的旧 Docker(如 snap 安装)冲突;"storage-driver": "overlay2":显式声明,防止dockerd启动时因内核模块未加载而 fallback 到vfs(性能极差);"live-restore": false:必须关闭!内网环境无外部监控,开启后systemctl stop docker不会终止容器,导致cleanup.sh卸载时残留进程;"insecure-registries":内网私有仓库地址段,避免证书校验失败;"registry-mirrors":指向内网镜像缓存服务,加速后续docker pull;"default-ulimits":解决常见fork: retry: Resource temporarily unavailable错误,内网机器常因ulimit -n默认 1024 导致容器启动失败。
血泪经验:某次交付中,客户服务器
ulimit -n为 1024,docker run nginx启动后立即exit 1,docker logs显示fork: Cannot allocate memory。排查 3 小时才发现是 ulimit 限制,而非内存不足。从此所有离线包daemon.json必加default-ulimits。
3.3docker.service单元文件的关键预处理逻辑
[Unit] Description=Docker Application Container Engine (Offline) Documentation=https://docs.docker.com After=network-online.target firewalld.service containerd.service Wants=network-online.target Requires=containerd.service [Service] Type=notify EnvironmentFile=-/etc/docker/daemon.env # 关键:预加载 overlay 模块,否则 dockerd 启动失败 ExecStartPre=/sbin/modprobe overlay ExecStartPre=/sbin/modprobe br_netfilter # 关键:初始化 iptables 规则,避免容器网络不通 ExecStartPre=/opt/docker-offline/scripts/iptables-init.sh # 关键:设置 rlimit,匹配 daemon.json 中的 ulimit LimitNOFILE=65536 LimitNPROC=65536 OOMScoreAdjust=-500 ExecStart=/opt/docker-offline/bin/dockerd \ --host=fd:// \ --containerd=/run/containerd/containerd.sock \ --exec-opt native.cgroupdriver=systemd [Install] WantedBy=multi-user.targetExecStartPre=/sbin/modprobe overlay:overlay2存储驱动依赖内核overlay模块,CentOS 7 默认未加载,此行确保模块就绪;ExecStartPre=/opt/docker-offline/scripts/iptables-init.sh:该脚本执行iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER等 5 条规则,打通容器端口映射;LimitNOFILE=65536:与daemon.json中default-ulimits呼应,防止 systemd 对进程的资源限制覆盖 Docker 配置;--exec-opt native.cgroupdriver=systemd:强制使用systemdcgroup 驱动,避免与cgroupfs混用导致docker info显示WARNING: No swap limit support等干扰信息。
提示:
iptables-init.sh脚本末尾会执行iptables-save > /etc/sysconfig/iptables(RHEL/CentOS)或iptables-save > /etc/iptables/rules.v4(Ubuntu),确保重启后规则持久化。这是内网环境“一次配置,永久生效”的关键。
4. 实操步骤:从离线包解压到docker run hello-world成功
4.1 准备工作:确认目标系统兼容性与基础依赖
在目标内网服务器上,先执行以下命令验证基础环境:
# 1. 检查内核版本(Docker CE v24.0.7 要求 Linux kernel >= 3.10) uname -r # 预期输出:5.15.0-86-generic(Ubuntu 22.04)或 3.10.0-1160.el7.x86_64(CentOS 7.9) # 2. 检查 CPU 架构(确保与离线包一致) uname -m # 预期输出:x86_64 或 aarch64 # 3. 检查 cgroup 版本(v24+ 推荐 cgroup v2,但兼容 v1) ls /sys/fs/cgroup/ # 若存在 'cgroup.controllers' 文件,则为 cgroup v2;若只有 'cpu', 'memory' 等子目录,则为 v1 # 4. 检查基础库版本(关键!避免 libseccomp 版本过低) ldd --version | head -1 # 预期:ldd (Ubuntu GLIBC 2.35-0ubuntu3.4) 2.35 seccomp-syscalls -V 2>/dev/null || echo "libseccomp not found" # 若报错,说明 libseccomp 版本 < 2.4.0,需手动升级(见避坑章节)逻辑说明:Docker v24.0.7 编译时链接
libseccomp >= 2.4.0,若目标系统libseccomp.so.2版本为 2.3.3(如 CentOS 7.6 默认),dockerd启动时会报error while loading shared libraries: libseccomp.so.2: cannot open shared object file。此时必须先升级libseccomp,再安装 Docker。
4.2 执行离线安装:四步完成环境搭建
假设离线包已通过 U 盘拷贝至服务器/tmp/docker-offline-v24.0.7-amd64.tar.gz:
# 步骤 1:解压到 /opt 目录(保留原始权限) sudo tar -xzf /tmp/docker-offline-v24.0.7-amd64.tar.gz -C /opt/ # 步骤 2:运行安装脚本(自动处理用户、权限、服务注册) cd /opt/docker-offline-v24.0.7-amd64 sudo ./scripts/install.sh # 步骤 3:启动 Docker 服务 sudo systemctl daemon-reload sudo systemctl enable docker sudo systemctl start docker # 步骤 4:验证安装结果 sudo ./scripts/verify-docker.shinstall.sh脚本核心逻辑(简化版):
#!/bin/bash # 1. 创建 docker 用户组和 docker 用户(避免 root 运行容器) getent group docker >/dev/null || groupadd docker getent passwd docker >/dev/null || useradd -g docker -s /sbin/nologin docker # 2. 复制二进制到 /opt/docker-offline/bin/,并设置权限 mkdir -p /opt/docker-offline/bin cp -f bin/* /opt/docker-offline/bin/ chmod +x /opt/docker-offline/bin/* # 3. 复制配置文件 mkdir -p /etc/docker /etc/systemd/system cp -f etc/docker/daemon.json /etc/docker/ cp -f etc/systemd/system/docker.service /etc/systemd/system/ # 4. 创建符号链接到 /usr/local/bin(确保 PATH 优先) ln -sf /opt/docker-offline/bin/docker /usr/local/bin/docker ln -sf /opt/docker-offline/bin/dockerd /usr/local/bin/dockerd # ... 其他二进制同理 # 5. 设置 /var/lib/docker-offline 目录权限 mkdir -p /var/lib/docker-offline chown root:root /var/lib/docker-offline chmod 700 /var/lib/docker-offline参数说明:
install.sh不做任何网络请求,所有操作基于本地文件。chown root:root是必须的,因为dockerd进程以 root 身份运行,其数据目录必须由 root 拥有,否则启动时报permission denied。
4.3 验证脚本verify-docker.sh的逐层检测逻辑
#!/bin/bash # 1. 检查 dockerd 进程是否存在且 UID 为 root if ! pgrep -u root dockerd > /dev/null; then echo "FAIL: dockerd process not running or not owned by root" exit 1 fi # 2. 检查 containerd socket 是否可访问 if ! sudo /opt/docker-offline/bin/ctr --address /run/containerd/containerd.sock version > /dev/null 2>&1; then echo "FAIL: containerd socket /run/containerd/containerd.sock not accessible" exit 1 fi # 3. 检查 runc 版本(验证二进制完整性) if ! /opt/docker-offline/bin/runc --version | grep -q "runc version"; then echo "FAIL: runc binary broken or missing" exit 1 fi # 4. 检查 docker info 关键字段 if ! docker info 2>/dev/null | grep -q "Storage Driver: overlay2"; then echo "FAIL: Storage Driver not set to overlay2" exit 1 fi # 5. 最终验证:运行 hello-world 镜像(从本地加载,不 pull) if ! docker run --rm hello-world 2>/dev/null | grep -q "Hello from Docker!"; then echo "FAIL: docker run hello-world failed" exit 1 fi echo "SUCCESS: Docker offline installation verified."逻辑说明:该脚本不依赖
docker pull(需要网络),而是利用 Docker 自带的hello-world镜像(docker load时已内置)。docker run --rm hello-world会触发镜像本地加载、容器创建、进程执行、标准输出捕获全流程,是端到端功能验证的黄金标准。
5. 避坑指南:内网离线安装 Docker 的五个高频翻车点与解决方案
5.1 现象:systemctl start docker失败,日志显示Failed to start Docker Application Container Engine (Offline),journalctl -u docker -n 50报overlay: module not found
原因:目标系统内核未编译overlay模块,或模块未加载。常见于定制内核或老旧 CentOS 7。
解决:
- 执行
modprobe overlay,若报modprobe: FATAL: Module overlay not found in directory /lib/modules/$(uname -r),说明内核不支持; - 升级内核至
kernel-3.10.0-1160.el7或更高(CentOS 7.9+),或改用aufs驱动(需额外安装kernel-devel并编译aufs-modules); - 若无法升级内核,在
daemon.json中强制指定"storage-driver": "vfs"(仅限测试,生产禁用,性能极差)。
5.2 现象:docker info显示WARNING: No swap limit support,且容器内存限制失效
原因:内核启动参数未启用cgroup_memory,或swapaccount=1未设置。
解决:
- 编辑
/etc/default/grub,在GRUB_CMDLINE_LINUX行末尾添加cgroup_enable=memory swapaccount=1; - 执行
sudo update-grub && sudo reboot(Ubuntu)或sudo grub2-mkconfig -o /boot/grub2/grub.cfg && sudo reboot(RHEL/CentOS); - 重启后验证:
cat /proc/cmdline | grep -E "cgroup|swapaccount"应输出包含cgroup_enable=memory swapaccount=1。
5.3 现象:docker run -p 8080:80 nginx后,宿主机curl http://localhost:8080返回Connection refused
原因:iptables规则未正确初始化,或firewalld/ufw阻断了端口。
解决:
- 运行
sudo /opt/docker-offline/scripts/iptables-init.sh手动执行规则; - 检查
iptables -t nat -L -n | grep DOCKER,应看到PREROUTING和OUTPUT链中的 DOCKER 规则; - 若使用
firewalld:sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload; - 若使用
ufw:sudo ufw allow 8080。
5.4 现象:docker build过程中报failed to solve: rpc error: code = Unknown desc = failed to compute cache key: failed to walk /var/lib/docker-offline/buildkit/cache: lstat /var/lib/docker-offline/buildkit/cache: permission denied
原因:buildkit目录权限错误,或dockerd未以 root 身份运行。
解决:
- 确认
dockerd进程 UID 为 0:ps aux | grep dockerd | grep -v grep; - 修复目录权限:
sudo chown -R root:root /var/lib/docker-offline/buildkit; - 重启服务:
sudo systemctl restart docker。
5.5 现象:docker-compose安装后执行docker-compose up报ERROR: for service_name Cannot create container for service service_name: invalid mount config for type "bind": bind source path does not exist
原因:docker-compose二进制是 Python 脚本(pip install docker-compose),离线包中若只放了docker-compose二进制,未包含docker-compose-schema.json和docker-composePython 依赖,会导致解析docker-compose.yml失败。
解决:
- 推荐方案:不使用
docker-compose二进制,改用docker compose(Docker v20.10+ 内置插件); - 确保离线包
bin/目录包含docker-compose-plugin(名称为docker-compose的二进制),并创建软链接:ln -sf /opt/docker-offline/bin/docker-compose-plugin /opt/docker-offline/bin/docker-compose; - 验证:
docker compose version应输出Docker Compose version v2.20.2; - 若必须用旧版
docker-compose,需在离线包中加入venv/目录(含完整 Python 环境及docker-compose==1.29.2),并通过./venv/bin/docker-compose调用。
6. 进阶技巧:如何让离线 Docker 环境具备生产级可观测性与热升级能力
6.1 为离线环境注入 Prometheus 监控:零依赖指标采集
内网环境无法拉取prom/node-exporter,但我们可以通过dockerd内置的 metrics 端点暴露指标。关键在于:dockerd默认不开启 metrics,需修改daemon.json:
{ "metrics-addr": "127.0.0.1:9323", "experimental": true }然后启动dockerd后,执行:
# 验证 metrics 端点 curl -s http://127.0.0.1:9323/metrics | head -20 # 输出应包含 # HELP docker_daemon_container_actions_total 等指标 # 将指标持久化到本地文件(供后续离线分析) while true; do curl -s http://127.0.0.1:9323/metrics > /var/log/docker-metrics.prom sleep 15 done &技巧说明:
metrics-addr绑定127.0.0.1而非0.0.0.0,确保指标不暴露给外部网络,符合内网安全策略。/var/log/docker-metrics.prom文件可被离线日志分析工具(如grep、awk)读取,无需额外部署 Prometheus Server。
6.2 构建离线镜像仓库:用registry镜像实现内网镜像分发
虽然不能联网 pull,但我们可以将常用镜像(nginx:alpine,redis:7-alpine,python:3.11-slim)提前docker pull并docker save成 tar 包,再导入内网 registry:
# 在有网机器上准备镜像包 docker pull nginx:alpine docker pull redis:7-alpine docker save nginx:alpine redis:7-alpine > /tmp/offline-images.tar # 在内网服务器上启动 registry(使用离线 registry 镜像) # registry 镜像已包含在离线包中:docker-offline-v24.0.7-amd64/images/registry.tar docker load < /opt/docker-offline-v24.0.7-amd64/images/registry.tar # 启动 registry 容器(数据目录挂载到内网存储) docker run -d \ --restart=always \ --name registry \ -v /opt/registry/data:/var/lib/registry \ -v /opt/registry/auth:/auth \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ -p 5000:5000 \ registry:2 # 将离线镜像包导入 registry docker load < /tmp/offline-images.tar docker tag nginx:alpine localhost:5000/nginx:alpine docker push localhost:5000/nginx:alpine参数说明:
-v /opt/registry/data:/var/lib/registry将 registry 数据持久化到/opt/registry/data,避免容器重启丢失镜像;-e "REGISTRY_AUTH=htpasswd"启用基础认证,/auth/htpasswd文件需提前用htpasswd -Bbn username password > /opt/registry/auth/htpasswd生成。
6.3 热升级 Docker:不重启服务,平滑切换新版本二进制
离线包通常按版本号组织(如v24.0.7),升级时若直接systemctl restart docker,会导致所有容器短暂中断。我们采用dockerd的--live-restore替代方案(注意:此处live-restore与daemon.json中的live-restore不同):
# 步骤 1:下载新版本离线包,解压到新路径 sudo tar -xzf /tmp/docker-offline-v24.0.9-amd64.tar.gz -C /opt/ # 步骤 2:发送 USR1 信号,让当前 dockerd 进程 fork 新进程并 exec 新二进制 sudo kill -USR1 $(pgrep -f "dockerd.*--host=fd://") # 步骤 3:验证新进程已启动(PID 变化) ps aux | grep dockerd | grep -v grep # 步骤 4:验证容器仍在运行 docker ps -q | xargs -r docker inspect --format='{{.Name}} {{.State.Status}}'原理:
dockerd支持USR1信号触发 graceful reload。收到信号后,它会fork()一个子进程,子进程exec()新的dockerd二进制,加载原有配置和状态,父进程等待子进程就绪后退出。整个过程容器不重启,网络连接不中断。这是内网生产环境“零停机升级”的核心技术。
从那以后我每次交付内网 Docker 环境,都会在离线包里固化三样东西:一份verify-docker.sh的完整执行日志模板(填空式,客户签字确认)、一份iptables-init.sh的备份规则快照(iptables-save > /opt/backup/iptables-pre-docker.rules)、以及一张手写的dockerd USR1 升级流程图(贴在机柜侧板上)。不是为了炫技,而是当凌晨两点客户电话打来“容器全挂了”,我能第一时间问出:“您执行kill -USR1之前,有没有先iptables-save?”——这比任何文档都管用。希望帮到你。
本文还有配套的精品资源,点击获取