
简介这份资源面向需要在无外网环境下部署容器服务的内网运维与开发人员提供一套完整的离线安装方案解决服务器无法访问公网、无法通过 yum 在线拉取 Docker 组件的痛点。压缩包共 22 个文件约 120.91MB以 20 个 rpm 依赖包为主涵盖 docker-ce、docker-ce-cli、containerd.io、container-selinux、fuse-overlayfs、slirp4netns 等核心组件及 python、policycoreutils 等前置依赖另附 1 个 docker-compose-linux-x86_64 二进制文件与 1 个 install.sh 一键安装脚本覆盖从依赖补齐到服务启动的完整链路。已有 4706 人学习下载适合 CentOS 7 环境下快速完成离线部署。读者可直接执行脚本完成安装省去逐条排查依赖版本与顺序的繁琐过程同时借助脚本中的命令逻辑理解各 rpm 包的作用与安装次序为后续容器编排与镜像管理打好基础。1. 内网离线装 Docker为什么你每次都得重装一遍很多做交付的工程师都有过这种经历客户现场是纯内网没有外网出口连个 yum 源都连不上但项目又必须跑在容器里。你带着笔记本进去发现目标机器上 Docker 没装或者版本太老而客户的安全策略不允许你临时开外网。这时候唯一能依赖的就是你提前准备好的离线安装包。这个场景在金融、能源、制造行业的私有化部署里非常普遍。Docker 和 docker-compose 的离线安装本身不复杂但坑特别多依赖包版本对不上、systemd 单元文件路径写错、compose 插件和独立二进制的区别搞混、SELinux 和防火墙在装完之后才出来捣乱。我见过太多人第一次装完以为成功了结果docker run hello-world直接报错又得从头排查。这篇内容面向的是需要在内网环境完成容器运行时部署的工程师不管你是第一次做离线交付还是已经装过几次但总在某个环节翻车下面的步骤和参数说明都可以直接抄作业。整篇会从包的选择开始到二进制安装、systemd 配置、compose 部署再到实际验证和排错把每个环节的边界条件讲清楚。2. 离线包怎么选二进制、rpm 和 deb 的取舍2.1 三种分发形式的适用边界Docker 官方提供的离线安装方式主要有三种静态二进制包、rpm 包、deb 包。选哪种不取决于你习惯用什么而取决于目标机器的发行版和包管理策略。静态二进制包docker-version.tgz是最通用的方式。它不依赖包管理器解压后把二进制文件放到/usr/bin就行。适合目标机器发行版不确定、或者客户不允许你用包管理器改动系统的情况。缺点是 systemd 单元文件要自己写升级也得手动替换二进制。rpm 包适合 CentOS、RHEL、Fedora、Rocky Linux 这类系统。你需要下载containerd.io、docker-ce、docker-ce-cli、docker-compose-plugin这几个包用yum localinstall或rpm -ivh安装。好处是依赖关系由包管理器处理systemd 单元文件自动就位。坑在于版本必须和系统自带的依赖匹配比如containerd.io的版本和docker-ce有对应关系下错了会报依赖冲突。deb 包适合 Ubuntu、Debian 系列逻辑和 rpm 类似用dpkg -i安装。需要注意的是 Ubuntu 不同大版本对 Docker 版本的支持范围不同比如 Ubuntu 18.04 上装太新的 Docker 可能会缺 libc 版本。我一般会优先确认目标机器的发行版和版本号然后去 Docker 官方下载页找对应版本的离线包。如果客户机器是 CentOS 7我会直接下 rpm 包如果是那种定制过的国产化系统静态二进制更稳妥。2.2 下载哪些文件、怎么带进去以静态二进制方式为例你需要准备的文件清单如下文件用途备注docker- .tgzDocker 引擎和 CLI 二进制从官方下载页获取docker-compose-linux-x86_64Compose 独立二进制如果不用插件方式containerd.servicecontainerd 的 systemd 单元二进制包内已含docker.serviceDocker 的 systemd 单元二进制包内已含如果用 rpm 方式需要下载的文件更多# 以 CentOS 7 Docker 24.0.7 为例需要下载以下 rpm 包 containerd.io-1.6.25-3.1.el7.x86_64.rpm docker-ce-24.0.7-1.el7.x86_64.rpm docker-ce-cli-24.0.7-1.el7.x86_64.rpm docker-buildx-plugin-0.11.2-1.el7.x86_64.rpm docker-compose-plugin-2.23.0-1.el7.x86_64.rpm这些包之间有版本对应关系不能随便混搭。docker-ce24.0.7 要求containerd.io不低于 1.6.4docker-compose-plugin的版本也要和 Docker 引擎兼容。我一般会去下载页看同一个发布批次里的文件避免跨版本组合。注意如果目标机器是 aarch64 架构所有包都要换成对应的 aarch64 版本x86_64 的包装不上。把文件带进内网的方式取决于客户的安全策略常见做法是用刻录光盘、加密 U 盘或者通过客户提供的文件摆渡系统。这一步没有技术含量但一定要提前确认文件完整性我习惯在带进去之前先算一遍 sha256进去之后再校验一次。3. 二进制安装全流程从解压到 systemd 拉起3.1 解压、放置二进制和配置 containerd假设你已经把docker-24.0.7.tgz带到了目标机器上接下来的操作按顺序执行。# 解压二进制包 tar -xzvf docker-24.0.7.tgz # 把二进制文件复制到系统路径 sudo cp docker/* /usr/bin/ # 确认关键二进制已就位 which dockerd which docker which containerd which runc解压后docker/目录里包含dockerd、docker、containerd、containerd-shim、runc、ctr、docker-init等文件。全部复制到/usr/bin/之后系统就能找到这些命令了。接下来配置 containerd。containerd 是 Docker 的底层运行时Docker 24 之后默认使用 containerd 来管理容器生命周期。需要生成默认配置文件# 生成 containerd 默认配置 sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml # 修改 cgroup 驱动为 systemd与 Docker 保持一致 sudo sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.tomlSystemdCgroup这个参数非常关键。如果 containerd 用 cgroupfs 而 Docker 用 systemd或者反过来容器启动时会出现资源限制不生效、容器无法正常退出的问题。我一般会强制两边都用 systemd避免玄学问题。3.2 编写 systemd 单元文件并启动服务二进制安装方式不会自动创建 systemd 单元文件需要手动写。先创建 containerd 的sudo tee /etc/systemd/system/containerd.service EOF [Unit] Descriptioncontainerd container runtime Documentationhttps://containerd.io Afternetwork.target local-fs.target [Service] ExecStartPre-/sbin/modprobe overlay ExecStart/usr/bin/containerd Typenotify Delegateyes KillModeprocess Restartalways RestartSec5 LimitNPROCinfinity LimitCOREinfinity LimitNOFILEinfinity TasksMaxinfinity OOMScoreAdjust-999 [Install] WantedBymulti-user.target EOFExecStartPre加载 overlay 内核模块这是 Docker 存储驱动 overlay2 的前提。Delegateyes允许 containerd 管理自己的 cgroup 子树。LimitNOFILEinfinity避免容器多的时候文件描述符不够用。然后创建 Docker 的 systemd 单元sudo tee /etc/systemd/system/docker.service EOF [Unit] DescriptionDocker Application Container Engine Documentationhttps://docs.docker.com Afternetwork-online.target docker.socket firewalld.service containerd.service Wantsnetwork-online.target Requiresdocker.socket containerd.service [Service] Typenotify ExecStart/usr/bin/dockerd -H fd:// --containerd/run/containerd/containerd.sock ExecReload/bin/kill -s HUP $MAINPID TimeoutSec0 RestartSec2 Restartalways StartLimitBurst3 StartLimitInterval60s LimitNOFILEinfinity LimitNPROCinfinity LimitCOREinfinity TasksMaxinfinity Delegateyes KillModeprocess OOMScoreAdjust-500 [Install] WantedBymulti-user.target EOFExecStart里的-H fd://表示通过 systemd socket 激活方式监听--containerd指定 containerd 的 socket 路径。After和Requires确保 containerd 先于 Docker 启动。还需要一个 socket 单元sudo tee /etc/systemd/system/docker.socket EOF [Unit] DescriptionDocker Socket for the API [Socket] ListenStream/var/run/docker.sock SocketMode0660 SocketUserroot SocketGroupdocker [Install] WantedBysockets.target EOF创建 docker 用户组然后把当前用户加进去这样不用 sudo 也能执行 docker 命令sudo groupadd docker 2/dev/null || true sudo usermod -aG docker $USER最后重新加载 systemd 并启动服务sudo systemctl daemon-reload sudo systemctl enable containerd sudo systemctl start containerd sudo systemctl enable docker sudo systemctl start docker启动后检查状态sudo systemctl status containerd sudo systemctl status docker docker version docker infodocker version会分别显示 Client 和 Server 的版本信息如果 Server 部分报错说明 dockerd 没起来需要看journalctl -u docker的日志。4. docker-compose 离线部署独立二进制还是插件4.1 两种形态的区别和选择docker-compose 在 v2 之后有两种使用方式一种是作为 Docker CLI 的插件命令是docker compose中间有空格另一种是独立的二进制文件命令是docker-compose中间有横杠。两者功能基本一致但安装方式和路径不同。插件方式需要把二进制放到~/.docker/cli-plugins/或/usr/local/lib/docker/cli-plugins/目录下Docker CLI 启动时会自动加载。独立二进制方式就是把文件放到/usr/local/bin/docker-compose并赋予执行权限。我一般优先用插件方式因为docker compose是官方推荐的未来形态而且和 Docker CLI 的集成更好。但如果目标机器上的 Docker 版本较老低于 20.10可能不支持插件机制那就只能用独立二进制。4.2 安装步骤和版本对齐插件方式的安装# 创建插件目录 sudo mkdir -p /usr/local/lib/docker/cli-plugins # 复制二进制并赋予执行权限 sudo cp docker-compose-linux-x86_64 /usr/local/lib/docker/cli-plugins/docker-compose sudo chmod x /usr/local/lib/docker/cli-plugins/docker-compose # 验证 docker compose version独立二进制方式的安装sudo cp docker-compose-linux-x86_64 /usr/local/bin/docker-compose sudo chmod x /usr/local/bin/docker-compose docker-compose version版本对齐方面docker-compose v2.23 对应 Docker 24.0 及以上v2.20 对应 Docker 23.0。如果版本差距太大docker compose命令可能无法识别某些 compose 文件语法。我一般会让 compose 的版本和 Docker 引擎的版本保持在同一个发布周期内。注意如果之前装过 python 版的 docker-composev1要先卸载掉否则/usr/local/bin/docker-compose可能被旧版本占用导致命令行为异常。4.3 用 compose 跑一个验证服务装完之后不要只看版本号就结束要实际跑一个多容器服务验证网络和存储是否正常。写一个最简单的 compose 文件# docker-compose-test.yml services: web: image: nginx:alpine ports: - 8080:80 depends_on: - redis redis: image: redis:alpine command: redis-server --appendonly yes volumes: - redis-data:/data volumes: redis-data:这个文件定义了两个服务nginx 和 redis它们在同一个默认网络里web 可以通过服务名redis访问 redis。redis 挂了一个命名卷做持久化。启动命令docker compose -f docker-compose-test.yml up -d启动后验证# 查看服务状态 docker compose -f docker-compose-test.yml ps # 测试 web 是否能访问 redis docker compose -f docker-compose-test.yml exec web ping -c 2 redis # 测试端口映射 curl -s http://localhost:8080 | head -5 # 清理 docker compose -f docker-compose-test.yml down -v如果ping redis能通说明 compose 创建的自定义网络和 DNS 解析正常。如果 curl 返回 nginx 欢迎页说明端口映射正常。down -v会同时删除容器和命名卷避免残留。5. 避坑排查离线安装最常见的五个翻车点5.1 坑一dockerd 启动报错 “failed to start daemon: error initializing graphdriver”现象是systemctl start docker之后状态变成 failedjournalctl -u docker里看到 graphdriver 初始化失败。原因通常是 overlay2 存储驱动不可用。可能是内核模块没加载也可能是文件系统不支持 overlay2比如某些老版本的 ext4 或者 xfs 在 ftype0 的情况下不支持。解决方式是先确认内核模块lsmod | grep overlay modprobe overlay如果模块加载了还是报错检查/var/lib/docker所在文件系统的类型df -T /var/lib/docker xfs_info /var/lib/docker | grep ftype如果是 xfs 且 ftype0需要重新格式化文件系统或者换一个支持 overlay2 的分区。临时方案是在/etc/docker/daemon.json里把存储驱动改成vfs但性能会差很多只适合测试环境。5.2 坑二容器内无法解析 DNS现象是容器能启动但ping外部域名失败或者apt update卡住。原因是宿主机的/etc/resolv.conf里配置的 DNS 服务器在容器网络里不可达或者 Docker 默认的 DNS 配置被覆盖了。解决方式是在/etc/docker/daemon.json里显式指定 DNS{ dns: [223.5.5.5, 114.114.114.114] }改完之后systemctl restart docker。如果内网有自建的 DNS 服务器就填内网地址。注意这个配置会影响所有容器如果某个容器需要不同的 DNS可以在 compose 文件里单独指定。5.3 坑三docker compose 命令找不到插件现象是docker compose version报错 “docker: compose is not a docker command”。原因是插件二进制没有放到正确的目录或者文件名不对。Docker CLI 在/usr/local/lib/docker/cli-plugins/和~/.docker/cli-plugins/里查找插件文件名必须是docker-compose不能是docker-compose-linux-x86_64。解决方式是确认路径和文件名ls -l /usr/local/lib/docker/cli-plugins/ # 应该看到 docker-compose 这个文件且有执行权限如果路径对但还不行检查 Docker CLI 的版本是否支持插件机制。docker version里 Client 版本低于 20.10 的话插件机制可能不生效需要改用独立二进制方式。5.4 坑四SELinux 导致挂载卷权限拒绝现象是容器启动时报 “Permission denied”尤其是挂载了宿主机目录的时候。原因是 SELinux 处于 enforcing 模式容器进程没有权限访问宿主机上的文件。解决方式有两种临时把 SELinux 设为 permissive 模式或者在挂载时加:z或:Z标签volumes: - ./data:/app/data:z:z表示多个容器可以共享这个卷:Z表示私有。如果不想改 compose 文件也可以直接关掉 SELinuxsetenforce 0 # 永久生效需要改 /etc/selinux/config生产环境不建议直接关优先用:z标签解决。5.5 坑五防火墙规则导致容器间通信失败现象是同一台机器上的两个容器无法通过服务名互相访问或者容器无法访问宿主机上的服务。原因是 firewalld 或 iptables 规则拦截了 Docker 创建的网桥流量。Docker 在启动时会自动添加 iptables 规则但如果 firewalld 在 Docker 之后启动可能会覆盖这些规则。解决方式是重启 Docker 让规则重新生效systemctl restart docker或者把 Docker 的网桥接口加入 firewalld 的信任区域firewall-cmd --permanent --zonetrusted --add-interfacedocker0 firewall-cmd --reload如果目标机器用的是 iptables 而不是 firewalld检查iptables -L FORWARD的默认策略是不是 DROP如果是需要改成 ACCEPT 或者添加 Docker 相关的放行规则。6. 验证与固化把离线安装变成可重复的交付流程装完一次不算完交付场景里你需要在多台机器上重复同样的操作。我一般会把整个流程固化成一个脚本包包含二进制文件、systemd 单元、daemon.json 模板和一个安装脚本。安装脚本里做三件事检查架构和发行版、按顺序执行安装步骤、跑一个最小验证。验证环节我习惯用docker run --rm hello-world加上一个 compose 的多容器测试。hello-world 验证引擎基本功能compose 测试验证网络、存储和编排能力。两个都过了才算这次交付的运行时环境是可靠的。还有一个容易忽略的点是 daemon.json 的配置。离线环境里我一般会加上这些参数{ log-driver: json-file, log-opts: { max-size: 50m, max-file: 3 }, storage-driver: overlay2, live-restore: true, default-address-pools: [ { base: 172.30.0.0/16, size: 24 } ] }log-opts限制日志大小避免容器日志把磁盘写满。live-restore让 Docker 守护进程重启时容器继续运行减少升级时的停机时间。default-address-pools自定义容器网络的地址段避免和客户内网已有网段冲突。这个参数在客户内网环境里特别重要我遇到过好几次 Docker 默认的 172.17.0.0/16 和客户内网网段撞了导致容器网络不通。从那以后我每次进内网交付之前都会先问清楚客户的网段规划然后把default-address-pools改成不冲突的地址段再装。这个习惯帮我省了很多事后排查的时间。希望帮到你。本文还有配套的精品资源点击获取