1. 为什么需要离线部署Docker?

在企业生产环境中,我们经常会遇到一些特殊的网络限制场景。比如某些金融、军工类企业的内网完全与互联网隔离,或者一些实验室环境出于安全考虑禁止连接外网。这时候如果还想用Docker来部署应用,传统的在线安装方式就行不通了。

我去年给一家制造企业做容器化改造时就遇到过这种情况。他们的生产线控制系统运行在一个完全封闭的网络环境中,连最基本的yum源都没有。当时为了部署Docker,我不得不先在外网环境准备好所有依赖包,然后用U盘一个个拷进去。这个过程虽然麻烦,但确实解决了实际问题。

离线部署Docker主要有以下优势:

  • 安全性高:不需要连接外网,杜绝了潜在的网络攻击风险
  • 稳定性强:所有依赖包都是预先准备好的,不会出现安装中途下载失败的情况
  • 版本可控:可以精确控制每个组件的版本,避免自动升级带来的兼容性问题
  • 批量部署:一次准备可以重复使用,特别适合大规模集群环境

2. 准备工作:获取离线安装包

2.1 下载Docker二进制包

首先需要在一个能联网的机器上下载Docker的离线安装包。推荐直接从官方仓库获取最新稳定版:

# 下载Docker二进制包
wget https://download.docker.com/linux/static/stable/x86_64/docker-20.10.9.tgz

# 下载Docker Compose二进制文件
wget https://github.com/docker/compose/releases/download/v2.3.3/docker-compose-linux-x86_64

这里有个小技巧:我习惯把下载的文件按照版本号重命名,比如docker-20.10.9.tgzdocker-compose-v2.3.3,这样后期维护时一目了然。

2.2 检查系统依赖

在开始安装前,建议先检查目标机器是否满足基本要求:

  • 64位Linux系统(内核3.10以上)
  • iptables版本1.4+
  • device-mapper工具(如果使用devicemapper存储驱动)
  • systemd(用于服务管理)

可以用以下命令快速检查:

# 检查内核版本
uname -r

# 检查iptables版本
iptables --version

# 检查device-mapper
lsmod | grep dm_mod

3. 详细安装步骤

3.1 Docker安装与配置

把下载好的Docker包复制到目标机器后,按以下步骤操作:

# 解压安装包
tar xvf docker-20.10.9.tgz

# 复制二进制文件到系统目录
sudo cp -r docker/* /usr/bin/

# 创建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
Wants=network-online.target

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

[Install]
WantedBy=multi-user.target
EOF

# 设置权限并启动服务
sudo chmod +x /etc/systemd/system/docker.service
sudo systemctl daemon-reload
sudo systemctl enable docker
sudo systemctl start docker

# 验证安装
docker --version
sudo docker run hello-world

这里有个容易踩的坑:如果系统使用了代理,需要额外配置Docker的代理设置。可以在/etc/systemd/system/docker.service.d/http-proxy.conf文件中添加:

[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080"
Environment="HTTPS_PROXY=http://proxy.example.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"

3.2 Docker Compose安装

Docker Compose的安装相对简单:

# 复制二进制文件并设置权限
sudo cp docker-compose-linux-x86_64 /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# 验证安装
docker-compose --version

为了使用更方便,我通常会创建一个符号链接:

sudo ln -s /usr/local/bin/docker-compose /usr/bin/dc

这样以后就可以直接用dc命令代替docker-compose了。

4. 高级配置与优化

4.1 配置镜像加速器

在内网环境中,我们可以搭建自己的镜像仓库作为加速器。假设已经在内网部署了Harbor仓库,可以这样配置:

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": ["https://harbor.yourcompany.com"],
  "insecure-registries": ["harbor.yourcompany.com"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}
EOF

sudo systemctl restart docker

4.2 存储驱动选择

根据不同的使用场景,可以选择合适的存储驱动。对于生产环境,我推荐使用overlay2

# 检查当前存储驱动
docker info | grep "Storage Driver"

# 修改存储驱动
sudo tee /etc/docker/daemon.json <<EOF
{
  "storage-driver": "overlay2"
}
EOF

4.3 资源限制配置

为了防止容器占用过多系统资源,可以设置默认的资源限制:

sudo tee /etc/docker/daemon.json <<EOF
{
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65535,
      "Soft": 65535
    }
  },
  "default-runtime": "runc"
}
EOF

5. 一键安装脚本

为了简化部署过程,我整理了一个完整的一键安装脚本:

#!/bin/bash
set -e

echo "===== Docker离线安装脚本 ====="

# 定义版本变量
DOCKER_VERSION="20.10.9"
COMPOSE_VERSION="v2.3.3"

# 检查root权限
if [ "$(id -u)" != "0" ]; then
   echo "错误:请使用root用户执行此脚本" 1>&2
   exit 1
fi

# 安装Docker
echo "正在安装Docker..."
tar xvf docker-${DOCKER_VERSION}.tgz
cp -r docker/* /usr/bin/
rm -rf docker

# 配置服务
cat > /etc/systemd/system/docker.service <<EOF
[Unit]
Description=Docker Application Container Engine
After=network-online.target firewalld.service
Wants=network-online.target

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

[Install]
WantedBy=multi-user.target
EOF

chmod +x /etc/systemd/system/docker.service
systemctl daemon-reload
systemctl enable docker
systemctl start docker

# 验证Docker
if ! docker --version; then
    echo "Docker安装失败"
    exit 1
fi
echo "Docker安装成功"

# 安装Docker Compose
echo "正在安装Docker Compose..."
cp docker-compose-linux-x86_64 /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/dc

# 验证Compose
if ! docker-compose --version; then
    echo "Docker Compose安装失败"
    exit 1
fi
echo "Docker Compose安装成功"

echo "===== 安装完成 ====="

这个脚本包含了完整的安装流程和错误检查,使用时只需要把安装包和脚本放在同一目录下执行即可。

6. 常见问题排查

6.1 服务启动失败

如果遇到Docker服务启动失败,可以按以下步骤排查:

# 查看详细日志
journalctl -u docker.service -n 50 --no-pager

# 手动运行dockerd查看输出
/usr/bin/dockerd --debug

常见问题包括:

  • 端口冲突(特别是2375/2376)
  • 存储驱动配置错误
  • 内核模块缺失

6.2 镜像导入导出

在内网环境中,镜像需要先在外网下载再导入:

# 在外网机器下载镜像
docker pull nginx:alpine
docker save -o nginx-alpine.tar nginx:alpine

# 在内网机器导入镜像
docker load -i nginx-alpine.tar

6.3 网络配置

如果容器需要访问内网特定服务,可以自定义网络:

# 创建自定义网络
docker network create --subnet=172.18.0.0/16 mynet

# 运行容器时指定网络
docker run --net mynet --ip 172.18.0.100 -d nginx

7. 维护与升级

7.1 版本升级

离线环境升级需要手动下载新版本包:

# 停止旧版本服务
systemctl stop docker

# 备份配置
cp -r /etc/docker /etc/docker.bak

# 安装新版本
tar xvf docker-new-version.tgz
cp -r docker/* /usr/bin/

# 重启服务
systemctl start docker

7.2 数据备份

定期备份Docker数据很重要:

# 备份镜像
docker save -o all-images.tar $(docker images -q)

# 备份卷数据
tar czvf docker-volumes.tar.gz /var/lib/docker/volumes/

在实际项目中,我建议把这些维护操作写成定时任务,确保数据安全。

更多推荐