跳到内容

Docker

受众:开发者 摘要:Docker / Compose 启动方式。一体化镜像 / 外部 MySQL / Redis / Nginx 静态优先。

本项目的 Docker 目标是省掉环境准备:默认镜像已经内置 Java 应用、MySQL、Redis 和 Nginx,拉取镜像后用一条 docker run 就能看到完整程序。

生产上线的推荐拓扑、目录规划、Nginx 外层代理和 smoke 清单见 生产部署样板

先看这里

你要做什么看这里
本机马上体验零配置启动
运行本地容器运行本地容器
本地打包镜像给服务器构建和导出镜像
校验 Docker / Nginx / prod 入口部署 smoke
上传到 Linux 服务器运行服务器部署
配置服务器 Nginx 反代Nginx 反向代理
只启动 Redis / MySQL / PostgreSQL单独启动基础组件
想拆开 MySQL / Redis / NginxCompose 拆分部署
找目录和配置项目录和配置
排查容器问题排查

运行模式

同一个镜像支持两种模式:

模式配置适合场景
一体化模式SPRING_OPEN_RUNTIME_MODE=all-in-one默认模式,一个容器内启动 MySQL、Redis、Java 应用和 Nginx
应用模式SPRING_OPEN_RUNTIME_MODE=app只启动 Java 应用,配合外部 MySQL、Redis、Nginx 或 Compose

docker/docker-compose.yml 是 Docker 环境版本基线;Compose 默认使用 MySQL 8.4、Redis 8、Nginx 1.27。一体化镜像以同款 MySQL 8.4 为底座,Redis / Nginx 使用同一 Linux 发行版的软件包,避免单镜像内跨发行版复制二进制导致运行库不兼容。docker/Dockerfile 已把 Java/common、MySQL、Redis、Nginx 依赖分组注释;需要更轻的镜像时,可以按注释删除对应依赖,并改用 SPRING_OPEN_RUNTIME_MODE=app

零配置启动

不需要提前准备 MySQL、Redis 或 Nginx:

bash
docker run -d \
  --name springopen \
  --restart unless-stopped \
  -p 8080:80 \
  springopen/springopen:1.0.0

本地 Docker 测试部署优先使用宿主机 8080,这样浏览器预览地址固定、方便反复查看。如果 8080 已被占用,可以按端口号递增查找可用端口:

bash
PORT=8080
while lsof -iTCP:${PORT} -sTCP:LISTEN >/dev/null 2>&1; do
  PORT=$((PORT + 1))
done

docker rm -f springopen 2>/dev/null || true
docker run -d \
  --name springopen \
  --restart unless-stopped \
  -p ${PORT}:80 \
  springopen/springopen:1.0.0

echo "访问地址: http://127.0.0.1:${PORT}/"

常用入口:

text
http://127.0.0.1:8080/
http://127.0.0.1:8080/admin/
http://127.0.0.1:8080/app/
http://127.0.0.1:8080/pc/
http://127.0.0.1:8080/install/
http://127.0.0.1:8080/docs/

零配置模式不会占用宿主机 33066379,因为 MySQL 和 Redis 只在容器内部监听 127.0.0.1。宿主机只暴露映射出来的 Web 端口,例如 8080

运行本地容器

开发过程中,如果想把当前代码重新构建成 Docker 镜像,并替换本机 springopen 容器,使用根目录脚本:

bash
chmod +x scripts/docker
./scripts/docker run

脚本会执行:

  1. 使用 docker/Dockerfile 构建 springopen/springopen:1.0.0
  2. 删除并重建本机容器 springopen
  3. 默认映射到 http://127.0.0.1:8080/
  4. 默认把内置 MySQL 数据持久化到 docker/data/mysql
  5. 等待根路径 / 返回 200,即认为容器可访问。

如果 8080 被其他程序占用,脚本会自动尝试 80818082 等递增端口。也可以手动指定起始端口:

bash
HOST_PORT=18080 ./scripts/docker run

如果从起始端口连续检查多个端口仍然占用,可以扩大查找范围:

bash
MAX_PORT_ATTEMPTS=200 ./scripts/docker run

脚本默认会构建前端视图。只想快速重建后端镜像、复用当前 public/ 静态产物时,可以显式跳过前端构建:

