| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- <!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-<版本>.tar.gz</code> 后,目录结构如下:</p>
- <div class="tree">zkxw-docker-deploy-<版本>/
- ├── 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://<服务器IP>: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://<IP>:8112/</code></td><td>Web 管理端</td></tr>
- <tr><td><code>http://<IP>:8112/health</code></td><td>健康检查</td></tr>
- <tr><td><code>http://<IP>: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>
|