1. 为什么企业内网需要离线部署Docker?

很多朋友可能觉得,现在云服务这么方便,Docker安装不就是一行 yum install docker-ce 或者 apt-get install docker.io 的事儿吗?这话没错,但那是建立在你的服务器能自由访问互联网的前提下。我这些年跑过不少项目,尤其是在金融、政务、大型制造业这些对安全有极高要求的客户现场,情况就完全不一样了。

他们的生产环境服务器,绝大多数都部署在严格隔离的内网中。什么叫严格隔离?就是物理上拔掉网线,或者通过防火墙策略,彻底断绝了与互联网的连接。这么做的目的很明确:防止外部攻击、杜绝数据泄露、满足合规审计。在这种环境下,你想通过官方仓库在线安装Docker?门儿都没有。所有软件的引入,都必须像“特供品”一样,经过审批、安全检查,然后以离线包的形式带进去。

所以,掌握Docker的离线部署,不是一项炫技,而是很多企业级场景下的硬性生存技能。它意味着你能在“与世隔绝”的环境里,依然能把现代化的容器化技术用起来,享受Docker带来的环境一致性、快速部署和资源隔离的好处。今天,我就把自己在内网环境里摸爬滚打总结出来的一整套实战指南分享给你,从怎么搞到安装包,到怎么安全地搬进去,再到怎么配得既安全又好用。咱们不玩虚的,全是踩过坑之后的干货。

2. 战前准备:规划你的离线部署策略

打无准备之仗,进去就是抓瞎。在动手之前,我们必须把整个链条理清楚。离线部署不是简单下载一个包,它是一套组合拳。

2.1 明确系统环境与版本对齐

第一步,搞清楚目标服务器的“底细”。这直接决定了你该下载哪个版本的Docker二进制包。

# 登录目标服务器,执行以下命令收集关键信息
cat /etc/os-release  # 查看操作系统名称和版本(如 CentOS 7.9, Ubuntu 20.04)
uname -m             # 查看系统架构,必须是 x86_64(amd64)或 aarch64(ARM)
kernel_version=$(uname -r) # 查看内核版本,Docker对内核有最低要求
echo "内核版本: $kernel_version"

这里有个关键点:生产环境追求的是稳定,而不是最新。不要盲目下载最新的Docker版本。我建议,先在你能控制的、与生产环境类似的测试机上,用在线方式安装一个经过验证的稳定版本(比如 Docker CE 20.10.x 或 23.0.x),确认一切正常后,再决定离线部署的版本。版本对齐能避免很多因兼容性导致的灵异事件。

2.2 搭建临时的“搬运工”环境

你需要一台能同时连接互联网和内部网络的“跳板机”或“中转机”。这台机器承担着下载、校验、中转的重任。如果没有物理上的双网卡机器,一个常见的做法是:用一台能上网的办公电脑(Windows/Mac)作为下载机,然后通过严格管控的方式将文件传输到内网。

在这台“搬运工”机器上,我习惯创建一个清晰的工作目录,避免文件混乱:

mkdir -p ~/docker-offline-deploy/{binaries,images,scripts,configs}
cd ~/docker-offline-deploy

binaries 放Docker和docker-compose的安装包,images 放后续需要导入的镜像tar包,scripts 放安装脚本,configs 放服务配置文件。结构清晰,后续部署时才能有条不紊。

3. 核心步骤一:获取与传输离线安装包

这是离线部署的物资准备阶段,每一步都要稳。

3.1 精准下载Docker二进制包

Docker官方很贴心地提供了静态二进制包的下载地址。你需要根据之前查到的系统架构,选择正确的链接。

  • x86_64 (AMD64) 架构https://download.docker.com/linux/static/stable/x86_64/
  • aarch64 (ARM64) 架构https://download.docker.com/linux/static/stable/aarch64/

打开页面后,你会看到一长串版本列表。我以 docker-23.0.6.tgz 这个长期支持版本为例(你可以根据情况选择其他稳定版):

# 在能上网的“搬运工”机器上执行
wget https://download.docker.com/linux/static/stable/x86_64/docker-23.0.6.tgz

重要提示:务必核对文件的完整性。下载完成后,用 sha256sum 校验(如果官网提供了校验文件的话),或者至少用 ls -lh 看一下文件大小是否合理(通常60-100MB左右)。一个损坏的包会让你在内网调试到怀疑人生。

3.2 别忘了docker-compose

现在单机编排几乎离不开docker-compose。它也是一个独立的二进制文件,需要单独下载。 访问 Docker Compose 在GitHub的发布页:https://github.com/docker/compose/releases。找到对应版本(比如 v2.23.3),下载适用于Linux的二进制文件。

# 例如下载 docker-compose-linux-x86_64
wget https://github.com/docker/compose/releases/download/v2.23.3/docker-compose-linux-x86_64

下载后,最好先改好名,方便后续操作:

mv docker-compose-linux-x86_64 docker-compose
chmod +x docker-compose  # 赋予执行权限

3.3 安全跨网传输文件

文件怎么进内网?这是安全部门最关心的一环。严禁使用任何未经授权的移动存储设备。通常企业会有批准的传输通道,常见的有以下几种:

  1. 经审计的专用文件摆渡系统:这是最规范的方式,文件上传下载都有日志记录。
  2. 内部堡垒机/跳板机文件上传功能:通过Web页面或SCP命令,将文件先传到堡垒机,再从堡垒机分发到目标服务器。
  3. 经过审批的加密移动介质:在极端隔离环境下,使用专用的、经过病毒扫描和加密的U盘或光盘。

假设我们通过堡垒机使用SCP命令传输(这是比较通用的方式):

# 从你的“搬运工”机器,将文件传到堡垒机的指定接收目录
scp docker-23.0.6.tgz docker-compose user@bastion-host-ip:/secure-transfer/incoming/
# 然后,由运维人员从堡垒机将文件分发到最终的目标服务器
# 例如,登录目标服务器后,从堡垒机拉取(如果网络可达):
scp user@bastion-host-ip:/secure-transfer/incoming/docker-23.0.6.tgz .

整个传输过程,务必遵循企业的信息安全流程,该报备报备,该登记登记。

4. 核心步骤二:在内网服务器上安装与配置

好了,现在安装包已经躺在了你的内网服务器上。真正的操作开始了。

4.1 解压与部署二进制文件

首先,找个合适的地方放安装包,比如 /opt 目录下。

# 上传后,在目标服务器上操作
cd /opt
tar -xzvf docker-23.0.6.tgz

解压后会得到一个 docker/ 目录,里面包含了 dockerd, docker, containerd 等所有核心可执行文件。我们需要把它们放到系统的 PATH 路径下,通常是 /usr/bin

