ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

内网服务器离线安装Docker全流程:静态二进制与包管理方案详解

内网服务器离线安装Docker全流程:静态二进制与包管理方案详解 接手过内网服务器的人都知道最麻烦的不是Docker本身而是那台机器压根连不上外网。x86架构、离线安装这两个词凑在一块儿基本就是政务内网、生产隔离区、等保整改这类场景的标配需求。你手边可能只有一台能联网的跳板机目标服务器是干净的CentOS 7.9或者Ubuntu 20.04没有外网、没有可用的yum源这时候想装Docker就得老老实实走离线这一条路。这篇文章把我实际跑过的离线安装流程完整梳理一遍适合刚接触容器化、或者在内网环境里第一次部署Docker的运维和开发同学参考。1. 离线安装之前先搞清楚你要面对什么环境1.1 确认架构和系统版本少走一半弯路很多人一上来就下载安装包结果装到一半发现架构不对或者内核版本太老白折腾一下午。离线安装的第一步永远是确认目标机器的底细。在目标服务器上执行这几条命令uname -m cat /etc/os-release uname -runame -m输出x86_64就代表这是标准的x86 64位架构Docker官方对应的平台名是amd64。如果输出的是aarch64那就是ARM架构安装包完全不同千万别混用。cat /etc/os-release告诉你具体的发行版和版本号。CentOS 7.x、CentOS 8.x、Ubuntu 18.04/20.04/22.04、Debian 10/11这些系统离线安装的路径都不太一样。uname -r看内核版本。Docker对内核有硬性要求CentOS 7的默认内核是3.10跑Docker 20.10.x没压力但如果你非要装最新的Docker 24.x或25.x部分老内核环境就可能遇到存储驱动或cgroup兼容问题。这里我补充一个判断逻辑离线场景下Docker版本不是越新越好而是越稳越好。我一般优先选24.0.x如果目标系统是CentOS 7且内核没升过级就退到20.10.x。下载前先想清楚后面能省掉大量排错时间。1.2 离线安装路线的三种思路怎么选离线安装Docker没有银弹分别有静态二进制、RPM包集合、DEB包集合三种主流方案。它们之间的关系说简单点就是静态二进制像绿色软件解压就能跑RPM/DEB像正规安装包需要系统包管理器接管。方案适用系统优点缺点静态二进制tar包几乎所有Linux发行版不依赖软件源、不依赖包管理器、兼容性好升级靠手动换二进制RPM包集合离线安装RHEL/CentOS/Fedora系和系统原生机制结合systemd服务自动配好依赖关系复杂下载时容易漏包DEB包集合离线安装Ubuntu/Debian系安装简单依赖管理清晰同样存在依赖收集麻烦的问题Docker Desktop仅限桌面环境图形化操作适合开发不适合服务器依赖WSL2和虚拟化支持我个人的标准是服务器上优先静态二进制因为它对环境的影响最小。内部测试开发用的桌面机、笔记本才考虑Docker Desktop。后面两个章节我会把静态二进制方案和包管理方案的完整操作都写出来。2. 静态二进制包方式最通用、最可控的离线安装手段2.1 为什么我推荐静态二进制方案离线安装的核心矛盾是没网怎么拿到依赖。RPM和DEB方案需要依赖系统自带的软件源结构而静态二进制包把Docker运行所需的所有组件都打在了同一个压缩包里包括dockerd、docker、containerd、runc、docker-init、docker-proxy。这些二进制基本不依赖特定发行版只要Linux内核满足要求就能跑。这个方案还有个额外的好处你不需要在目标机器上执行任何yum install或者apt install不会污染系统自带的软件环境。对于那种生产服务器绝不能乱动系统包的场景静态二进制包是保存底线的最优解。2.2 完整操作流程从下载到启动第一步在一台能联网的机器上去Docker官方静态包下载页https://download.docker.com/linux/static/stable/x86_64/找到类似docker-24.0.9.tgz的文件下载。这一个压缩包就包含了全部运行组件不需要额外找别的依赖。上传到目标服务器后解压并把二进制文件放到系统路径tar xzf docker-24.0.9.tgz cp docker/* /usr/bin//usr/bin、/usr/local/bin都可以关键是后面写systemd服务时要对应上实际路径。第二步准备daemon.json配置文件。这是Docker守护进程的全局配置强烈建议启动前先写好{ data-root: /data/docker, storage-driver: overlay2, exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, iptables: true, ipv6: false }简单解释一下每个配置的含义>[Unit] DescriptionDocker Application Container Engine Documentationhttps://docs.docker.com Afternetwork-online.target firewalld.service Wantsnetwork-online.target [Service] Typenotify ExecStart/usr/bin/dockerd ExecReload/bin/kill -s HUP $MAINPID LimitNOFILEinfinity LimitNPROCinfinity TimeoutStartSec0 Delegateyes Restartalways RestartSec2s [Install] WantedBymulti-user.target这个配置里几个容易看漏的点我要提醒一下Typenotify不能随便改成simpledockerd启动完成会通过sd_notify通知systemd改成simple会导致systemctl迟迟不显示active状态。Delegateyes让systemd把cgroup的管理权下放给Docker这是容器运行时正常工作的前提。Restartalways保证机器重启或者dockerd意外崩溃后自动拉起。LimitNOFILEinfinity防止高并发场景下文件描述符不够用。配置写好以后依次执行mkdir -p /etc/docker /data/docker cp daemon.json /etc/docker/daemon.json systemctl daemon-reload systemctl enable docker systemctl start docker启动后立刻验证状态systemctl status docker docker version docker infodocker version分为Client和Server两段只有当Server段也正常显示版本号才说明守护进程真正跑起来了。docker info可以看到存储驱动、cgroup驱动、数据目录这些关键信息确认和daemon.json里的配置一致。2.3 生命周期管理升级和卸载的坑静态二进制方案有个隐藏问题Docker的systemd配置文件是手写的升级时如果只替换了二进制配置还留在原位这倒不是大问题。真正需要注意的是升级前先systemctl stop docker备份/etc/docker/daemon.json再替换二进制最后systemctl start docker。卸载时更简单把/usr/bin下的相关二进制移除再删除/etc/systemd/system/docker.service和/etc/docker、数据目录。整个过程不会像rpm卸载那样触发一大堆依赖检查。这种完全可预期的控制感是静态包方案最大的魅力。3. 包管理器路线的离线方案适合批量管理环境3.1 CentOS/RHELRPM包集合的收集与安装静态二进制虽然好但有些运维团队的管理规范要求所有软件都必须走rpm包管理审计时能查到安装了哪些包。这种环境就走RPM离线安装。收集RPM包的办法很简单。在一台能联网、且系统版本和目标机器一致的CentOS机器上先配置好Docker的官方yum源然后用yumdownloader把Docker相关包和所有依赖全部下载下来yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo mkdir -p /root/docker-rpm yum install --downloadonly --downloaddir/root/docker-rpm docker-ce docker-ce-cli containerd.io docker-compose-plugin--downloadonly会把包和依赖全部落到指定目录不会真正安装。我见过很多人用yumdownloader docker-ce只下载了一个主包拷到内网一安装报告缺一堆依赖就是因为漏掉了--resolve参数或者没有用--downloadonly模式。把/root/docker-rpm整个目录打包传到目标机器后执行yum localinstall -y /root/docker-rpm/*.rpmyum localinstall会自动根据本地rpm文件解析依赖顺序比直接rpm -ivh *.rpm靠谱得多。直接rpm命令遇到依赖顺序不对就会中断用localinstall就没这个问题。装完以后同样准备好/etc/docker/daemon.json然后启用服务systemctl enable --now dockerRPM方案的好处是systemd服务文件由包管理器自动写好不需要手动创建服务名和参数都是官方默认的。坏处也明显如果目标机器的内核小版本和收集rpm时那台机器差异过大内核模块不匹配dockerd启动时依然可能报存储驱动错误。3.2 Ubuntu/DebianDEB包集合的收集与安装Debian系离线安装的思路和RPM大同小异收集DEB包用apt-get downloadapt-get install -y apt-utils apt-get update mkdir -p /root/docker-deb cd /root/docker-deb apt-get download docker-ce docker-ce-cli containerd.io docker-compose-plugin这里有个注意点apt-get download只会下载你明确指定的包不会自动带依赖。所以你需要先用apt-cache depends docker-ce查看依赖列表再逐个下载。更省事的做法是用apt-get install --download-only先把包列表装到缓存目录再把缓存拷走apt-get install -y --download-only docker-ce docker-ce-cli containerd.io cp /var/cache/apt/archives/*.deb /root/docker-deb/目标机器上执行安装dpkg -i /root/docker-deb/*.deb如果中途报依赖缺失再配合apt-get -f install或者直接下载缺失的DEB包。Debian系的依赖关系比RPM清晰正常情况下不会有太多坑。3.3 包管理方案里的隐藏雷区RPM方案最常见的坑是系统已经装了老版本Docker或Podman导致包冲突。我在CentOS 8上遇到过containerd.io和系统自带podman冲突解决办法是先卸载冲突包再安装Docker相关RPM。DEB方案则容易卡在docker-ce-rootless-extras这类扩展包上它依赖uidmap。如果离线环境连这个依赖也没装就必须从系统安装镜像里找到uidmap对应的DEB包一起带上。别问我为什么知道问就是踩过。4. 离线环境下的镜像管理装上Docker只是开始4.1 用 docker save / load 把镜像搬进内网Docker装好了但内网没有外网你照样拉不了nginx、mysql。这时候需要在联网的机器上先把镜像准备好再通过离线导入的方式塞进目标机器。标准操作是这样在一台能联网的Docker主机上拉取你需要的镜像docker pull nginx:1.25 docker pull mysql:8.0 docker pull redis:7.0然后逐个导出为tar文件docker save -o nginx-1.25.tar nginx:1.25 docker save -o mysql-8.0.tar mysql:8.0导出之后建议用gzip压缩一下镜像文件传输能小不少gzip nginx-1.25.tar mysql-8.0.tar把压缩后的tar.gz文件通过U盘、FTP、内网共享等方式拷到目标服务器执行docker load -i nginx-1.25.tar.gz docker load mysql-8.0.tar.gzdocker load支持直接读取gzip压缩包不需要先解压。加载完用docker images确认镜像已经进入本地镜像库。这里要强调一个选型问题备份镜像必须用docker save这个命令保留完整的镜像历史和分层结构加载出来可以正常启动容器、打标签。千万不要用docker export它导出的是运行中容器打包的文件系统丢掉了镜像本身的分层和元数据导出来的文件以后再想要新容器跑起来会非常别扭。4.2 批量导入脚本一台服务器几十个镜像也压得住内网环境往往不止要部署一两个镜像。我维护了一套最简单的批量导入脚本直接分享给你#!/bin/bash # 批量导入离线镜像 IMPORT_DIR/data/docker-images cd $IMPORT_DIR || exit 1 for img in $(ls *.tar.gz 2/dev/null); do echo 正在导入 $img ... docker load -i $img done echo 全部镜像导入完成 docker images这个脚本看起来简单实际使用中帮我节省了大量时间。一次性拷60个镜像压缩包执行一次脚本全进本地镜像库每台新服务器部署环境的时间从半天缩到了半小时以内。4.3 要不要搭一个内网镜像仓库如果维护的机器数量比较多每台机器都load一遍镜像不现实。更合理的做法是在内网找一台服务器搭Harbor或者registry把镜像推到私有仓库其他机器从内网仓库拉取。离线场景下Harbor本身的安装也需要走离线包它有官方预编译的离线安装包。如果只是想快速解决内网拉镜像的问题部署一个轻量的registry:2就够用了docker run -d --name registry \ -p 5000:5000 \ -v /data/registry:/var/lib/registry \ --restartalways \ registry:2然后把镜像推送到内网registrydocker tag nginx:1.25 172.16.100.10:5000/nginx:1.25 docker push 172.16.100.10:5000/nginx:1.25其余机器上只要修改daemon.json把私有仓库地址加入insecure-registries{ insecure-registries: [172.16.100.10:5000] }重启Docker后就能直接从内网仓库pull镜像不需要二次导入。这个方案做一次后面每加一台机器都是几分钟的事。你在离线Clinet环境导入SQL数据库镜像、Nginx、Redis主从方案时走的就是这条路——先在外网机器上docker pull再src内网load或者推入registry。完全绕开了外网限制的问题。5. 常见问题与排查每一项都是我摔过的坑5.1 dockerd启动失败错误信息千奇百怪报错一Error starting daemon: Error initializing network controller: error creating default bridge network这个错误基本可以断定是iptables相关的模块没加载或者规则错误。先执行modprobe br_netfilter systemctl restart docker依然不行就检查系统的iptables服务是否开了防火墙规则冲突。确认一下内核网络参数sysctl -w net.bridge.bridge-nf-call-iptables1 sysctl -w net.ipv4.ip_forward1然后/etc/sysctl.conf里持久化这些参数重启生效。报错二failed to start daemon: error while loading shared libraries静态包方案下出现这种错误通常是二进制文件没有移动到位或者执行权限丢失。不常见但遇到过。检查/usr/bin/dockerd是否存在、是否有x权限。如果权限没问题就执行ldd /usr/bin/dockerd | grep not found看是否有系统库缺失。静态包按道理是全静态编译的出现这种问题大概率是下载的包和你系统架构不匹配。报错三overlay2 is not supported老内核上常见的坑。内核低于3.10或者文件系统不支持d_type比如某些网络存储挂载的目录overlay2就用不了。要么升级内核要么在daemon.json里临时把存储驱动改成vfs。我真的不建议直接改vfs它性能很差、磁盘占用高只能作为临时逃生通道。报错四Docker Desktop场景下的虚拟化错误如果你用的是Windows桌面机装Docker Desktop启动报错提示virtualization support not detected先检查主板BIOS里的VT-x/AMD-V是否开启再确认Windows的Hyper-V和WSL2这两个功能是否启用。服务器场景不推荐Docker Desktop但开发人员的办公电脑上这个错见过很多次。5.2 SELinux、防火墙、数据目录权限CentOS环境还有一个绕不开的东西SELinux。如果你的系统开启了SELinux且没有为Docker配置对应策略容器很可能无法读取挂载的目录。快速验证方式是getenforce如果输出Enforcing要么执行setenforce 0临时关闭要么正确配置SELinux策略。生产环境我不建议直接关SELinux但很多内网环境为了省事确实会设置成permissive。这是审计时要自己权衡的问题。防火墙方面如果宿主机开了firewalld你需要放行Docker需要的端口。最省事但安全要求高的做法是把Docker的数据面接口docker0加入信任区域或者干脆只在防火墙里按具体应用端口放行。离线场景中很多人装完Docker发现容器跑起来了但外面访问不了八成都是防火墙拦了端口。数据目录权限的报错信息类似这样/var/lib/docker exists with symbolic link或者permission denied。简单检查一下目录所属用户和权限ls -ld /data/docker chmod 711 /data/docker大多数情况下Docker数据目录只要所有者为root即可不需要额外授权普通用户。5.3 常用问题速查表现象可能原因处理方式启动报 iptables chain 错误br_netfilter模块未加载modprobe br_netfilter并持久化老内核报 overlay2不支持内核版本过低升级内核或临时用vfs容器无网络ip_forward未开启sysctl -w net.ipv4.ip_forward1普通用户执行docker命令报权限不足用户不在docker组usermod -aG docker $USER后重登加载tar后docker images为空误用了docker import改用docker load -i内网pull镜像报证书错误私有仓库未加入insecure-registries修改daemon.json后重启docker普通用户执行docker命令这个点值得多看两眼因为静态包方式不会自动创建docker用户组。建议初始化时手动建一下groupadd docker usermod -aG docker yourname不建这个组每次都得sudo执行docker命令很影响效率而且脚本化部署时容易出权限错。5.4 离线环境的长期维护建议Docker装完、镜像导完不等于万事大吉。离线环境的运维重点在未来怎么更新。我的经验是维护一个联网仓库机在这台机器上定期拉取所需镜像的最新版本同步更新内网registry再批量推到生产服务器。如果部署的是国产化系统比如OpenHarmony系x86桌面版、麒麟等基于Linux内核的发行版静态二进制方案同样适用只要内核够新、有overlayfs支持Docker跑起来没有问题。这类环境有时候反而更依赖离线方案因为软件源本身就不完整。最后再分享一个小技巧所有离线部署相关的包、脚本、配置文件统一放在一个/data/deploy目录里写好版本号和日期打包归档。网络正常时多花五分钟整理遇到大批量部署时就知道这个习惯能省多少时间。我在几十台x86服务器上重复这套流程最大的体会就是离线安装Docker本身不复杂真正可贵的是把整个流程标准化、可重复化让任何一台空机器都能在半小时内变成可用的容器节点。
返回列表