核心思路
离线部署的核心是提前本地化所有依赖资源(系统 deb 包、Python 库、nltk/tiktoken 数据、基础镜像),通过 Docker 多阶段构建理念适配离线场景,将所有资源打包进镜像,彻底摆脱外网依赖。整体流程分为「离线资源准备」「Dockerfile 适配」「镜像构建」「离线部署」四大步骤,确保部署过程零网络请求。
一、离线资源准备(联网环境执行)
在有网络的机器上完成所有依赖资源的下载与打包,最终生成 offline-resources.tar.gz 离线资源包,传输至无网络虚拟机。
1.1 目录结构规划(提前创建)
plaintext
dify-offline-build/
├── resources/
│ ├── base-image/ # 基础镜像存储目录
│ ├── debs/ # 系统deb包存储目录
│ └── data/ # 离线数据(nltk/tiktoken)
│ ├── nltk_data/
│ └── tiktoken_cache/
├── docker_requirements_final/ # Python离线依赖包
├── download-debs.sh # deb包下载脚本
├── pyproject.toml # Dify API源码中的依赖声明文件
├── uv.lock # Dify API源码中的依赖锁文件
└── requirements.txt # 导出的Python依赖清单
1.2 下载基础镜像
bash
运行
# 拉取基础镜像
docker pull python:3.12-slim-bookworm
# 保存镜像为tar包(后续导入离线环境)
mkdir -p resources/base-image
docker save -o resources/base-image/python-3.12-slim-bookworm.tar python:3.12-slim-bookworm
1.3 下载系统 deb 包(编译 / 运行依赖)
创建并执行 deb 包下载脚本,通过 Docker 容器下载所需系统依赖:
bash
运行
# 创建下载脚本
cat > download-debs.sh << 'EOF'
#!/bin/bash
set -e
# 确保deb存储目录存在
mkdir -p resources/debs && cd resources/debs
# 通过Python基础镜像下载deb包(使用阿里云源加速)
docker run --rm -v $(pwd):/tmp/debs python:3.12-slim-bookworm bash -c "
sed -i 's@deb.debian.org@mirrors.aliyun.com@g' /etc/apt/sources.list.d/debian.sources && \
apt-get update && \
apt-get install -y --download-only \
gcc g++ libc-dev libffi-dev libgmp-dev libmpfr-dev libmpc-dev \
curl nodejs libgmp-dev libmpfr-dev libmpc-dev \
expat libldap-2.5-0 perl libsqlite3-0 zlib1g \
fonts-noto-cjk media-types libmagic1 && \
cp /var/cache/apt/archives/*.deb /tmp/debs/
"
# 打包deb包(便于离线传输)
tar -czf debs.tar.gz ./*.deb
echo "✅ deb包下载完成,已打包为 debs.tar.gz"
EOF
# 赋予执行权限并运行
chmod +x download-debs.sh && ./download-debs.sh
1.4 下载 Python 依赖(项目核心依赖)
基于 Dify API 源码的依赖声明,下载所有 Python 包至离线目录:
bash
运行
# 1. 创建干净的Python虚拟环境
python -m venv .venv
source .venv/bin/activate
# 2. 安装依赖管理工具uv(与原版Dockerfile一致)
pip install uv
# 3. 生成依赖锁文件(若源码中无uv.lock,需执行此步)
uv lock
# 4. 导出依赖清单(不含开发依赖)
uv export --locked > requirements.txt
# 5. 下载所有Python依赖到离线目录
mkdir -p docker_requirements_final
pip download -r requirements.txt -d docker_requirements_final
echo "✅ Python依赖下载完成,共 $(ls docker_requirements_final | wc -l) 个包"
1.5 下载离线数据(nltk/tiktoken)
bash
运行
# 创建数据存储目录
mkdir -p resources/data/nltk_data resources/data/tiktoken_cache
# 下载nltk分词数据(通过Python脚本下载)
cat > download-nltk-data.py << 'EOF'
import nltk
nltk.download('punkt', download_dir='/tmp/nltk_data')
nltk.download('averaged_perceptron_tagger', download_dir='/tmp/nltk_data')
nltk.download('wordnet', download_dir='/tmp/nltk_data')
EOF
# 执行脚本并复制到资源目录
python download-nltk-data.py
cp -r /tmp/nltk_data/* resources/data/nltk_data/
# 下载tiktoken编码缓存(以gpt2为例,根据实际需求补充)
cat > download-tiktoken-cache.py << 'EOF'
import tiktoken
tokenizer = tiktoken.get_encoding("gpt2")
# 触发缓存下载
tokenizer.encode("test")
EOF
python download-tiktoken-cache.py
# 复制缓存文件(不同系统路径可能不同,需自行调整)
cp -r ~/.cache/tiktoken/* resources/data/tiktoken_cache/
echo "✅ 离线数据下载完成"
1.6 打包离线资源
将所有下载的资源打包,便于传输至无网络虚拟机:
bash
运行
tar -czf offline-resources.tar.gz resources/ docker_requirements_final/ requirements.txt pyproject.toml uv.lock
echo "✅ 所有离线资源打包完成:offline-resources.tar.gz"
二、离线环境准备(无网络虚拟机执行)
2.1 传输并解压离线资源
将 offline-resources.tar.gz 传输至无网络虚拟机的 /home/Documents/dify-offline-build/ 目录,执行解压:
bash
运行
# 创建工作目录
mkdir -p /home/Documents/dify-offline-build
cd /home/Documents/dify-offline-build
# 解压资源包
tar -xzf offline-resources.tar.gz
echo "✅ 离线资源解压完成"
2.2 导入基础镜像
bash
运行
# 导入Python基础镜像
docker load -i resources/base-image/python-3.12-slim-bookworm.tar
# 验证镜像导入成功
docker images | grep python:3.12-slim-bookworm
echo "✅ 基础镜像导入完成"
2.3 准备 Dify API 源码
将 Dify 1.8.1 源码的 api 目录复制至当前工作目录(确保包含 app.py、entrypoint.sh 等核心文件):
bash
运行
# 假设源码已传输至虚拟机,复制API目录
cp -r /home/Documents/dify/dify1.8.1/api/* /home/Documents/dify-offline-build/
echo "✅ Dify API源码准备完成"
三、编写离线 Dockerfile(Dockerfile.offline)
在 /home/Documents/dify-offline-build/ 目录创建 Dockerfile.offline,内容如下:
dockerfile
FROM python:3.12-slim-bookworm
# 环境变量配置
ENV LC_ALL=C.UTF-8
ENV DEBIAN_FRONTEND=noninteractive
ENV PYTHONUNBUFFERED=1
ENV DIFY_PROFILE=prod
ENV NLTK_DATA=/app/api/nltk_data
ENV TIKTOKEN_CACHE_DIR=/app/api/tiktoken_cache
# 设置工作目录
WORKDIR /app/api
# ---------------------------
# 步骤1:安装离线deb包(系统依赖)
# ---------------------------
COPY ./resources/debs/debs.tar.gz /tmp/
RUN mkdir -p /tmp/debs && \
tar -xzf /tmp/debs.tar.gz -C /tmp/debs && \
# 安装deb包,自动解决依赖冲突
dpkg -i /tmp/debs/*.deb || apt -f install -y --no-install-recommends && \
# 清理缓存,减小镜像体积
rm -rf /tmp/debs /tmp/debs.tar.gz /var/lib/apt/lists/*
# ---------------------------
# 步骤2:安装离线Python依赖
# ---------------------------
COPY ./docker_requirements_final /tmp/packages
COPY ./requirements.txt /tmp/
RUN python -m pip install --no-index --find-links=/tmp/packages /tmp/packages/* && \
# 清理离线包
rm -rf /tmp/packages /tmp/requirements.txt && \
# 验证依赖安装
pip list | grep -E "flask|celery|docker" || echo "⚠️ 部分核心依赖未安装"
# ---------------------------
# 步骤3:复制离线数据(nltk/tiktoken)
# ---------------------------
COPY ./resources/data/nltk_data /app/api/nltk_data
COPY ./resources/data/tiktoken_cache /app/api/tiktoken_cache
RUN chmod -R 755 /app/api/nltk_data /app/api/tiktoken_cache
# ---------------------------
# 步骤4:复制项目源码
# ---------------------------
COPY . /app/api
RUN chmod +x /app/api/entrypoint.sh
# ---------------------------
# 步骤5:暴露端口并设置启动命令
# ---------------------------
EXPOSE 5001
CMD ["sh", "/app/api/entrypoint.sh"]
四、构建离线镜像
在 /home/Documents/dify-offline-build/ 目录执行镜像构建命令:
bash
运行
# 无缓存构建,确保资源加载最新
docker build --no-cache -f Dockerfile.offline -t dify-api:1.8.1-offline .
# 验证镜像构建成功
docker images | grep dify-api:1.8.1-offline
echo "✅ Dify API离线镜像构建完成"
五、离线部署 Dify 服务
5.1 修改 docker-compose.yml
进入 Dify 的 Docker Compose 配置目录,修改 API 服务的镜像名称为离线构建的镜像:
bash
运行
cd /home/Documents/dify/dify1.8.1/dify/docker
sudo nano docker-compose.yml
修改核心配置(仅展示 API 服务部分,其他服务配置保持不变):
yaml
services:
api:
image: dify-api:1.8.1-offline # 替换为离线构建的镜像
restart: always
ports:
- "5001:5001"
environment:
- DATABASE_URL=postgresql://postgres:postgres@db:5432/dify
- REDIS_URL=redis://redis:6379/0
volumes:
- ./data/api:/app/api/data
depends_on:
- db
- redis
5.2 启动 Dify 服务
bash
运行
# 后台启动所有服务(使用Docker内置Compose,无横杠)
sudo docker compose up -d
# 查看服务启动状态
sudo docker compose ps
# 查看API服务日志(验证无报错)
sudo docker compose logs -f api
5.3 验证部署成功
bash
运行
# 测试API接口是否可用(本地访问)
curl http://localhost:5001/health
# 预期返回:{"status":"healthy"}
echo "✅ Dify 1.8.1 离线部署完成!"