Files
zkxw/deploy/docker/部署指导手册.html
2026-06-04 12:57:59 +08:00

500 lines
20 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>中科兴皖 Docker 部署指导手册</title>
<style>
:root {
--primary: #10b981;
--primary-dark: #059669;
--primary-bg: #ecfdf5;
--text: #0f172a;
--text-muted: #64748b;
--border: #e2e8f0;
--warn-bg: #fffbeb;
--warn-border: #f59e0b;
--danger-bg: #fef2f2;
--danger-border: #ef4444;
--code-bg: #f8fafc;
--radius: 10px;
--font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
"Hiragino Sans GB", "Microsoft YaHei", sans-serif;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: var(--font);
font-size: 15px;
line-height: 1.65;
color: var(--text);
background: #f1f5f9;
}
.layout {
display: grid;
grid-template-columns: 260px 1fr;
min-height: 100vh;
max-width: 1280px;
margin: 0 auto;
background: #fff;
box-shadow: 0 0 40px rgba(15, 23, 42, 0.06);
}
@media (max-width: 900px) {
.layout { grid-template-columns: 1fr; }
.sidebar { position: static; height: auto; border-right: none; border-bottom: 1px solid var(--border); }
}
.sidebar {
position: sticky;
top: 0;
height: 100vh;
overflow-y: auto;
padding: 24px 20px;
background: #fafbfc;
border-right: 1px solid var(--border);
}
.sidebar h1 {
font-size: 17px;
margin: 0 0 4px;
color: var(--primary-dark);
}
.sidebar .sub {
font-size: 12px;
color: var(--text-muted);
margin-bottom: 20px;
}
.sidebar nav a {
display: block;
padding: 6px 10px;
margin: 2px 0;
font-size: 13px;
color: var(--text);
text-decoration: none;
border-radius: 6px;
}
.sidebar nav a:hover { background: var(--primary-bg); color: var(--primary-dark); }
main { padding: 32px 40px 64px; min-width: 0; }
@media (max-width: 600px) { main { padding: 20px 16px 48px; } }
h2 {
font-size: 22px;
margin: 40px 0 16px;
padding-bottom: 8px;
border-bottom: 2px solid var(--primary-bg);
color: var(--primary-dark);
}
h2:first-of-type { margin-top: 0; }
h3 { font-size: 17px; margin: 24px 0 12px; }
p { margin: 0 0 12px; }
ul, ol { margin: 0 0 16px; padding-left: 1.4em; }
li { margin-bottom: 6px; }
table {
width: 100%;
border-collapse: collapse;
margin: 12px 0 20px;
font-size: 14px;
}
th, td {
border: 1px solid var(--border);
padding: 10px 12px;
text-align: left;
vertical-align: top;
}
th { background: var(--primary-bg); font-weight: 600; }
pre, code {
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
font-size: 13px;
}
pre {
background: var(--code-bg);
border: 1px solid var(--border);
border-radius: 8px;
padding: 14px 16px;
overflow-x: auto;
margin: 12px 0 20px;
line-height: 1.5;
}
code { background: var(--code-bg); padding: 2px 6px; border-radius: 4px; }
pre code { background: none; padding: 0; }
.hero {
background: linear-gradient(135deg, var(--primary-bg) 0%, #fff 60%);
border: 1px solid #a7f3d0;
border-radius: var(--radius);
padding: 24px 28px;
margin-bottom: 28px;
}
.hero h2 { border: none; margin: 0 0 8px; padding: 0; font-size: 24px; }
.hero p { margin: 0; color: var(--text-muted); }
.badge {
display: inline-block;
background: var(--primary);
color: #fff;
font-size: 12px;
font-weight: 600;
padding: 3px 10px;
border-radius: 999px;
margin-right: 8px;
vertical-align: middle;
}
.steps { counter-reset: step; list-style: none; padding: 0; }
.steps > li {
counter-increment: step;
position: relative;
padding: 16px 16px 16px 52px;
margin-bottom: 12px;
background: #fafbfc;
border: 1px solid var(--border);
border-radius: var(--radius);
}
.steps > li::before {
content: counter(step);
position: absolute;
left: 16px;
top: 16px;
width: 28px;
height: 28px;
line-height: 28px;
text-align: center;
background: var(--primary);
color: #fff;
font-weight: 700;
font-size: 14px;
border-radius: 50%;
}
.steps h3 { margin: 0 0 8px; font-size: 16px; }
.box {
border-radius: 8px;
padding: 14px 16px;
margin: 16px 0;
font-size: 14px;
}
.box-warn { background: var(--warn-bg); border-left: 4px solid var(--warn-border); }
.box-danger { background: var(--danger-bg); border-left: 4px solid var(--danger-border); }
.box-info { background: var(--primary-bg); border-left: 4px solid var(--primary); }
.checklist { list-style: none; padding: 0; }
.checklist li {
padding: 8px 0 8px 28px;
position: relative;
border-bottom: 1px dashed var(--border);
}
.checklist li::before {
content: "☐";
position: absolute;
left: 0;
color: var(--primary);
font-size: 18px;
}
.arch {
background: var(--code-bg);
border: 1px solid var(--border);
border-radius: 8px;
padding: 16px;
font-family: ui-monospace, monospace;
font-size: 13px;
line-height: 1.45;
white-space: pre;
overflow-x: auto;
}
.tree {
font-family: ui-monospace, monospace;
font-size: 13px;
background: var(--code-bg);
padding: 16px;
border-radius: 8px;
border: 1px solid var(--border);
}
footer {
margin-top: 48px;
padding-top: 20px;
border-top: 1px solid var(--border);
font-size: 13px;
color: var(--text-muted);
}
</style>
</head>
<body>
<div class="layout">
<aside class="sidebar">
<h1>中科兴皖</h1>
<p class="sub">Docker 部署指导手册<br />适用:甲方运维人员</p>
<nav>
<a href="#overview">概述</a>
<a href="#requirements">环境要求</a>
<a href="#package">交付包说明</a>
<a href="#mirror">镜像加速(国内)</a>
<a href="#install">安装步骤</a>
<a href="#config">配置说明</a>
<a href="#verify">验收检查</a>
<a href="#architecture">服务架构</a>
<a href="#profiles">部署模式</a>
<a href="#ops">日常运维</a>
<a href="#backup">备份与升级</a>
<a href="#faq">常见问题</a>
</nav>
</aside>
<main>
<div class="hero">
<h2><span class="badge">Docker</span>中科兴皖系统部署指导</h2>
<p>
本手册帮助您在 Linux 服务器上完成<strong>预构建镜像</strong>方式的安装。
交付包不含前后端源码,首次启动需联网拉取 MySQL / Redis / MinIO 等基础镜像。
对外访问端口默认为 <strong>8112</strong>。
</p>
</div>
<section id="overview">
<h2>1. 概述</h2>
<table>
<tr><th>项目</th><th>说明</th></tr>
<tr><td>部署方式</td><td><code>docker load</code> 导入应用镜像 + <code>docker compose up -d</code></td></tr>
<tr><td>应用镜像</td><td><code>zkxw-backend</code>、<code>zkxw-web</code>(已预构建,无需编译)</td></tr>
<tr><td>CPU 架构</td><td><code>linux/amd64</code>(常见 x86 云主机;ARM 服务器需联系交付方重新打包)</td></tr>
<tr><td>对外端口</td><td><strong>8112</strong>(Web 管理端 + API 反代)</td></tr>
<tr><td>默认账号</td><td><code>admin</code> / <code>111111</code>(首次登录后请立即修改)</td></tr>
</table>
<div class="box box-info">
<strong>说明:</strong>MySQL、Redis、MinIO 仅在 Docker 内部网络通信,<strong>不占用</strong>宿主机 3306 / 6379 / 9000 端口,一般不会与贵方已有中间件冲突。
</div>
</section>
<section id="requirements">
<h2>2. 环境要求</h2>
<table>
<tr><th>项</th><th>要求</th></tr>
<tr><td>操作系统</td><td>Linux x86_64(推荐 Ubuntu 22.04、CentOS 7+)</td></tr>
<tr><td>Docker</td><td>≥ 24.0</td></tr>
<tr><td>Docker Compose</td><td>v2(使用 <code>docker compose</code> 子命令)</td></tr>
<tr><td>网络</td><td>可访问 Docker Hub,或已配置国内 Registry 镜像加速</td></tr>
<tr><td>硬件建议</td><td>4 核 CPU、8 GB 内存、磁盘 ≥ 50 GB</td></tr>
<tr><td>端口</td><td>宿主机 <strong>8112</strong> 未被占用;防火墙 / 安全组已放行 TCP 8112</td></tr>
</table>
<p>安装前请执行以下命令确认环境:</p>
<pre><code>docker --version
docker compose version
docker info | grep -A2 "Registry Mirrors" # 国内环境建议已配置加速</code></pre>
</section>
<section id="package">
<h2>3. 交付包目录说明</h2>
<p>解压 <code>zkxw-docker-deploy-&lt;版本&gt;.tar.gz</code> 后,目录结构如下:</p>
<div class="tree">zkxw-docker-deploy-&lt;版本&gt;/
├── images/
│ └── zkxw-app-images.tar # 预构建前后端镜像(必做 docker load)
├── deploy/docker/
│ ├── docker-compose.yml
│ ├── .env.example # 复制为 .env 后修改密码
│ ├── mysql/init/
│ └── 部署指导手册.html # 本手册
├── docs/sql/zkxw.sql # 首次部署自动建库(非业务源码)
├── 部署说明.md # Markdown 版说明(可选阅读)
└── VERSION.txt # 版本与镜像 tag 信息</div>
<div class="box box-warn">
<strong>不包含:</strong>后端 Python 源码、前端 Vue 源码、Dockerfile。数据库脚本仅为表结构与基线数据。
</div>
</section>
<section id="mirror">
<h2>4. Docker 镜像加速(国内强烈建议)</h2>
<p>
应用镜像通过 <code>docker load</code> 本地导入;但首次 <code>docker compose up</code> 仍需从网络拉取
<code>mysql:5.7.36</code>、<code>redis:7-alpine</code>、<code>minio/minio</code> 等基础镜像。
国内服务器建议配置 Registry 镜像加速。
</p>
<p>编辑 <code>/etc/docker/daemon.json</code>(示例,任选可用加速地址):</p>
<pre><code>{
"registry-mirrors": [
"https://docker.1ms.run",
"https://docker.m.daocloud.io"
]
}</code></pre>
<pre><code>sudo systemctl daemon-reload
sudo systemctl restart docker</code></pre>
<p>若贵司已有阿里云 ACR 等专属加速地址,请优先使用官方提供的 URL。</p>
</section>
<section id="install">
<h2>5. 安装步骤</h2>
<p>以下命令假设交付包已上传至 <code>/opt/zkxw</code>,请按实际路径调整。</p>
<ol class="steps">
<li>
<h3>解压交付包</h3>
<pre><code>mkdir -p /opt/zkxw && cd /opt/zkxw
tar -xzf zkxw-docker-deploy-*.tar.gz
cd zkxw-docker-deploy-*</code></pre>
</li>
<li>
<h3>导入应用镜像</h3>
<pre><code>docker load -i images/zkxw-app-images.tar
docker images | grep zkxw-</code></pre>
<p>请记下镜像 tag(如 <code>zkxw-backend:v1.0.0</code>),下一步配置须一致。</p>
</li>
<li>
<h3>配置环境变量</h3>
<pre><code>cd deploy/docker
cp .env.example .env
vi .env</code></pre>
<p>至少修改:<code>MYSQL_ROOT_PASSWORD</code>、<code>DATABASE_URL</code> 中的密码、<code>SECRET_KEY</code>、<code>MINIO_SECRET_KEY</code>。</p>
<p>确认 <code>ZKXW_BACKEND_IMAGE</code>、<code>ZKXW_WEB_IMAGE</code> 与 <code>docker images</code> 显示的 tag 一致(可参考包内 <code>VERSION.txt</code>)。</p>
</li>
<li>
<h3>启动全部服务</h3>
<pre><code>docker compose up -d</code></pre>
<p>首次启动会自动拉取基础镜像,MySQL 导入 <code>zkxw.sql</code> 约需 <strong>1~3 分钟</strong>,请耐心等待。</p>
</li>
<li>
<h3>(可选)查看启动进度</h3>
<pre><code>docker compose ps
docker compose logs -f mysql # 可选,Ctrl+C 仅退出日志,不停止服务
docker compose logs -f backend</code></pre>
</li>
</ol>
</section>
<section id="config">
<h2>6. 配置说明(.env 要点)</h2>
<p>默认模式 <code>COMPOSE_PROFILES=full</code>:自带 MySQL、Redis、MinIO。</p>
<table>
<tr><th>变量</th><th>说明</th></tr>
<tr><td><code>HTTP_PORT</code></td><td>对外 HTTP 端口,默认 <strong>8112</strong></td></tr>
<tr><td><code>ZKXW_BACKEND_IMAGE</code></td><td>后端镜像名:tag,须与 docker load 一致</td></tr>
<tr><td><code>ZKXW_WEB_IMAGE</code></td><td>前端镜像名:tag,须与 docker load 一致</td></tr>
<tr><td><code>MYSQL_ROOT_PASSWORD</code></td><td>MySQL root 密码(full 模式)</td></tr>
<tr><td><code>DATABASE_URL</code></td><td>数据库连接串,密码须与上面一致</td></tr>
<tr><td><code>SECRET_KEY</code></td><td>JWT 密钥,生产环境务必改为长随机串</td></tr>
<tr><td><code>REDIS_HOST</code></td><td>full 模式填 <code>redis</code></td></tr>
<tr><td><code>MINIO_ENDPOINT</code></td><td>full 模式填 <code>minio:9000</code></td></tr>
<tr><td><code>MINIO_BASE_URL</code></td><td>保持 <code>/minio/zkxw</code>(由 Web 镜像内 Nginx 反代)</td></tr>
<tr><td><code>API_ENCRYPT_ENABLED</code></td><td>默认 <code>false</code>,Docker 交付为明文 API</td></tr>
</table>
<div class="box box-danger">
<strong>切勿将 .env 提交到版本库。</strong>修改密码后若服务已启动,执行 <code>docker compose up -d</code> 并 <code>docker compose restart backend</code>。
</div>
</section>
<section id="verify">
<h2>7. 验收检查</h2>
<ul class="checklist">
<li><code>docker compose ps</code> 中 mysql、redis、minio、backend、web 均为 running(backend/web 可为 healthy)</li>
<li>服务器本机:<code>curl -s http://127.0.0.1:8112/health</code> 返回正常</li>
<li>浏览器访问 <code>http://&lt;服务器IP&gt;:8112/</code> 可打开登录页</li>
<li>使用 <code>admin</code> / <code>111111</code> 登录成功(登录后请改密)</li>
<li>防火墙 / 安全组已放行 TCP 8112</li>
</ul>
<table>
<tr><th>地址</th><th>说明</th></tr>
<tr><td><code>http://&lt;IP&gt;:8112/</code></td><td>Web 管理端</td></tr>
<tr><td><code>http://&lt;IP&gt;:8112/health</code></td><td>健康检查</td></tr>
<tr><td><code>http://&lt;IP&gt;:8112/docs</code></td><td>Swagger API 文档</td></tr>
</table>
</section>
<section id="architecture">
<h2>8. 服务架构</h2>
<div class="arch">浏览器 :8112
└── web(Nginx + 前端静态)
├── /api/* → backend:8111(FastAPI)
└── /minio/zkxw/* → minio:9000(附件,容器内网络)
backend → mysql:3306(业务库 zkxw)
→ redis:6379(会话)
→ minio:9000(对象存储)</div>
</section>
<section id="profiles">
<h2>9. 部署模式(高级)</h2>
<p>通过 <code>.env</code> 中 <code>COMPOSE_PROFILES</code> 切换,默认无需修改。</p>
<h3>9.1 full(默认,全栈)</h3>
<pre><code>COMPOSE_PROFILES=full</code></pre>
<p>启动 MySQL + Redis + MinIO + 后端 + 前端,适合独立部署一台服务器。</p>
<h3>9.2 app(仅应用,连接已有中间件)</h3>
<p>若贵方已有 MySQL、Redis、MinIO,可设为 <code>COMPOSE_PROFILES=app</code>,并将 <code>DATABASE_URL</code>、<code>REDIS_HOST</code>、<code>MINIO_*</code> 改为实际地址。具体示例见 <code>deploy/docker/.env.example</code> 注释。</p>
<h3>9.3 app,storage(外部库 + 自带 MinIO)</h3>
<p>已有 MySQL/Redis,仅 MinIO 由本 compose 提供时使用。</p>
<div class="box box-warn">
使用外部 MinIO 且不在 Docker 网络内时,可能需要交付方重新构建 Web 镜像。一般建议先按默认 <code>full</code> 模式完成安装。
</div>
</section>
<section id="ops">
<h2>10. 日常运维命令</h2>
<p>以下命令均在 <code>deploy/docker</code> 目录执行:</p>
<pre><code># 查看状态
docker compose ps
# 查看日志
docker compose logs -f backend
docker compose logs -f web
# 重启
docker compose restart
# 停止(不删数据卷)
docker compose down
# 进入后端容器
docker compose exec backend bash</code></pre>
<div class="box box-danger">
<strong>警告:</strong><code>docker compose down -v</code> 会删除所有数据卷(MySQL、MinIO 等),导致数据丢失。仅在首次部署失败且可接受清空数据时使用。
</div>
</section>
<section id="backup">
<h2>11. 备份与升级</h2>
<h3>11.1 数据卷</h3>
<table>
<tr><th>卷名(前缀 zkxw_)</th><th>内容</th></tr>
<tr><td>mysql_data</td><td>MySQL 业务数据</td></tr>
<tr><td>redis_data</td><td>Redis 持久化</td></tr>
<tr><td>minio_data</td><td>附件对象</td></tr>
<tr><td>backend_uploads</td><td>本地上传目录(若使用本地存储)</td></tr>
</table>
<h3>11.2 MySQL 备份示例</h3>
<pre><code>docker compose exec mysql mysqldump -uroot -p zkxw > zkxw_backup.sql</code></pre>
<h3>11.3 版本升级</h3>
<ol>
<li>备份数据库与 MinIO 数据</li>
<li>解压新版本交付包,<code>docker load -i images/zkxw-app-images.tar</code></li>
<li>更新 <code>.env</code> 中 <code>ZKXW_BACKEND_IMAGE</code>、<code>ZKXW_WEB_IMAGE</code></li>
<li>在 <code>deploy/docker</code> 执行 <code>docker compose up -d</code></li>
<li><code>curl -s http://127.0.0.1:8112/health</code> 验收</li>
</ol>
<p>若仅有数据库结构变更,请使用交付方提供的增量 SQL,<strong>不要</strong>删除已有 mysql_data 卷。</p>
</section>
<section id="faq">
<h2>12. 常见问题</h2>
<h3>无法访问 8112</h3>
<ul>
<li>检查云主机安全组 / 防火墙是否放行 TCP 8112</li>
<li><code>docker compose ps</code> 确认 web 为 running</li>
<li><code>docker compose logs web</code> 查看 Nginx 日志</li>
</ul>
<h3>/api 返回 502</h3>
<ul>
<li>后端未就绪:<code>docker compose logs backend</code></li>
<li>首次部署 MySQL 仍在导入:等待 1~3 分钟后重试</li>
</ul>
<h3>拉取 mysql/redis/minio 镜像失败或很慢</h3>
<p>请按第 4 节配置 Docker Registry 镜像加速后,重新执行 <code>docker compose up -d</code>。</p>
<h3>附件无法显示</h3>
<ul>
<li>确认 <code>STORAGE_TYPE=minio</code></li>
<li><code>docker compose logs minio-init</code> 应显示 bucket 创建成功</li>
<li>浏览器中附件 URL 应为 <code>/minio/zkxw/...</code></li>
</ul>
<h3>首次部署数据库初始化失败(可清空重来)</h3>
<pre><code>cd deploy/docker
docker compose down -v
docker compose up -d</code></pre>
<p>此操作会清空所有数据,仅适用于尚未正式上线的环境。</p>
</section>
<footer>
<p>中科兴皖 · Docker 部署指导手册 · 与交付包内 <code>deploy/docker/README.md</code> 保持一致</p>
<p>技术支持请联系项目交付方。安装完成后请修改默认管理员密码。</p>
</footer>
</main>
</div>
</body>
</html>