bash
./scripts/docker run --skip-views
SKIP_VIEW_BUILD=true ./scripts/docker run

使用 --skip-views 前,要先确保本机 public/adminpublic/apppublic/pcpublic/docs 等静态产物已经是你想预览的版本。

本地预览脚本默认会挂载:

text
docker/data/mysql -> /home/app/docker/data/mysql
docker/data/redis -> /home/app/docker/data/redis
storage          -> /home/app/storage
public           -> /home/app/public

因此反复执行脚本更新镜像和容器时,注册账号、安装状态、Redis 数据、上传文件和运行缓存不会因为容器替换而丢失;本机重新构建或调整 public/ 静态资源后,刷新浏览器即可看到最新页面。需要临时挂载其他静态目录、存储目录或 Redis 数据目录时,可以指定:

bash
PUBLIC_DIR=/path/to/public ./scripts/docker run
STORAGE_DIR=/path/to/storage ./scripts/docker run
REDIS_DATA_DIR=/path/to/redis ./scripts/docker run

不想挂载本机 public/,而是使用镜像内置静态产物时:

bash
./scripts/docker run --no-mount-public
MOUNT_PUBLIC=false ./scripts/docker run

不想挂载本机 storage/,而是使用容器内部临时存储目录时:

bash
./scripts/docker run --no-mount-storage
MOUNT_STORAGE=false ./scripts/docker run

需要重置开发数据库时,优先使用脚本重建当前开发库:

bash
./scripts/docker db-reset --yes

需要彻底重置本地预览容器的整个 MySQL 数据目录时,再先停止容器并删除 docker/data/mysql

bash
docker rm -f springopen
rm -rf docker/data/mysql

如果只想临时体验一份干净数据库,不保留本次容器里的 MySQL 数据,可以关闭持久化:

bash
./scripts/docker run --no-persist-data
PERSIST_DATA=false ./scripts/docker run

关闭持久化后,数据库只保存在容器内部;下次脚本替换容器时账号、安装状态和业务数据都会重置。

Redis、上传文件和公开资源需要长期保留时,使用 服务器部署 中的完整挂载方式。

部署 smoke

改动 Dockerfile、Compose、Nginx 模板、entrypoint、生产配置或安装入口后,先跑脚本级 smoke:

bash
./scripts/docker smoke

默认不启动容器,会检查:

  • Dockerfile、Compose、Nginx 模板、entrypoint、application-prod.yml 等部署入口文件存在。
  • Compose 默认使用 prod profile、MySQL 8.4、Redis 8、Nginx 1.27;生产部署建议通过环境变量注入应用密钥、数据库凭据和真实 Provider 密钥。
  • application.yml 保留 SPRING_PROFILES_ACTIVE 环境覆盖,避免容器 profile 被构建时默认值锁死。
  • application-lite.yml 保持 H2 + memory auth / rate-limit / queue,并显式禁用 Redis / Redisson / db-scheduler。
  • Nginx 保留 /api/ 代理、WebSocket Upgrade、五端入口重定向和 SPA fallback。
  • entrypoint 支持 all-in-oneapp 两种运行模式。
  • 本机有 Docker Compose 时额外执行 docker compose -f docker/docker-compose.yml config --quiet
  • 追加 --websocket-cluster 时,会同时校验 websocket-cluster profile、双应用节点、集群 Nginx、WebSocket Upgrade 和 Compose profile 解析。

如果已经通过 ./scripts/docker run 或服务器部署启动了服务,可以追加 HTTP 入口 smoke:

bash
./scripts/docker smoke --base-url http://127.0.0.1:8080

HTTP smoke 会检查 //install//admin//app//pc//docs//actuator/health。其中页面入口允许 2xx3xx,健康检查要求 200

发布前需要覆盖 Admin / App / PC 三端主流程时,在运行中的服务上追加 --main-flow

bash
./scripts/docker smoke --base-url http://127.0.0.1:8080 --main-flow

不提供账号时,主流程 smoke 会检查 Site 配置、认证能力、CMS、Blog、Forum、Mall 公开业务入口,以及 /api/ws WebSocket guest 握手。需要同时验证登录、用户资料、权限、菜单、通知、社区联系人、购物车和授权 WebSocket 时,提供一组已存在的 smoke 账号:

