签入版本
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
# 11.6 Docker 生产部署
|
||||
|
||||
:::tip 概述
|
||||
本节提供基于 Docker Compose 的生产环境部署方案,包含 **Nginx 反向代理**、**PHP-FPM 应用**、**MySQL 数据库**和 **Redis 缓存**四个服务的容器编排配置。所有脚本均带详细注释,适合快速搭建生产环境,也便于 CI/CD 集成。
|
||||
本节提供基于 Docker Compose 的生产环境部署方案,包含 **Nginx 反向代理**、**PHP-FPM 应用**、**MySQL 数据库**和 **Redis 缓存**四个服务的容器编排配置。所有脚本均带详细注释,适合快速搭建生产环境,也便于 CI/CD 集成。本地快速体验请先阅读 [2.8 Docker 快速体验](/zh/quickstart/docker.html)。
|
||||
:::
|
||||
|
||||
## 架构说明
|
||||
|
||||
```
|
||||
浏览器 → 宿主机:8000 → [Nginx 容器:80] → [PHP-FPM 容器:9000] → ThinkPHP 应用
|
||||
```text
|
||||
浏览器 → 宿主机:8000 → [Nginx 容器:80] → [PHP-FPM 容器:9000] → Laravel 应用
|
||||
↕
|
||||
[MySQL 容器:3306] + [Redis 容器:6379]
|
||||
```
|
||||
@@ -15,7 +15,19 @@
|
||||
- **Nginx**:监听 80 端口,处理 HTTP 请求、URL 重写、静态资源缓存
|
||||
- **PHP-FPM**:监听 9000 端口,执行 PHP 代码
|
||||
- **MySQL**:数据库服务,数据持久化到 Docker 命名卷
|
||||
- **Redis**:缓存服务,数据持久化到 Docker 命名卷
|
||||
- **Redis**:缓存 / 会话 / 队列服务,数据持久化到 Docker 命名卷
|
||||
|
||||
## 与快速体验的差异
|
||||
|
||||
| 项 | 2.8 快速体验 | 本节生产部署 |
|
||||
|----|--------------|--------------|
|
||||
| 启动命令 | `docker compose up -d` | `docker compose --env-file docker/.env.docker up -d --build` |
|
||||
| 密码 | compose 内置默认值(root123 / redis123) | `.env.docker` 中的强密码 |
|
||||
| `APP_DEBUG` | `true` | **`false`** |
|
||||
| `JWT_SECRET` | 占位值或 `.env` 值 | `openssl rand -base64 32` 生成的随机值 |
|
||||
| `CORS_ALLOW_ORIGIN` | `*` | 前端站点具体域名 |
|
||||
| 数据库 / Redis 端口 | 映射到宿主机 | **建议注释掉映射或绑定 127.0.0.1** |
|
||||
| OPcache | `validate_timestamps=1` | 建议改为 `0`(见「性能调优」) |
|
||||
|
||||
## 前置要求
|
||||
|
||||
@@ -24,17 +36,33 @@
|
||||
| Docker | >= 20.10 | 容器运行时 |
|
||||
| Docker Compose | >= 2.0 | 容器编排工具 |
|
||||
| 磁盘空间 | >= 5GB | 镜像 + 数据卷 |
|
||||
| 服务器 | 2 核 / 4 GB 起 | 数据库初始化导入约 226MB |
|
||||
|
||||
## 部署 Checklist
|
||||
|
||||
| # | 步骤 | 说明 |
|
||||
|---|------|------|
|
||||
| 1 | 服务器安装 Docker | `docker compose version` 验证 |
|
||||
| 2 | 获取代码 | `git clone` 或上传代码包 |
|
||||
| 3 | 初始化 `.env` | `composer setup` 或 `cp .env.example .env` + `key:generate`(容器外执行) |
|
||||
| 4 | 定制 `docker/.env.docker` | 强密码、随机 JWT_SECRET、生产域名(见「环境变量配置」) |
|
||||
| 5 | 端口映射调整 | 数据库 / Redis 端口注释掉或绑定 `127.0.0.1` |
|
||||
| 6 | 构建并启动 | `docker compose --env-file docker/.env.docker up -d --build` |
|
||||
| 7 | 验证 | `/up` 健康检查、`/api/captcha` 返回 `code=0` |
|
||||
| 8 | 前端部署 | 见 [11.5 前端部署](/zh/deploy/frontend.html) |
|
||||
| 9 | 监控与备份 | `/up` 挂监控、数据库定时备份,见 [11.9 备份与恢复](/zh/deploy/backup.html) |
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
thinkphp6/
|
||||
```text
|
||||
RXThinkCMF_Laravel13_EleVue/
|
||||
├── docker/
|
||||
│ ├── Dockerfile # PHP-FPM 应用镜像定义
|
||||
│ ├── nginx.conf # Nginx 站点配置
|
||||
│ └── .env.docker # Docker 环境变量(密码等敏感信息)
|
||||
├── docker-compose.yml # 容器编排配置(放在项目根目录)
|
||||
├── .env # 应用配置(ThinkPHP 读取)
|
||||
├── .dockerignore # 构建上下文排除(.env、vendor、SQL 等)
|
||||
├── .env # 应用配置(Laravel 读取)
|
||||
└── ...
|
||||
```
|
||||
|
||||
@@ -42,14 +70,14 @@ thinkphp6/
|
||||
|
||||
```dockerfile
|
||||
# =============================================================================
|
||||
# Dockerfile — PHP-FPM 应用镜像
|
||||
# Dockerfile — PHP-FPM 应用镜像(RXThinkCMF Laravel13)
|
||||
# =============================================================================
|
||||
# 基础镜像:PHP 8.2 + FPM(FastCGI 进程管理器)
|
||||
# 构建命令:docker-compose build app
|
||||
# 基础镜像:PHP 8.3 + FPM(FastCGI 进程管理器)
|
||||
# 构建命令:docker compose build app
|
||||
# 运行方式:由 Nginx 容器通过 FastCGI 协议调用本容器的 9000 端口
|
||||
# =============================================================================
|
||||
|
||||
FROM php:8.2-fpm
|
||||
FROM php:8.3-fpm
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 1. 安装系统依赖
|
||||
@@ -69,11 +97,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
# -----------------------------------------------------------------------------
|
||||
# 项目必需扩展(根据 composer.json 和 config/ 推导):
|
||||
# pdo_mysql — MySQL 数据库驱动(config/database.php 使用)
|
||||
# mbstring — 多字节字符串处理(ThinkPHP 框架依赖)
|
||||
# mbstring — 多字节字符串处理(Laravel 框架依赖,composer 平台检查)
|
||||
# gd — 图片处理(验证码生成、图片缩放)
|
||||
# bcmath — 高精度数学运算(phpspreadsheet 依赖)
|
||||
# zip — ZIP 压缩(phpspreadsheet 读写 xlsx 依赖)
|
||||
# redis — Redis 缓存驱动(config/cache.php 使用)
|
||||
# redis — Redis 扩展(phpredis:缓存/会话/队列/JWT 会话均依赖)
|
||||
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
|
||||
&& docker-php-ext-install -j$(nproc) \
|
||||
pdo_mysql \
|
||||
@@ -108,20 +136,23 @@ memory_limit = 256M\n\
|
||||
max_execution_time = 60\n\
|
||||
max_input_time = 60\n\
|
||||
\n\
|
||||
; 文件上传(与 .env 中 FILE.MAX_SIZE 配合)\n\
|
||||
; 文件上传(与 .env 中 FILE_MAX_SIZE 配合)\n\
|
||||
upload_max_filesize = 50M\n\
|
||||
post_max_size = 50M\n\
|
||||
max_file_uploads = 20\n\
|
||||
\n\
|
||||
; 时区(与 .env 中 APP.DEFAULT_TIMEZONE 一致)\n\
|
||||
; 时区(与应用时区一致)\n\
|
||||
date.timezone = Asia/Shanghai\n\
|
||||
\n\
|
||||
; OPcache 加速(生产环境必须开启)\n\
|
||||
; OPcache 加速\n\
|
||||
; validate_timestamps=1 + revalidate_freq=0:挂载宿主机代码即时生效(开发友好)\n\
|
||||
; 生产环境建议改为 validate_timestamps=0(见 11.6「性能调优」)\n\
|
||||
opcache.enable = 1\n\
|
||||
opcache.memory_consumption = 256\n\
|
||||
opcache.interned_strings_buffer = 16\n\
|
||||
opcache.max_accelerated_files = 10000\n\
|
||||
opcache.validate_timestamps = 0\n\
|
||||
opcache.validate_timestamps = 1\n\
|
||||
opcache.revalidate_freq = 0\n\
|
||||
opcache.save_comments = 1\n\
|
||||
' >> "$PHP_INI_DIR/php.ini"
|
||||
|
||||
@@ -138,17 +169,24 @@ WORKDIR /var/www/html
|
||||
COPY composer.json composer.lock ./
|
||||
RUN composer install --no-dev --optimize-autoloader --no-interaction
|
||||
|
||||
# 再复制全部项目文件(会覆盖上面的 composer 文件,但内容一致无影响)
|
||||
# 再复制全部项目文件(.env、vendor、node_modules 已被 .dockerignore 排除)
|
||||
COPY . .
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 7. 设置目录权限
|
||||
# 7. 设置 Laravel 可写目录权限
|
||||
# -----------------------------------------------------------------------------
|
||||
# runtime — ThinkPHP 运行时缓存、日志(必须可写)
|
||||
# uploads — 用户上传文件目录(必须可写)
|
||||
RUN mkdir -p runtime uploads \
|
||||
&& chown -R www-data:www-data runtime uploads \
|
||||
&& chmod -R 775 runtime uploads
|
||||
# storage — 日志、缓存、会话、编译视图(必须可写)
|
||||
# bootstrap/cache — 配置/路由/事件缓存(必须可写)
|
||||
# public/uploads — 用户上传文件目录(必须可写)
|
||||
RUN mkdir -p \
|
||||
storage/framework/cache \
|
||||
storage/framework/sessions \
|
||||
storage/framework/views \
|
||||
storage/logs \
|
||||
bootstrap/cache \
|
||||
public/uploads \
|
||||
&& chown -R www-data:www-data storage bootstrap/cache public/uploads \
|
||||
&& chmod -R 775 storage bootstrap/cache public/uploads
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 8. 暴露端口并启动
|
||||
@@ -162,7 +200,7 @@ CMD ["php-fpm"]
|
||||
|
||||
```nginx
|
||||
# =============================================================================
|
||||
# Nginx 配置 — ThinkPHP 6 反向代理
|
||||
# Nginx 配置 — RXThinkCMF Laravel13 反向代理
|
||||
# =============================================================================
|
||||
# 用途:Docker 容器内 Nginx 服务,将 HTTP 请求转发给 PHP-FPM 处理
|
||||
# 挂载方式:docker-compose 中 volumes 映射到 /etc/nginx/conf.d/default.conf
|
||||
@@ -173,28 +211,25 @@ server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
# 网站根目录指向 ThinkPHP 入口目录
|
||||
# 网站根目录指向 Laravel 公开目录
|
||||
# 容器内代码挂载在 /var/www/html,入口文件在 public/index.php
|
||||
root /var/www/html/public;
|
||||
index index.php;
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# URL 重写(ThinkPHP 必需)
|
||||
# URL 重写(Laravel 路由)
|
||||
# -----------------------------------------------------------------
|
||||
# 将所有非真实文件请求转发到 index.php,由 ThinkPHP 路由解析
|
||||
# 例:/api/user/page → /index.php?s=/api/user/page
|
||||
# 真实存在的文件/目录直接返回,其余请求全部交给 public/index.php,
|
||||
# 由 Laravel 路由解析(如 /api/user/page → index.php 处理)
|
||||
location / {
|
||||
if (!-e $request_filename) {
|
||||
rewrite ^(.*)$ /index.php?s=$1 last;
|
||||
}
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# PHP-FPM 处理
|
||||
# PHP-FPM 处理(仅入口 index.php 可执行)
|
||||
# -----------------------------------------------------------------
|
||||
# 所有 .php 请求通过 FastCGI 协议转发给 PHP-FPM 容器
|
||||
# "app" 是 docker-compose 中 PHP-FPM 服务的名称,Docker 内部 DNS 自动解析
|
||||
location ~ \.php$ {
|
||||
location = /index.php {
|
||||
fastcgi_pass app:9000; # 转发到 PHP-FPM 容器的 9000 端口
|
||||
fastcgi_index index.php; # 默认索引文件
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
@@ -205,16 +240,16 @@ server {
|
||||
fastcgi_send_timeout 300;
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# 安全规则
|
||||
# -----------------------------------------------------------------
|
||||
# 禁止访问隐藏文件(如 .env、.git、.htaccess)
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
# 其余 .php 文件(含上传目录、storage 目录)一律 404
|
||||
# 防止恶意文件上传后被执行 —— 只有入口 index.php 能够运行
|
||||
location ~ \.php$ {
|
||||
return 404;
|
||||
}
|
||||
|
||||
# 禁止上传目录执行 PHP(防止恶意文件上传后被执行)
|
||||
location ~ /uploads/.*\.php$ {
|
||||
# -----------------------------------------------------------------
|
||||
# 安全规则:禁止访问隐藏文件(如 .env、.git、.htaccess)
|
||||
# -----------------------------------------------------------------
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
@@ -230,7 +265,6 @@ server {
|
||||
# -----------------------------------------------------------------
|
||||
# Gzip 压缩
|
||||
# -----------------------------------------------------------------
|
||||
# 对文本类响应启用压缩,减少传输体积
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
|
||||
gzip_min_length 1024; # 小于 1KB 的响应不压缩(压缩收益低)
|
||||
@@ -242,134 +276,146 @@ server {
|
||||
|
||||
:::tip 与实际文件的关系
|
||||
项目根目录已内置 `docker-compose.yml`,支持两种模式:
|
||||
- **快速体验**:`docker-compose up -d`(使用默认密码 root123 / redis123)
|
||||
- **生产部署**:`docker-compose --env-file docker/.env.docker up -d --build`(使用生产密码)
|
||||
- **快速体验**:`docker compose up -d`(使用默认密码 root123 / redis123)
|
||||
- **生产部署**:`docker compose --env-file docker/.env.docker up -d --build`(使用生产密码)
|
||||
|
||||
下方为生产推荐配置参考,实际文件通过 `${VAR:-默认值}` 语法兼容两种场景。
|
||||
:::
|
||||
|
||||
```yaml
|
||||
# =============================================================================
|
||||
# Docker Compose 生产部署配置
|
||||
# Docker Compose 生产部署配置(RXThinkCMF Laravel13)
|
||||
# =============================================================================
|
||||
# 服务架构:Nginx → PHP-FPM → MySQL + Redis
|
||||
# 启动命令:docker-compose --env-file docker/.env.docker up -d
|
||||
# 停止命令:docker-compose down
|
||||
# 启动命令:docker compose --env-file docker/.env.docker up -d
|
||||
# 停止命令:docker compose down
|
||||
# =============================================================================
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
|
||||
# ===========================================================================
|
||||
# Nginx 反向代理服务
|
||||
# ===========================================================================
|
||||
# 职责:接收外部 HTTP 请求,转发 .php 到 PHP-FPM,直接返回静态资源
|
||||
# 职责:接收外部 HTTP 请求,转发 index.php 到 PHP-FPM,直接返回静态资源
|
||||
# 端口:容器内 80 → 宿主机 8000
|
||||
# ===========================================================================
|
||||
nginx:
|
||||
image: nginx:1.25-alpine # 官方 Nginx 镜像(Alpine 版本,体积小)
|
||||
container_name: rxthinkcmf-nginx # 容器名称,便于 docker logs / docker exec
|
||||
container_name: rxthinkcmf-laravel13-nginx
|
||||
ports:
|
||||
- "8000:80" # 宿主机 8000 → 容器 80
|
||||
volumes:
|
||||
# 挂载 Nginx 站点配置(覆盖默认配置)
|
||||
- ./docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
# 挂载项目代码(与 PHP-FPM 容器共享同一份代码)
|
||||
- ./:/var/www/html:ro # :ro 只读,Nginx 不需要写入代码
|
||||
- ./docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro # 站点配置
|
||||
- ./:/var/www/html:ro # 项目代码(只读,与 PHP-FPM 共享同一份)
|
||||
depends_on:
|
||||
- app # 确保 PHP-FPM 先启动
|
||||
networks:
|
||||
- rxthinkcmf-net # 加入内部网络
|
||||
- rxthinkcmf-laravel13-net
|
||||
restart: unless-stopped # 异常退出自动重启
|
||||
|
||||
# ===========================================================================
|
||||
# PHP-FPM 应用服务
|
||||
# ===========================================================================
|
||||
# 职责:执行 ThinkPHP PHP 代码,处理业务逻辑
|
||||
# 端口:9000(FastCGI 协议,仅 Nginx 内部访问)
|
||||
# 职责:执行 Laravel PHP 代码,处理业务逻辑
|
||||
# 端口:9000(FastCGI 协议,仅 Nginx 内部访问,不映射宿主机)
|
||||
# ===========================================================================
|
||||
app:
|
||||
build:
|
||||
context: . # 构建上下文为项目根目录
|
||||
dockerfile: docker/Dockerfile # Dockerfile 路径(相对于 context)
|
||||
container_name: rxthinkcmf-app
|
||||
dockerfile: docker/Dockerfile
|
||||
container_name: rxthinkcmf-laravel13-app
|
||||
volumes:
|
||||
# 挂载项目代码(开发/更新时无需重建镜像)
|
||||
- ./:/var/www/html
|
||||
# 上传文件独立持久化卷(容器重建不丢失用户上传)
|
||||
- uploads_data:/opt/data/uploads
|
||||
- ./:/var/www/html # 挂载项目代码(更新时无需重建镜像)
|
||||
environment:
|
||||
- APP_DEBUG=${APP_DEBUG:-false} # 调试模式,默认关闭
|
||||
|
||||
# 数据库:容器内通过服务名 mysql 访问
|
||||
- DB_CONNECTION=mysql
|
||||
- DB_HOST=mysql
|
||||
- DB_PORT=3306
|
||||
- DB_DATABASE=${MYSQL_DATABASE:-rxthinkcmf.laravel13.elevue}
|
||||
- DB_USERNAME=root
|
||||
- DB_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||
|
||||
# 缓存 / 会话 / 队列:统一走 Redis
|
||||
- CACHE_STORE=redis
|
||||
- SESSION_DRIVER=redis
|
||||
- QUEUE_CONNECTION=redis
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
|
||||
# JWT 密钥 / 文件域名 / 跨域(取自 --env-file)
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
- FILE_DOMAIN_URL=${DOMAIN_URL:-http://localhost:8000}
|
||||
- CORS_ALLOW_ORIGIN=${CORS_ALLOW_ORIGIN:-*}
|
||||
|
||||
depends_on:
|
||||
- mysql # 确保数据库先启动
|
||||
- redis # 确保缓存先启动
|
||||
mysql:
|
||||
condition: service_healthy # 确保数据库就绪(含首次 SQL 导入)
|
||||
redis:
|
||||
condition: service_started
|
||||
networks:
|
||||
- rxthinkcmf-net
|
||||
- rxthinkcmf-laravel13-net
|
||||
restart: unless-stopped
|
||||
|
||||
# ===========================================================================
|
||||
# MySQL 数据库服务
|
||||
# ===========================================================================
|
||||
# 职责:存储业务数据(用户、菜单、字典、文章等)
|
||||
# 端口:3306(可选暴露,用于外部工具连接调试)
|
||||
# ===========================================================================
|
||||
mysql:
|
||||
image: mysql:8.0 # MySQL 8.0 官方镜像
|
||||
container_name: rxthinkcmf-mysql
|
||||
container_name: rxthinkcmf-laravel13-mysql
|
||||
# ports: # 生产环境建议注释掉,不暴露到宿主机
|
||||
# - "3306:3306"
|
||||
environment:
|
||||
# root 用户密码(必须 8 位以上,包含大小写字母和数字)
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||
# 启动时自动创建的数据库
|
||||
MYSQL_DATABASE: ${MYSQL_DATABASE:-rxthinkcmf.thinkphp6.elevue}
|
||||
# 字符集(支持 emoji 等四字节字符)
|
||||
MYSQL_CHARSET: utf8mb4
|
||||
# 排序规则
|
||||
MYSQL_COLLATION: utf8mb4_general_ci
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} # root 用户密码(>=16 位强密码)
|
||||
MYSQL_DATABASE: ${MYSQL_DATABASE:-rxthinkcmf.laravel13.elevue}
|
||||
volumes:
|
||||
# 数据持久化(容器重建不丢数据)
|
||||
- mysql_data:/var/lib/mysql
|
||||
# 初始化 SQL(首次启动时自动执行,仅在数据卷为空时生效)
|
||||
- ./document/mysql/rxthinkcmf.thinkphp6.elevue.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
||||
- mysql_data:/var/lib/mysql # 数据持久化
|
||||
# 初始化 SQL(首次启动自动执行,仅在数据卷为空时生效)
|
||||
- ./document/mysql/rxthinkcmf.laravel13.elevue.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
||||
command:
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_general_ci
|
||||
- --default-authentication-plugin=mysql_native_password
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 30
|
||||
start_period: 60s # 首次导入约 226MB SQL,给足缓冲
|
||||
networks:
|
||||
- rxthinkcmf-net
|
||||
- rxthinkcmf-laravel13-net
|
||||
restart: unless-stopped
|
||||
|
||||
# ===========================================================================
|
||||
# Redis 缓存服务
|
||||
# ===========================================================================
|
||||
# 职责:会话缓存、数据缓存(config/cache.php 配置的驱动)
|
||||
# 端口:6379(可选暴露,用于外部工具连接调试)
|
||||
# 职责:JWT 会话、字典/权限缓存、队列(config/database.php redis 配置)
|
||||
# ===========================================================================
|
||||
redis:
|
||||
image: redis:7-alpine # Redis 7 Alpine 版本(体积小)
|
||||
container_name: rxthinkcmf-redis
|
||||
container_name: rxthinkcmf-laravel13-redis
|
||||
# ports: # 生产环境建议注释掉,不暴露到宿主机
|
||||
# - "6379:6379"
|
||||
command: redis-server --requirepass ${REDIS_PASSWORD} # 设置访问密码
|
||||
volumes:
|
||||
# 数据持久化(RDB 快照文件)
|
||||
- redis_data:/data
|
||||
- redis_data:/data # 数据持久化(RDB 快照)
|
||||
networks:
|
||||
- rxthinkcmf-net
|
||||
- rxthinkcmf-laravel13-net
|
||||
restart: unless-stopped
|
||||
|
||||
# =============================================================================
|
||||
# 命名卷(Named Volumes)
|
||||
# =============================================================================
|
||||
# Docker 管理的持久化存储,容器删除后数据保留
|
||||
# 删除所有数据:docker-compose down -v(-v 参数同时删除命名卷)
|
||||
# 删除所有数据:docker compose down -v(-v 参数同时删除命名卷)
|
||||
# =============================================================================
|
||||
volumes:
|
||||
mysql_data: # MySQL 数据文件
|
||||
redis_data: # Redis RDB 快照文件
|
||||
uploads_data: # 用户上传文件
|
||||
|
||||
# =============================================================================
|
||||
# 内部网络
|
||||
@@ -378,155 +424,207 @@ volumes:
|
||||
# 外部无法直接访问此网络,必须通过 Nginx 的 ports 映射进入
|
||||
# =============================================================================
|
||||
networks:
|
||||
rxthinkcmf-net:
|
||||
rxthinkcmf-laravel13-net:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
## 环境变量配置
|
||||
|
||||
创建 `docker/.env.docker` 文件:
|
||||
创建 / 编辑 `docker/.env.docker` 文件:
|
||||
|
||||
```ini
|
||||
# Docker 环境变量(密码等敏感信息,切勿提交 Git)
|
||||
MYSQL_ROOT_PASSWORD=Your_Strong_Password_2024
|
||||
MYSQL_DATABASE=rxthinkcmf.thinkphp6.elevue
|
||||
REDIS_PASSWORD=Your_Redis_Password_2024
|
||||
|
||||
# 端口(宿主机端口)
|
||||
NGINX_PORT=8000
|
||||
MYSQL_PORT=3306
|
||||
REDIS_PORT=6379
|
||||
|
||||
# MySQL(首次启动自动导入数据库脚本)
|
||||
MYSQL_ROOT_PASSWORD=<16 位以上强密码>
|
||||
MYSQL_DATABASE=rxthinkcmf.laravel13.elevue
|
||||
|
||||
# Redis(与数据库密码不同)
|
||||
REDIS_PASSWORD=<强密码>
|
||||
|
||||
# 应用
|
||||
JWT_SECRET=<openssl rand -base64 32 生成,>= 32 字符>
|
||||
APP_DEBUG=false
|
||||
DOMAIN_URL=https://admin.example.com
|
||||
CORS_ALLOW_ORIGIN=https://www.example.com
|
||||
```
|
||||
|
||||
:::warning 安全提示
|
||||
- `docker/.env.docker` 包含生产密码,**必须加入 `.gitignore`**
|
||||
- 密码至少 16 位,包含大小写字母和数字
|
||||
- JWT 密钥在应用 `.env` 文件中配置,不在此文件中
|
||||
- `docker/.env.docker` 包含生产密码,**必须加入 `.gitignore`,切勿提交到 Git 仓库**
|
||||
- 密码至少 16 位,包含大小写字母和数字,MySQL 与 Redis 密码不同
|
||||
- `JWT_SECRET` 是令牌签名根密钥,泄露等于任意用户令牌可伪造;不同环境使用不同密钥
|
||||
:::
|
||||
|
||||
## 应用 .env 配置
|
||||
|
||||
容器启动前,确保项目根目录 `.env` 文件中以下配置正确:
|
||||
容器启动前,确保项目根目录 `.env` 已初始化(`APP_KEY`、`JWT_SECRET`、`DB_PREFIX`):
|
||||
|
||||
```ini
|
||||
APP_DEBUG = false
|
||||
|
||||
[APP]
|
||||
SHOW_ERROR_MSG = false
|
||||
|
||||
[DATABASE]
|
||||
; 连接地址(Docker 内部使用服务名 "mysql")
|
||||
HOSTNAME = mysql
|
||||
; 密码(与 .env.docker 中 MYSQL_ROOT_PASSWORD 一致)
|
||||
PASSWORD = Your_Strong_Password_2024
|
||||
|
||||
[CACHE]
|
||||
; 连接地址(Docker 内部使用服务名 "redis")
|
||||
REDIS_HOST = redis
|
||||
; 密码(与 .env.docker 中 REDIS_PASSWORD 一致)
|
||||
REDIS_PASSWORD = Your_Redis_Password_2024
|
||||
|
||||
[FILE]
|
||||
; 上传目录(容器内路径,与 docker-compose uploads_data 卷对应)
|
||||
UPLOAD_DIR = /opt/data/uploads
|
||||
APP_KEY= # 留空,composer setup 的 key:generate 生成
|
||||
JWT_SECRET=<32 字符以上随机值> # 应用启动 fail-close 校验
|
||||
DB_PREFIX=laravel_ # 数据库脚本使用 laravel_ 前缀,必须保留
|
||||
```
|
||||
|
||||
:::tip 数据库连接无需修改
|
||||
`docker-compose.yml` 的 `environment` 块已把 `DB_HOST` 覆盖为 `mysql`、`REDIS_HOST` 覆盖为 `redis`(容器环境变量优先级高于 `.env` 文件),本地 `.env` 保持 `127.0.0.1` 即可与手动部署共用同一份配置。
|
||||
:::
|
||||
|
||||
## 启动部署
|
||||
|
||||
```bash
|
||||
# 1. 配置环境变量
|
||||
# 复制模板并修改密码
|
||||
cp docker/.env.docker docker/.env.docker.local
|
||||
vi docker/.env.docker.local # 修改密码
|
||||
vi docker/.env.docker.local # 修改密码、JWT_SECRET、域名
|
||||
|
||||
# 2. 配置应用 .env
|
||||
cp .env.example .env
|
||||
vi .env # 修改数据库、Redis 连接信息
|
||||
php artisan key:generate # 生成 APP_KEY
|
||||
|
||||
# 3. 构建并启动所有服务
|
||||
docker-compose --env-file docker/.env.docker.local up -d --build
|
||||
docker compose --env-file docker/.env.docker.local up -d --build
|
||||
|
||||
# 4. 查看运行状态
|
||||
docker-compose ps
|
||||
# 4. 查看运行状态(首次 mysql 需导入约 226MB SQL,等 healthy)
|
||||
docker compose ps
|
||||
|
||||
# 5. 查看应用日志(确认无报错)
|
||||
docker-compose logs -f app
|
||||
docker compose logs -f app
|
||||
|
||||
# 6. 验证
|
||||
curl https://your-domain/up
|
||||
curl http://localhost:8000/api/captcha # 返回 code=0 即成功
|
||||
```
|
||||
|
||||
## 常用命令
|
||||
### 首次初始化与数据迁移
|
||||
|
||||
- MySQL 仅在**数据卷为空**时执行 `docker-entrypoint-initdb.d` 中的初始化 SQL;
|
||||
- 已有数据卷不会重复导入,更换 SQL 脚本需先 `docker compose down -v`(**会清空数据**);
|
||||
- 从旧环境迁入已有数据:
|
||||
|
||||
```bash
|
||||
# Linux / Git Bash
|
||||
docker compose exec -T mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" rxthinkcmf.laravel13.elevue' < backup.sql
|
||||
|
||||
# Windows CMD(PowerShell 不支持 < 重定向,用 cmd /c 包裹)
|
||||
cmd /c "docker compose exec -T mysql mysql -uroot -p<密码> rxthinkcmf.laravel13.elevue < backup.sql"
|
||||
```
|
||||
|
||||
## 日常运维
|
||||
|
||||
```bash
|
||||
# --------------------------------------------------------------------------
|
||||
# 代码更新
|
||||
# --------------------------------------------------------------------------
|
||||
git pull
|
||||
docker compose --env-file docker/.env.docker build app
|
||||
docker compose --env-file docker/.env.docker up -d app
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 生命周期管理
|
||||
# --------------------------------------------------------------------------
|
||||
# 启动所有服务(后台运行)
|
||||
docker-compose up -d
|
||||
|
||||
# 停止所有服务(保留数据卷)
|
||||
docker-compose down
|
||||
|
||||
# 停止并删除所有数据卷(⚠️ 清空数据库和上传文件)
|
||||
docker-compose down -v
|
||||
|
||||
# 重建镜像并启动(Dockerfile 或 composer.json 变更后)
|
||||
docker-compose up -d --build
|
||||
|
||||
# 重启单个服务
|
||||
docker-compose restart app
|
||||
docker compose up -d # 启动所有服务(后台运行)
|
||||
docker compose down # 停止所有服务(保留数据卷)
|
||||
docker compose down -v # 停止并删除所有数据卷(⚠️ 清空数据库)
|
||||
docker compose restart app # 重启单个服务(修改 .env 后生效)
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 日志排查
|
||||
# --------------------------------------------------------------------------
|
||||
# 查看所有服务日志
|
||||
docker-compose logs -f
|
||||
|
||||
# 查看单个服务日志
|
||||
docker-compose logs -f app
|
||||
docker-compose logs -f nginx
|
||||
docker-compose logs -f mysql
|
||||
docker compose logs -f # 所有服务日志
|
||||
docker compose logs -f app # 应用日志
|
||||
docker compose logs -f nginx # Nginx 日志
|
||||
docker compose logs -f mysql # 数据库日志(首次看导入进度)
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 进入容器调试
|
||||
# --------------------------------------------------------------------------
|
||||
# 进入 PHP-FPM 容器
|
||||
docker-compose exec app bash
|
||||
|
||||
# 进入 MySQL 容器
|
||||
docker-compose exec mysql bash
|
||||
|
||||
# 在容器内执行 SQL
|
||||
docker-compose exec mysql mysql -uroot -pYour_Strong_Password_2024 rxthinkcmf.thinkphp6.elevue
|
||||
docker compose exec app bash # 进入 PHP-FPM 容器
|
||||
docker compose exec mysql bash # 进入 MySQL 容器
|
||||
docker compose exec mysql mysql -uroot -p'<密码>' rxthinkcmf.laravel13.elevue
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 数据库操作
|
||||
# --------------------------------------------------------------------------
|
||||
# 导入 SQL 文件
|
||||
docker-compose exec -T mysql mysql -uroot -pYour_Strong_Password_2024 rxthinkcmf.thinkphp6.elevue < document/mysql/rxthinkcmf.thinkphp6.elevue.sql
|
||||
|
||||
# 导出数据库备份
|
||||
docker-compose exec mysql mysqldump -uroot -pYour_Strong_Password_2024 rxthinkcmf.thinkphp6.elevue > backup_$(date +%Y%m%d).sql
|
||||
docker compose exec -T mysql sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" rxthinkcmf.laravel13.elevue' > backup_$(date +%Y%m%d).sql
|
||||
|
||||
# 导入 SQL 文件
|
||||
docker compose exec -T mysql mysql -uroot -p'<密码>' rxthinkcmf.laravel13.elevue < backup.sql
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# ThinkPHP 命令
|
||||
# Laravel Artisan 命令
|
||||
# --------------------------------------------------------------------------
|
||||
# 数据库迁移
|
||||
docker-compose exec app php think db:migrate
|
||||
|
||||
# 清除运行时缓存
|
||||
docker-compose exec app php think clear
|
||||
|
||||
# 查看路由列表
|
||||
docker-compose exec app php think route:list
|
||||
docker compose exec app php artisan config:cache # 缓存配置(生产建议)
|
||||
docker compose exec app php artisan route:cache # 缓存路由
|
||||
docker compose exec app php artisan migrate --force # 执行迁移
|
||||
docker compose exec app php artisan config:clear # 清除配置缓存
|
||||
docker compose exec app php artisan route:list # 查看路由列表
|
||||
```
|
||||
|
||||
## 生产环境建议
|
||||
:::tip 定时任务
|
||||
项目内置 Cron / Daemon 双模式定时任务(见 [6.11 定时任务](/zh/modules/job.html)),容器化部署时在宿主机配置 Crontab 调用 `docker compose exec app php artisan ...`,或单独以 `app` 镜像运行常驻容器执行任务守护命令。
|
||||
:::
|
||||
|
||||
## 性能调优
|
||||
|
||||
### OPcache(生产建议)
|
||||
|
||||
镜像默认 `opcache.validate_timestamps=1`(便于挂载代码即时生效)。生产环境代码不再变动,建议在 `docker/Dockerfile` 中改为:
|
||||
|
||||
```ini
|
||||
opcache.validate_timestamps = 0 # 代码不再重新检查,性能最优
|
||||
```
|
||||
|
||||
修改后重新构建镜像:
|
||||
|
||||
```bash
|
||||
docker compose --env-file docker/.env.docker build app
|
||||
docker compose --env-file docker/.env.docker up -d app
|
||||
```
|
||||
|
||||
:::warning
|
||||
`validate_timestamps=0` 后修改代码必须重启容器(或重新构建)才会生效。
|
||||
:::
|
||||
|
||||
### PHP-FPM
|
||||
|
||||
镜像使用 `php-fpm` 默认动态进程池。并发较高时按 CPU 核数调整 `www.conf` 的 `pm.max_children`(建议 `(内存 - 系统占用) / 单进程内存`),可通过自定义配置挂载覆盖。
|
||||
|
||||
### MySQL / Redis
|
||||
|
||||
- MySQL 数据在命名卷 `mysql_data`,大表查询配合项目索引策略(见 [4.9 数据库设计](/zh/architecture/database-design.html));
|
||||
- Redis 建议设置 `maxmemory` + 淘汰策略防止内存耗尽——注意 **JWT 会话存储在 Redis**,淘汰策略不当会导致用户掉线。
|
||||
|
||||
### 生产环境建议
|
||||
|
||||
| 配置项 | 建议值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| APP_DEBUG | false | 关闭调试模式,防止 SQL/路径泄露 |
|
||||
| APP_DEBUG | false | 关闭调试模式,防止堆栈/路径泄露 |
|
||||
| MYSQL_ROOT_PASSWORD | 强密码(>=16位) | 包含大小写字母和数字 |
|
||||
| REDIS_PASSWORD | 强密码 | 与数据库密码不同 |
|
||||
| JWT.SECRET | 随机字符串(>=32字节) | 在应用 .env 中配置 |
|
||||
| FILE.UPLOAD_DIR | /opt/data/uploads | 使用命名卷持久化 |
|
||||
| JWT_SECRET | 随机字符串(>=32字符) | `openssl rand -base64 32` |
|
||||
| CORS_ALLOW_ORIGIN | 前端具体域名 | 生产禁止 `*` |
|
||||
| 数据库/Redis 端口 | 注释掉映射 | 容器间通信不需要宿主机映射 |
|
||||
| 数据卷 | 持久化挂载 | 避免容器重启丢失数据 |
|
||||
| Nginx SSL | 443 + 证书 | 生产环境必须启用 HTTPS |
|
||||
|
||||
## 安全加固
|
||||
|
||||
| 项 | 措施 |
|
||||
|----|------|
|
||||
| 调试模式 | `APP_DEBUG=false`(true 会泄露异常堆栈、配置信息) |
|
||||
| JWT 密钥 | 随机生成、不同环境不同密钥、严格保密 |
|
||||
| 数据库端口 | 注释 `docker-compose.yml` 中 mysql/redis 的 `ports` 映射,或绑定 `"127.0.0.1:3306:3306"` |
|
||||
| 跨域 | `CORS_ALLOW_ORIGIN` 显式配置前端域名 |
|
||||
| 敏感文件 | `.dockerignore` 已排除 `.env`、SQL 脚本;`nginx.conf` 禁止访问隐藏文件 |
|
||||
| PHP 执行 | Nginx 仅允许入口 `index.php` 执行,上传目录中的 `.php` 一律 404 |
|
||||
| 默认账号 | 首次登录后立即修改 `admin` 默认密码(见 [6.1 用户管理](/zh/modules/user.html)) |
|
||||
|
||||
## SSL 配置(HTTPS)
|
||||
|
||||
生产环境建议在 Nginx 前增加 SSL 终止,修改 `nginx.conf`:
|
||||
@@ -550,7 +648,7 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
docker-compose.yml 中增加证书挂载:
|
||||
`docker-compose.yml` 中增加证书挂载:
|
||||
|
||||
```yaml
|
||||
nginx:
|
||||
@@ -560,9 +658,39 @@ nginx:
|
||||
- ./ssl/key.pem:/etc/nginx/ssl/key.pem:ro
|
||||
```
|
||||
|
||||
## 备份与恢复
|
||||
|
||||
```bash
|
||||
# 数据库备份(定时任务执行)
|
||||
docker compose exec -T mysql sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" rxthinkcmf.laravel13.elevue' > backup_$(date +%F).sql
|
||||
|
||||
# 数据库恢复
|
||||
docker compose exec -T mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" rxthinkcmf.laravel13.elevue' < backup_2026-10-01.sql
|
||||
|
||||
# 整卷备份(停机快照)
|
||||
docker compose down
|
||||
docker run --rm -v rxthinkcmf-laravel13_mysql_data:/data -v $(pwd):/backup alpine tar czf /backup/mysql_data.tar.gz -C /data .
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
更多方案见 [11.9 备份与恢复](/zh/deploy/backup.html)。
|
||||
|
||||
## 故障排查
|
||||
|
||||
| 症状 | 排查 | 处理 |
|
||||
|------|------|------|
|
||||
| 启动报 dependency failed to start | `docker compose logs mysql` | 首次导入大 SQL 较慢,等待 healthy;密码错误则 `down -v` 后修正重来 |
|
||||
| 页面 502 Bad Gateway | `docker compose ps` | app 未运行 → `docker compose logs app` 定位崩溃原因 |
|
||||
| 页面 404 | `docker compose logs nginx` | 确认 `docker/nginx.conf` 挂载正确、入口在 `public/` 下 |
|
||||
| 500 且无详情 | `docker compose logs app` | 生产 `APP_DEBUG=false` 时错误细节只在日志中 |
|
||||
| 启动即退出,日志报 JWT_SECRET | `.env` 或 `.env.docker` 密钥 < 32 字符 | 重新生成并重启 |
|
||||
| 存储写入失败 | `storage/`、`bootstrap/cache/` 权限 | 镜像已 chown;挂载宿主机时确认目录对容器可写 |
|
||||
| 备份 SQL 中文乱码 | 导出未指定字符集 | `mysqldump --default-character-set=utf8mb4` |
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [后端部署](/zh/deploy/backend.html) — Nginx/Apache 详细配置
|
||||
- [2.8 Docker 快速体验](/zh/quickstart/docker.html) — 本地一键启动
|
||||
- [后端部署](/zh/deploy/backend.html) — Nginx/Apache 非 Docker 详细配置
|
||||
- [前端部署](/zh/deploy/frontend.html) — Vue3 前端部署
|
||||
- [数据库迁移](/zh/deploy/db-migrate.html) — 多数据库迁移工具
|
||||
- [环境变量参考](/zh/appendix/config-reference.html) — 完整配置项说明
|
||||
- [环境变量参考](/zh/quickstart/env-vars.html) — 完整配置项说明
|
||||
|
||||
Reference in New Issue
Block a user