Files
rxthinkcmf-wiki/RXThinkCMF_Laravel13_AntdVue/zh/deploy/docker.md
T
2026-10-08 17:50:29 +08:00

30 KiB
Raw Blame History

11.6 Docker 生产部署

:::tip 概述 本节提供基于 Docker Compose 的生产环境部署方案,包含 Nginx 反向代理、PHP-FPM 应用、MySQL 数据库和 Redis 缓存四个服务的容器编排配置。所有脚本均带详细注释,适合快速搭建生产环境,也便于 CI/CD 集成。本地快速体验请先阅读 2.8 Docker 快速体验。 :::

架构说明

浏览器 → 宿主机:8000 → [Nginx 容器:80] → [PHP-FPM 容器:9000] → Laravel 应用
                                                ↕
                                    [MySQL 容器:3306] + [Redis 容器:6379]
  • Nginx:监听 80 端口,处理 HTTP 请求、URL 重写、静态资源缓存
  • PHP-FPM:监听 9000 端口,执行 PHP 代码
  • MySQL:数据库服务,数据持久化到 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(见「性能调优」)

前置要求

依赖 版本要求 说明
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 前端部署
9 监控与备份 /up 挂监控、数据库定时备份,见 11.9 备份与恢复

文件结构

RXThinkCMF_Laravel13_EleVue/
├── docker/
│   ├── Dockerfile          # PHP-FPM 应用镜像定义
│   ├── nginx.conf          # Nginx 站点配置
│   └── .env.docker         # Docker 环境变量(密码等敏感信息)
├── docker-compose.yml      # 容器编排配置(放在项目根目录)
├── .dockerignore           # 构建上下文排除(.env、vendor、SQL 等)
├── .env                    # 应用配置(Laravel 读取)
└── ...

Dockerfile

# =============================================================================
# Dockerfile — PHP-FPM 应用镜像(RXThinkCMF Laravel13)
# =============================================================================
# 基础镜像:PHP 8.3 + FPM(FastCGI 进程管理器)
# 构建命令:docker compose build app
# 运行方式:由 Nginx 容器通过 FastCGI 协议调用本容器的 9000 端口
# =============================================================================

FROM php:8.3-fpm