bash
SMOKE_USERNAME=admin SMOKE_PASSWORD=changeit \
  ./scripts/docker smoke --base-url http://127.0.0.1:8080 --main-flow

正式发布验收建议加上 --require-auth,这样缺少账号密码会直接失败,而不是只跑公开入口:

bash
./scripts/docker smoke \
  --base-url http://127.0.0.1:8080 \
  --main-flow \
  --require-auth \
  --smoke-username admin \
  --smoke-password changeit

WebSocket 多实例入口可以独立 smoke。只做静态部署校验时不需要启动容器;服务已通过 websocket-cluster profile 启动后,可以加 --base-url 走集群 Nginx 健康检查和 guest WebSocket 握手:

bash
./scripts/docker smoke --websocket-cluster
./scripts/docker smoke --websocket-cluster --base-url http://127.0.0.1:18080

需要真实复验跨容器投递时,使用 acceptance 命令。它默认启动 websocket-cluster profile、等待 Nginx 和应用健康、打开两个原生 WebSocket 客户端并通过 X-Upstream-Addr 证明落到不同应用节点,然后验证用户目标通知 payload 和分组聊天 payload 都能跨实例到达。命令默认使用临时 MySQL / Redis 数据目录,结束后自动 docker compose down 并删除临时数据;如需复用 docker/data,显式传 --reuse-data

bash
./scripts/docker websocket-cluster-acceptance
./scripts/docker websocket-cluster-acceptance --no-build

构建和导出镜像

推荐使用根目录脚本构建并导出 Linux 服务器可导入的 .tar 镜像包:

bash
chmod +x scripts/docker
./scripts/docker build

脚本默认使用 docker/Dockerfile 构建 springopen/springopen:1.0.0,并导出到:

text
docker/images/springopen-springopen-1.0.0-linux-amd64.tar

常用覆盖:

bash
IMAGE_TAG=1.0.0 PLATFORM=linux/amd64 ./scripts/docker build
OUTPUT=docker/images/springopen-springopen-1.0.0-linux-amd64.tar ./scripts/docker build

脚本默认会构建前端视图。只想复用当前 public/ 静态产物时,可以跳过前端构建:

bash
./scripts/docker build --skip-views
SKIP_VIEW_BUILD=true ./scripts/docker build

跳过前端构建不会重新生成视图,只会把当前 public/ 中已有的静态资源打进镜像。

也可以手动从项目根目录构建本机镜像:

bash
docker build -f docker/Dockerfile -t springopen/springopen:1.0.0 .

docker/Dockerfile 使用 BuildKit cache mount 缓存系统包、Maven 依赖和 pnpm store。MySQL 8.4 底座、Redis / Nginx 运行包、tzdata、ca-certificates 这类固定基础包在本机重复构建时会复用构建缓存,不会每次完整下载;缓存不会进入最终镜像层。

如果你发现基础包仍然每次重新下载,通常是本机 Docker builder 缓存被清理过,或没有启用 BuildKit。可以显式启用:

bash
DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile -t springopen/springopen:1.0.0 .

在 macOS 上构建给常见 Linux x86_64 服务器使用的 .tar 镜像包:

bash
mkdir -p docker/images

docker buildx build \
  --platform linux/amd64 \
  -f docker/Dockerfile \
  -t springopen/springopen:1.0.0 \
  --output type=docker,dest=docker/images/springopen-springopen-1.0.0-linux-amd64.tar \
  .

检查镜像包:

bash
ls -lh docker/images/springopen-springopen-1.0.0-linux-amd64.tar
shasum -a 256 docker/images/springopen-springopen-1.0.0-linux-amd64.tar

如果镜像已经在本机 Docker 中,也可以直接导出:

bash
docker save -o docker/images/springopen-springopen-1.0.0-linux-amd64.tar springopen/springopen:1.0.0

docker/images/ 用目录内 .gitignore 忽略镜像产物,导出的 .tar 不进入 Git。

服务器部署

.tar 上传到 Linux 服务器后导入:

bash
docker load -i springopen-springopen-1.0.0-linux-amd64.tar
docker images | grep springopen

服务器面板导入镜像通常要求文件后缀为 .tar,推荐直接上传未压缩文件。

生产或长期试用建议在当前部署目录挂载数据目录,并让容器端口只绑定本机:

bash
mkdir -p storage
mkdir -p public

docker rm -f springopen 2>/dev/null || true

docker run -d \
  --name springopen \
  --restart unless-stopped \
  -p 127.0.0.1:8080:80 \
  -e DB_DATABASE=spring_open \
  -e DB_USERNAME=spring_open \
  -e DB_PASSWORD='replace-with-strong-database-password' \
  -e DB_ROOT_PASSWORD='replace-with-strong-root-password' \
  -e REDIS_PASSWORD='replace-with-strong-redis-password' \
  -e APP_SECRET='replace-with-at-least-32-random-characters' \
  -e SPRING_PROFILES_ACTIVE=prod \
  -e SPRING_OPEN_INSTALL_ENABLED=true \
  -e SPRING_OPEN_INSTALL_TOKEN='replace-with-high-entropy-install-token' \
  -e TZ=Asia/Shanghai \
  -v "$(pwd)/storage:/home/app/storage" \
  -v "$(pwd)/public:/home/app/public" \
  springopen/springopen:1.0.0

public 目录默认不需要映射。只有需要临时替换前端文件、上传站点公开文件,或让公开资源跟随服务器目录持久化时再映射。映射空目录时,容器启动会自动复制镜像内置前端文件。

Nginx 反向代理

服务器外层有 Nginx 时,推荐 Docker 只绑定本机端口:

bash
-p 127.0.0.1:8080:80