sudo cp docker/* /usr/bin/

复制完成后,立刻验证一下关键命令是否可用:

ls -l /usr/bin/docker /usr/bin/dockerd /usr/bin/containerd
/usr/bin/docker --version

如果能看到版本信息,说明二进制文件复制成功且本身没有损坏。同样处理 docker-compose

sudo cp /path/to/docker-compose /usr/local/bin/  # 或 /usr/bin/
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

4.2 配置Systemd服务与内核参数

Docker守护进程需要以服务形式运行。我们使用Systemd来管理它,这样可以实现开机自启、日志收集、服务监控。

创建服务单元文件:

sudo tee /etc/systemd/system/docker.service << 'EOF'
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=containerd.service

[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutStartSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process

[Install]
WantedBy=multi-user.target
EOF

这个配置比基础版更健壮,设置了重启策略、资源限制,并明确声明了与 containerd 服务的依赖关系。

接下来是关键一步:配置Docker守护进程选项。通过 /etc/docker/daemon.json 文件,我们可以定义数据根目录、存储驱动、镜像加速器(内网镜像仓库地址)等。在内网环境下,配置一个内部私有镜像仓库地址是重中之重

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json << 'EOF'
{
  "data-root": "/var/lib/docker",
  "storage-driver": "overlay2",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  },
  "insecure-registries": ["192.168.10.100:5000"],
  "registry-mirrors": ["http://192.168.10.100:5000"],
  "live-restore": true
}
EOF

解释一下几个重要参数:

  • insecure-registries: 如果你的内网镜像仓库是HTTP的,需要在这里添加其地址,否则Docker会拒绝连接。
  • registry-mirrors: 将镜像拉取请求重定向到你的内网仓库,加速拉取并完全避免外网访问。
  • live-restore: 允许Docker守护进程重启时,容器继续运行,这对生产环境维护非常友好。

在启动服务前,还需要确保系统内核参数满足Docker要求。编辑 /etc/sysctl.conf,添加或修改以下行:

sudo tee -a /etc/sysctl.conf << 'EOF'
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 使配置生效
sudo sysctl -p

4.3 启动服务与权限配置

现在,启动Docker服务:

sudo systemctl daemon-reload        # 重新加载systemd配置
sudo systemctl start docker         # 启动服务
sudo systemctl enable docker        # 设置开机自启
sudo systemctl status docker        # 检查运行状态

如果状态显示 active (running),恭喜你,Docker服务已经跑起来了。

但默认只有root用户能操作Docker。为了安全和方便,我们需要让特定的运维或开发用户也能使用Docker命令,而不需要每次都 sudo

# 创建docker用户组(如果不存在)
sudo groupadd docker
# 将需要使用的用户(例如‘deploy’)加入docker组
sudo usermod -aG docker deploy

重要:组权限的变更不会立即生效在当前已登录的会话中。用户需要退出当前终端并重新登录,或者新开一个终端,才能让新的组成员身份生效。之后,该用户就可以直接运行 docker ps 等命令了。

5. 核心步骤三:构建内网镜像供应链

Docker装好了,但镜像从哪里来?这是离线环境的核心挑战。我们需要建立一个完整的内网镜像供应链。

5.1 在外网环境准备基础镜像

在你的能上网的开发机或跳板机上,拉取所有需要的镜像。务必记录下每个镜像的完整名称和标签,形成一份清单。

docker pull nginx:1.24-alpine
docker pull mysql:8.0
docker pull redis:7-alpine
docker pull your-app-image:latest

5.2 导出镜像与导入内网

使用 docker save 命令将镜像导出为tar归档文件。我强烈建议使用镜像的完整名称(包含仓库地址)和标签进行导出,这样导入后信息更完整。

docker save -o nginx-1.24-alpine.tar nginx:1.24-alpine
docker save -o mysql-8.0.tar mysql:8.0

将这些 .tar 文件通过之前的安全通道,传输到内网服务器。然后在目标服务器上,使用 docker load 导入:

docker load -i nginx-1.24-alpine.tar
docker load -i mysql-8.0.tar

导入后,运行 docker images 检查,镜像应该都在列表里了。

5.3 搭建私有镜像仓库(长期方案)

对于长期、多团队协作的项目,每次都手动导镜像太低效了。搭建一个内网私有镜像仓库(如Harbor或简单的Docker Registry)是终极解决方案。

这里以部署一个最简单的Docker Registry为例(适用于小团队或初期):

# 在内网一台服务器上操作
# 1. 拉取registry镜像(需先通过上述方式导入)
# 2. 运行registry容器
docker run -d \
  --name registry \
  --restart=always \
  -p 5000:5000 \
  -v /data/registry:/var/lib/registry \
  registry:2

运行后,你的内网私有仓库地址就是 http://<server-ip>:5000。然后,修改所有Docker主机的 daemon.json,将 insecure-registriesregistry-mirrors 指向这个地址。之后,你就可以在外网将镜像 docker tagdocker push 到这个内网仓库,其他内网机器直接 docker pull 即可,实现了内网镜像的集中管理和分发。

6. 企业级加固与故障排查

部署完成不是终点,让它在企业环境里稳定、安全地跑起来才是。

6.1 安全与权限管控配置

企业内网对安全的要求是刻在骨子里的。除了前面提到的用户组权限,还有几点:

  • 配置TLS证书通信:如果Registry和Docker客户端之间通信敏感,应该配置HTTPS,而不是使用 insecure-registries。这需要你提前准备好内部CA签发的证书。
  • 限制容器能力:在运行容器时,使用 --cap-drop 丢弃不必要的Linux能力,使用 --security-opt 限制seccomp和AppArmor策略。
  • 日志与审计:确保Docker的日志驱动(我们前面配置了 json-file)正常工作,并将日志目录纳入企业的日志收集和审计系统(如ELK)中。定期检查 /var/log/messagesjournalctl -u docker.service 查看Docker服务日志。

6.2 常见故障与解决方案

在内网环境,问题通常更隐蔽。这里有几个我常遇到的坑:

  • 服务启动失败,报 iptablescgroup 相关错误:这通常是系统内核版本过低或相关内核模块未加载。检查内核版本是否满足要求(一般3.10以上),并尝试手动加载模块 sudo modprobe overlaysudo modprobe br_netfilter,然后将它们添加到 /etc/modules-load.d/docker.conf 使其开机自动加载。
  • docker pulldocker run 提示 no such hostconnection refused:首先检查 docker info 输出,确认 Registry MirrorsInsecure Registries 配置是否正确。然后使用 curl -v http://<your-registry-ip>:5000/v2/ 测试网络连通性和Registry服务是否正常响应。
  • 非root用户执行 docker ps 报权限错误:确认用户已加入 docker 组,并且已经重新登录。检查 /var/run/docker.sock 的权限:ls -l /var/run/docker.sock,它应该属于 root:docker 且权限为 srw-rw----。如果不是,可以通过 sudo systemctl restart docker 重启服务来重置(注意重启会导致容器停止,生产环境慎用)。
  • 磁盘空间不足:Docker默认将镜像和容器数据存储在 /var/lib/docker。内网服务器往往磁盘规划严格。定期使用 docker system prune -a(谨慎!会删除所有未使用的镜像、容器、网络和卷)或 docker image prune 来清理空间。更好的做法是在 daemon.json 中通过 data-root 配置将其指向一个足够大的独立分区。

最后,我想说,内网离线部署Docker确实比在线安装繁琐不少,但它带来的价值——在安全合规的前提下享受容器化技术的红利——是巨大的。这套流程看起来步骤多,但一旦你跑通一次,形成标准化操作手册和工具包,后续就会非常顺畅。最关键的是理解每个步骤背后的“为什么”,这样遇到新环境或新问题时,你才能灵活应对,而不是机械地照搬命令。希望这份指南能帮你少走些弯路,顺利拿下那些“与世隔绝”的服务器。

更多推荐