# -----------------------------------------------------------------------------
# 1. 安装系统依赖
# -----------------------------------------------------------------------------
# PHP 扩展编译需要的 C 库和工具,安装后清理 apt 缓存减小镜像体积
RUN apt-get update && apt-get install -y --no-install-recommends \
        libpng-dev \                # GD 扩展 — PNG 支持
        libjpeg-dev \               # GD 扩展 — JPEG 支持
        libfreetype6-dev \          # GD 扩展 — 字体渲染(验证码依赖)
        libzip-dev \                # zip 扩展依赖
        zip \                       # Composer 安装依赖包时可能用到
        unzip \                     # Composer 解压依赖包
    && rm -rf /var/lib/apt/lists/*  # 清理 apt 缓存,减小镜像体积

# -----------------------------------------------------------------------------
# 2. 安装 PHP 扩展
# -----------------------------------------------------------------------------
# 项目必需扩展(根据 composer.json 和 config/ 推导):
#   pdo_mysql  — MySQL 数据库驱动(config/database.php 使用)
#   mbstring   — 多字节字符串处理(Laravel 框架依赖,composer 平台检查)
#   gd         — 图片处理(验证码生成、图片缩放)
#   bcmath     — 高精度数学运算(phpspreadsheet 依赖)
#   zip        — ZIP 压缩(phpspreadsheet 读写 xlsx 依赖)
#   redis      — Redis 扩展(phpredis:缓存/会话/队列/JWT 会话均依赖)
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) \
        pdo_mysql \
        mbstring \
        gd \
        bcmath \
        zip \
    && pecl install redis \
    && docker-php-ext-enable redis

# -----------------------------------------------------------------------------
# 3. 安装 Composer
# -----------------------------------------------------------------------------
# 从官方镜像复制 composer 二进制文件,避免重复安装
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# -----------------------------------------------------------------------------
# 4. 配置 PHP 生产环境参数
# -----------------------------------------------------------------------------
# 使用 php.ini-production 作为基础,追加项目所需配置
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

# 生产环境追加配置:内存、超时、上传、时区、OPcache 等
RUN echo '\n\
; ====== 生产环境追加配置(Docker 自动生成) ====== \n\
\n\
; 关闭错误显示,防止敏感信息泄露到前端\ndisplay_errors = Off\n\
error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED\n\
\n\
; 内存与超时\n\
memory_limit = 256M\n\
max_execution_time = 60\n\
max_input_time = 60\n\
\n\
; 文件上传(与 .env 中 FILE_MAX_SIZE 配合)\n\
upload_max_filesize = 50M\n\
post_max_size = 50M\n\
max_file_uploads = 20\n\
\n\
; 时区(与应用时区一致)\n\
date.timezone = Asia/Shanghai\n\
\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 = 1\n\
opcache.revalidate_freq = 0\n\
opcache.save_comments = 1\n\
' >> "$PHP_INI_DIR/php.ini"

# -----------------------------------------------------------------------------
# 5. 设置工作目录
# -----------------------------------------------------------------------------
WORKDIR /var/www/html

# -----------------------------------------------------------------------------
# 6. 复制项目文件并安装依赖
# -----------------------------------------------------------------------------
# 先复制 composer 文件,利用 Docker 层缓存 ——
# 只要 composer.json / composer.lock 没变就不重新安装依赖
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-interaction

# 再复制全部项目文件(.env、vendor、node_modules 已被 .dockerignore 排除)
COPY . .

# -----------------------------------------------------------------------------
# 7. 设置 Laravel 可写目录权限
# -----------------------------------------------------------------------------
# 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. 暴露端口并启动
# -----------------------------------------------------------------------------
# 9000 是 PHP-FPM 的 FastCGI 监听端口,Nginx 通过此端口转发请求
EXPOSE 9000
CMD ["php-fpm"]

Nginx 配置

# =============================================================================
# Nginx 配置 — RXThinkCMF Laravel13 反向代理
# =============================================================================
# 用途:Docker 容器内 Nginx 服务,将 HTTP 请求转发给 PHP-FPM 处理
# 挂载方式:docker-compose 中 volumes 映射到 /etc/nginx/conf.d/default.conf
# =============================================================================

server {
    # 监听容器内 80 端口(宿主机通过 docker-compose ports 映射到 8000)
    listen 80;
    server_name localhost;

    # 网站根目录指向 Laravel 公开目录
    # 容器内代码挂载在 /var/www/html,入口文件在 public/index.php
    root /var/www/html/public;
    index index.php;

    # -----------------------------------------------------------------
    # URL 重写(Laravel 路由)
    # -----------------------------------------------------------------
    # 真实存在的文件/目录直接返回,其余请求全部交给 public/index.php,
    # 由 Laravel 路由解析(如 /api/user/page → index.php 处理)
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # -----------------------------------------------------------------
    # PHP-FPM 处理(仅入口 index.php 可执行)
    # -----------------------------------------------------------------
    # "app" 是 docker-compose 中 PHP-FPM 服务的名称,Docker 内部 DNS 自动解析
    location = /index.php {
        fastcgi_pass   app:9000;            # 转发到 PHP-FPM 容器的 9000 端口
        fastcgi_index  index.php;            # 默认索引文件
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;       # 引入标准 FastCGI 参数

        # 超时设置(秒),防止长请求被 Nginx 提前断开
        fastcgi_read_timeout  300;
        fastcgi_send_timeout  300;
    }

    # 其余 .php 文件(含上传目录、storage 目录)一律 404
    # 防止恶意文件上传后被执行 —— 只有入口 index.php 能够运行
    location ~ \.php$ {
        return 404;
    }

    # -----------------------------------------------------------------
    # 安全规则:禁止访问隐藏文件(如 .env、.git、.htaccess)
    # -----------------------------------------------------------------
    location ~ /\. {
        deny all;
    }

    # -----------------------------------------------------------------
    # 静态资源缓存
    # -----------------------------------------------------------------
    # 常见静态文件类型设置 30 天浏览器缓存,减少重复请求
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # -----------------------------------------------------------------
    # Gzip 压缩
    # -----------------------------------------------------------------
    gzip            on;
    gzip_types      text/plain text/css application/json application/javascript text/xml application/xml;
    gzip_min_length 1024;       # 小于 1KB 的响应不压缩(压缩收益低)
    gzip_comp_level 5;          # 压缩级别 1-9,5 为性能与压缩率的平衡点
}

docker-compose.yml

:::tip 与实际文件的关系 项目根目录已内置 docker-compose.yml,支持两种模式:

  • 快速体验:docker compose up -d(使用默认密码 root123 / redis123)
  • 生产部署:docker compose --env-file docker/.env.docker up -d --build(使用生产密码)

下方为生产推荐配置参考,实际文件通过 ${VAR:-默认值} 语法兼容两种场景。 :::

# =============================================================================
# Docker Compose 生产部署配置(RXThinkCMF Laravel13)
# =============================================================================
# 服务架构:Nginx → PHP-FPM → MySQL + Redis
# 启动命令:docker compose --env-file docker/.env.docker up -d
# 停止命令:docker compose down
# =============================================================================

services:

  # ===========================================================================
  # Nginx 反向代理服务
  # ===========================================================================
  # 职责:接收外部 HTTP 请求,转发 index.php 到 PHP-FPM,直接返回静态资源
  # 端口:容器内 80 → 宿主机 8000
  # ===========================================================================
  nginx:
    image: nginx:1.25-alpine             # 官方 Nginx 镜像(Alpine 版本,体积小)
    container_name: rxthinkcmf-laravel13-nginx
    ports:
      - "8000:80"                        # 宿主机 8000 → 容器 80
    volumes:
      - ./docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro   # 站点配置
      - ./:/var/www/html:ro              # 项目代码(只读,与 PHP-FPM 共享同一份)
    depends_on:
      - app                              # 确保 PHP-FPM 先启动
    networks:
      - rxthinkcmf-laravel13-net
    restart: unless-stopped              # 异常退出自动重启

  # ===========================================================================
  # PHP-FPM 应用服务
  # ===========================================================================
  # 职责:执行 Laravel PHP 代码,处理业务逻辑
  # 端口:9000(FastCGI 协议,仅 Nginx 内部访问,不映射宿主机)
  # ===========================================================================
  app:
    build:
      context: .                         # 构建上下文为项目根目录
      dockerfile: docker/Dockerfile
    container_name: rxthinkcmf-laravel13-app
    volumes:
      - ./:/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:
        condition: service_healthy        # 确保数据库就绪(含首次 SQL 导入)
      redis:
        condition: service_started
    networks:
      - rxthinkcmf-laravel13-net
    restart: unless-stopped

  # ===========================================================================
  # MySQL 数据库服务
  # ===========================================================================
  # 职责:存储业务数据(用户、菜单、字典、文章等)
  # ===========================================================================
  mysql:
    image: mysql:8.0                     # MySQL 8.0 官方镜像
    container_name: rxthinkcmf-laravel13-mysql
    # ports:                             # 生产环境建议注释掉,不暴露到宿主机
    #   - "3306:3306"
    environment:
      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.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-laravel13-net
    restart: unless-stopped

  # ===========================================================================
  # Redis 缓存服务
  # ===========================================================================
  # 职责:JWT 会话、字典/权限缓存、队列(config/database.php redis 配置)
  # ===========================================================================
  redis:
    image: redis:7-alpine                # Redis 7 Alpine 版本(体积小)
    container_name: rxthinkcmf-laravel13-redis
    # ports:                             # 生产环境建议注释掉,不暴露到宿主机
    #   - "6379:6379"
    command: redis-server --requirepass ${REDIS_PASSWORD}  # 设置访问密码
    volumes:
      - redis_data:/data                 # 数据持久化(RDB 快照)
    networks:
      - rxthinkcmf-laravel13-net
    restart: unless-stopped

# =============================================================================
# 命名卷(Named Volumes)
# =============================================================================
# Docker 管理的持久化存储,容器删除后数据保留
# 删除所有数据:docker compose down -v(-v 参数同时删除命名卷)
# =============================================================================
volumes:
  mysql_data:       # MySQL 数据文件
  redis_data:       # Redis RDB 快照文件

# =============================================================================
# 内部网络
# =============================================================================
# 所有服务通过此网络互通,容器间使用服务名(如 "mysql")作为主机名
# 外部无法直接访问此网络,必须通过 Nginx 的 ports 映射进入
# =============================================================================
networks:
  rxthinkcmf-laravel13-net:
    driver: bridge

环境变量配置

创建 / 编辑 docker/.env.docker 文件:

# Docker 环境变量(密码等敏感信息,切勿提交 Git)

# 端口(宿主机端口)
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,切勿提交到 Git 仓库
  • 密码至少 16 位,包含大小写字母和数字,MySQL 与 Redis 密码不同
  • JWT_SECRET 是令牌签名根密钥,泄露等于任意用户令牌可伪造;不同环境使用不同密钥 :::

应用 .env 配置

容器启动前,确保项目根目录 .env 已初始化(APP_KEY、JWT_SECRET、DB_PREFIX):

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 即可与手动部署共用同一份配置。 :::

启动部署

# 1. 配置环境变量
#    复制模板并修改密码
cp docker/.env.docker docker/.env.docker.local
vi docker/.env.docker.local    # 修改密码、JWT_SECRET、域名

# 2. 配置应用 .env
cp .env.example .env
php artisan key:generate       # 生成 APP_KEY

# 3. 构建并启动所有服务
docker compose --env-file docker/.env.docker.local up -d --build

# 4. 查看运行状态(首次 mysql 需导入约 226MB SQL,等 healthy)
docker compose ps

# 5. 查看应用日志(确认无报错)
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(会清空数据);
  • 从旧环境迁入已有数据:
# 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"

日常运维

# --------------------------------------------------------------------------
# 代码更新
# --------------------------------------------------------------------------
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               # 停止并删除所有数据卷(⚠️ 清空数据库)
docker compose restart app           # 重启单个服务(修改 .env 后生效)

# --------------------------------------------------------------------------
# 日志排查
# --------------------------------------------------------------------------
docker compose logs -f               # 所有服务日志
docker compose logs -f app           # 应用日志
docker compose logs -f nginx         # Nginx 日志
docker compose logs -f mysql         # 数据库日志(首次看导入进度)

# --------------------------------------------------------------------------
# 进入容器调试
# --------------------------------------------------------------------------
docker compose exec app bash         # 进入 PHP-FPM 容器
docker compose exec mysql bash       # 进入 MySQL 容器
docker compose exec mysql mysql -uroot -p'<密码>' rxthinkcmf.laravel13.elevue

# --------------------------------------------------------------------------
# 数据库操作
# --------------------------------------------------------------------------
# 导出数据库备份
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

# --------------------------------------------------------------------------
# Laravel Artisan 命令
# --------------------------------------------------------------------------
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 定时任务),容器化部署时在宿主机配置 Crontab 调用 docker compose exec app php artisan ...,或单独以 app 镜像运行常驻容器执行任务守护命令。 :::

性能调优

OPcache(生产建议)

镜像默认 opcache.validate_timestamps=1(便于挂载代码即时生效)。生产环境代码不再变动,建议在 docker/Dockerfile 中改为:

opcache.validate_timestamps = 0    # 代码不再重新检查,性能最优

修改后重新构建镜像:

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 数据库设计);
  • Redis 建议设置 maxmemory + 淘汰策略防止内存耗尽——注意 JWT 会话存储在 Redis,淘汰策略不当会导致用户掉线。

生产环境建议

配置项 建议值 说明
APP_DEBUG false 关闭调试模式,防止堆栈/路径泄露
MYSQL_ROOT_PASSWORD 强密码(>=16位) 包含大小写字母和数字
REDIS_PASSWORD 强密码 与数据库密码不同
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 用户管理)

SSL 配置(HTTPS)

生产环境建议在 Nginx 前增加 SSL 终止,修改 nginx.conf:

server {
    listen 443 ssl;
    server_name api.example.com;

    ssl_certificate     /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;

    # ... 其余配置不变 ...
}

# HTTP 跳转 HTTPS
server {
    listen 80;
    server_name api.example.com;
    return 301 https://$server_name$request_uri;
}

docker-compose.yml 中增加证书挂载:

nginx:
  volumes:
    - ./docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro
    - ./ssl/cert.pem:/etc/nginx/ssl/cert.pem:ro
    - ./ssl/key.pem:/etc/nginx/ssl/key.pem:ro

备份与恢复

# 数据库备份(定时任务执行)
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 备份与恢复。

故障排查

症状 排查 处理
启动报 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

相关文档