如果只能编辑站点 server {},不能写 Nginx 全局 http {}map,可以直接使用下面配置。WebSocket 统一走 /api/ws,和普通 /api/** 合并到同一个 location /api/;局部 if 只做变量赋值,不做 rewrite / return / proxy_pass 分支。

nginx
server {
    listen 80;
    server_name your.domain.com;

    client_max_body_size 50m;

    location = /api/ws {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }

    location /api/ {
        set $spring_open_connection "";

        if ($http_upgrade != "") {
            set $spring_open_connection "upgrade";
        }

        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $spring_open_connection;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }
}

your.domain.com 改成实际域名。公网只暴露服务器 Nginx,Docker 容器端口只绑定 127.0.0.1proxy_pass http://127.0.0.1:8080; 后面不要附加 /api//api/ws,否则原始 URI 会被改写。

默认推荐显式保留 location = /api/ws,并放在普通 location /api/ 前面。这样前端默认的 ws(s)://host/api/ws?... 会被专用 WebSocket 规则接住,普通 REST API 仍走 /api/

nginx
location = /api/ws {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;
}

location /api/ {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;
}

容器内置 Nginx 采用静态优先模式:先直接读取 public/ 下的前端资源,只有 /api/**/actuator/**/swagger-ui/**/v3/api-docs** 会代理到后端应用。WebSocket 使用 /api/ws,由 /api/ 代理规则完成 101 升级。后台、App、PC、安装向导和文档站支持浏览器直接输入内部路由;/admin/app/pc/install/docs 这类裸入口会先 301 到带尾部斜杠的目录入口,避免浏览器把 ./assets/*.js 解析到站点根路径;/admin/**/app/**/pc/**/install/**/docs/** 这类无扩展名路径会回退到各自 index.html,带扩展名的静态资源不会被误回退,方便定位真实资源 404。

单独启动基础组件

如果只想本地单独启动 Redis、MySQL 或 PostgreSQL,用于 Java 进程或其他开发工具连接,可以直接使用下面命令。数据默认放在项目 docker/data/ 下,删除容器不会丢数据。

Compose 启动 MySQL + Redis

在项目根目录执行下面命令,只启动本地开发常用的 MySQL 和 Redis:

bash
docker compose -f docker/docker-compose.yml up -d mysql redis

查看两个基础组件状态:

bash
docker compose -f docker/docker-compose.yml ps mysql redis

Redis

bash
mkdir -p docker/data/redis
docker rm -f redis 2>/dev/null || true

docker run -d \
  --name redis \
  --restart unless-stopped \
  -p 6379:6379 \
  -v "$PWD/docker/data/redis:/data" \
  redis:8 \
  redis-server --appendonly yes

连接配置:

dotenv
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DATABASE=0

MySQL

bash
mkdir -p docker/data/mysql
docker rm -f mysql 2>/dev/null || true

docker run -d \
  --name mysql \
  --restart unless-stopped \
  -p 3306:3306 \
  -e MYSQL_DATABASE=spring_open \
  -e MYSQL_USER=spring_open \
  -e MYSQL_PASSWORD=spring_open \
  -e MYSQL_ROOT_PASSWORD=root \
  -e TZ=Asia/Shanghai \
  -v "$PWD/docker/data/mysql:/var/lib/mysql" \
  mysql:8.4 \
  --character-set-server=utf8mb4 \
  --collation-server=utf8mb4_unicode_ci

连接配置:

dotenv
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=spring_open
DB_USERNAME=spring_open
DB_PASSWORD=spring_open
# DB_ROOT_PASSWORD=root

检查开发库字符集和排序规则:

bash
./scripts/docker db-collation

如果库默认排序规则不是 utf8mb4_unicode_ci,只修正库默认值,不清库、不删表:

bash
./scripts/docker db-collation --fix

IDEA 或本地 Maven 正常启动不需要清空数据库。只有明确要重置开发数据时,才人工确认目标后执行显式重置命令:

bash
./scripts/docker db-reset --yes

该命令会删除并重建指定开发库,默认仍使用 utf8mb4 + utf8mb4_unicode_ci。不要把它作为日常启动步骤。

PostgreSQL

bash
mkdir -p docker/data/postgres
docker rm -f postgres 2>/dev/null || true

docker run -d \
  --name postgres \
  --restart unless-stopped \
  -p 5432:5432 \
  -e POSTGRES_DB=spring_open \
  -e POSTGRES_USER=spring_open \
  -e POSTGRES_PASSWORD=spring_open \
  -e TZ=Asia/Shanghai \
  -v "$PWD/docker/data/postgres:/var/lib/postgresql" \
  postgres:18

PostgreSQL 18 官方镜像会把数据放在 /var/lib/postgresql/18/docker 这类版本目录中, 因此宿主目录要挂载到 /var/lib/postgresql,不要挂载到旧的 /var/lib/postgresql/data

连接配置:

dotenv
DB_PORT=5432
DB_URL=jdbc:postgresql://127.0.0.1:5432/spring_open
DB_DRIVER_CLASS_NAME=org.postgresql.Driver
DB_USERNAME=spring_open
DB_PASSWORD=spring_open

如果宿主机端口已被占用,可以只改 -p 左侧端口。例如 MySQL 使用 -p 13306:3306 时,应用侧配置改为 DB_PORT=13306;容器内端口保持不变。

也可以用项目 Compose 只启动某个基础组件:

bash
docker compose -f docker/docker-compose.yml up -d mysql
docker compose -f docker/docker-compose.yml up -d redis
docker compose -f docker/docker-compose.yml --profile postgres up -d postgres

Compose 拆分部署

如果希望 MySQL、Redis、Nginx 独立成多个容器,使用 Compose:

bash
APP_SECRET='replace-with-at-least-32-random-characters' \
DB_PASSWORD='replace-with-database-password' \
DB_ROOT_PASSWORD='replace-with-root-password' \
docker compose -f docker/docker-compose.yml \
  --profile app \
  --profile nginx \
  up -d --build

如果需要本地验证 WebSocket 多实例投递,使用内置 websocket-cluster profile。该 profile 会启动 app-ws-1app-ws-2 和独立的 nginx-websocket-cluster,默认对外端口为 18080,可通过 DOCKER_WEBSOCKET_CLUSTER_NGINX_PORT 覆盖:

bash
docker compose -f docker/docker-compose.yml --profile websocket-cluster up -d --build --remove-orphans
./scripts/docker smoke --websocket-cluster --base-url http://127.0.0.1:18080
./scripts/docker websocket-cluster-acceptance --no-build

websocket-cluster-acceptance 默认跳过前端视图重建,复用当前 public/ 资产,避免 WebSocket 后端链路验收被无关视图构建阻断;如果需要完整镜像视图构建,传 --build-views

Compose 应用容器会设置:

dotenv
SPRING_OPEN_RUNTIME_MODE=app

因此应用容器只启动 Java 进程,数据库、Redis 和 Nginx 由 Compose 单独管理。

Compose Nginx 同样采用静态优先模式,并把项目根目录 public/ 挂载到 Nginx 静态根目录。Compose 应用容器会把项目根目录 storage/ 挂载到 /home/app/storage,便于联调上传文件和运行缓存;MySQL、Redis、Postgres 仍使用 docker/data/<component> 挂载到各自镜像标准数据目录。开发者在本地重新构建视图后,刷新 Nginx 即可看到最新静态资源;后端只处理 API、WebSocket、Actuator 和 OpenAPI。

常用命令:

bash
docker compose -f docker/docker-compose.yml --profile app --profile nginx ps
docker compose -f docker/docker-compose.yml --profile app --profile nginx logs -f app
docker compose -f docker/docker-compose.yml --profile app --profile nginx down

目录和配置

项目 Docker 目录:

text
docker/
├── Dockerfile
├── docker-compose.yml
├── data/
├── images/
├── nginx/
└── scripts/
路径作用
.env.example根目录本地 / Compose 示例配置,复制为 .env 后生效
docker/Dockerfile默认一体化镜像构建文件
docker/docker-compose.yml拆分式环境编排
docker/data/本地 Docker 组件数据目录;MySQL、Redis、Postgres 默认分别使用 docker/data/mysqldocker/data/redisdocker/data/postgres
docker/images/本地导出的镜像包,目录内产物不进 Git
docker/nginx/default.conf.templateNginx 唯一模板,Compose 和一体化镜像共用
docker/scripts/entrypoint一体化镜像入口脚本,负责启动内置 MySQL、Redis、Java 应用和 Nginx
scripts/docker buildDocker 一体化镜像构建与 .tar 导出脚本
scripts/docker run本机 Docker 容器构建、运行和根路径检查脚本
scripts/docker smokeDocker / Nginx / prod 安装入口静态校验,可选 HTTP 入口检查

镜像内默认目录:

路径作用
/home/app/app.jar应用启动 Jar
/home/app/public前端静态资源和公开文件
/home/app/storage应用存储、日志、上传文件、运行缓存
/home/app/docker/data/mysql一体化模式内置 MySQL 数据目录
/home/app/docker/data/redis一体化模式内置 Redis 数据目录

本地联调默认使用项目根目录:

text
storage/
public/
docker/data/mysql
docker/data/redis
docker/data/postgres

服务器部署时可把同名目录放在部署目录下;只有团队运维规范要求时再自行调整到 /opt 或其他固定路径。

常用变量:

dotenv
APP_PORT=8000

DB_DATABASE=spring_open
DB_USERNAME=spring_open
DB_PASSWORD=replace-with-strong-database-password
DB_ROOT_PASSWORD=replace-with-strong-root-password

REDIS_PASSWORD=replace-with-strong-redis-password
APP_SECRET=replace-with-at-least-32-random-characters
SPRING_OPEN_INSTALL_ENABLED=true
SPRING_OPEN_INSTALL_TOKEN=replace-with-high-entropy-install-token

# Docker / Compose 可选覆盖项。
# DOCKER_* 不是 Spring Boot 配置 key;常用默认值已在 docker-compose.yml 中定义。

DOCKER_* 只供 Docker / Compose 使用,平时不用写;只有需要改镜像名、宿主机端口、构建参数、基础组件镜像、root 密码或 JVM 参数时再在 .env 中显式覆盖。一体化模式下,DB_PORTREDIS_PORT 是容器内部端口;只有 -p 映射的 Web 端口会暴露到宿主机。生产 profile 会在启动时拦截空密钥、弱数据库密码、弱 Redis 密码和未配置令牌的安装入口;dev / test profile 保持宽松,便于本地开发和验证;lite 仅作为历史兼容和隔离诊断模式保留,不作为普通开发推荐入口。

排查

检查容器和日志:

bash
docker ps
docker logs --tail=200 springopen
docker logs -f springopen

进入容器:

bash
docker exec -it springopen bash

检查健康状态:

bash
curl -i http://127.0.0.1:8080/nginx-health
curl -i http://127.0.0.1:8080/actuator/health

清理容器但保留挂载数据:

bash
docker rm -f springopen

彻底删除数据前,先确认 storage/ 中没有需要保留的上传文件或运行缓存,并确认 docker/data/mysqldocker/data/redis 中没有需要保留的数据库或 Redis 数据。

Released under the Apache License 2.0.