写字台部署 with docker-compose.mariadb.yml

xiezitai · 2026-10-07 02:02 · 13 次阅读
cover

原打算在Oracle免费云主机上部署一个写字台,折腾了一天也没有成功,实在是国内访问甲骨文是又慢又卡,每一步都要等,有点难受。再免费,也让人抓狂。还是部署到国内的腾讯云上好了。

部署方案

compose文件

# ---------------------------------------------------------------------------
# 写字台 (xiezitai) — MariaDB 11.4 + 应用容器,专为「1G 内存的小机器」调优
#
# 什么时候用这份:
#   甲骨文云 Oracle Cloud 免费实例(E2.1.Micro 1 核 1G / A1 最低配)、1 核 1G 的 VPS、
#   树莓派这类内存吃紧的机器 —— 数据库想跑在自己机器上(不买云数据库),但又不想用
#   lite 单容器模式。编排里两个容器:mariadb:11.4 与 zhongdaiqi/xiezitai,
#   两个容器的内存相关默认值全部按 1G 收敛过,照抄即可跑起来。
#
# 五份编排的分工:
#   docker-compose.yml              app 从源码构建 + 本地 mysql:8.4    (改代码用)
#   docker-compose.hub.yml          app 用官方镜像 + 本地 mysql:8.4    (服务器省事)
#   docker-compose.lite.yml         app 单容器,内置 H2 文件库          (NAS / 最省资源)
#   docker-compose.external-db.yml  app 用官方镜像 + 你自己的外部 MySQL (云数据库)
#   docker-compose.mariadb.yml      app 用官方镜像 + 本地 MariaDB 11.4  ← 本文件(1G 调优)
#
# ── 为什么低配机选 MariaDB 而不是 MySQL 8 ──────────────────────────────────
#   • performance_schema 在 MariaDB 默认就是 OFF;MySQL 8 默认 ON,光这一项常驻
#     100~200MB,在 1G 机器上等于砍掉五分之一内存。
#   • mysqld 进程本身的基础占用更小(后台线程、内存池、innodb 相关缓冲都比 MySQL 8 少)。
#   • 11.4 是 LTS,官方镜像同时提供 amd64 与 arm64(甲骨文 A1 实例是 arm64)。
#   • 连接协议与 MySQL 兼容,应用侧一行代码都不用改(JDBC 驱动仍是 Connector/J)。
#
# ── 1G 内存怎么分(本文件的取值依据,2026-10 实机实测)──────────────────────
#   系统 + sshd + dockerd          ~200MB      不可避免的系统开销
#   MariaDB 容器(上限 320m)        ~53MB      空闲实测;随数据增长会爬向 ~200MB 的天花板
#   应用容器 JVM(上限 512m)       ~257MB      空闲实测 / 压测后 280MB(-Xmx320m + 元空间 112m)
#   留给文件缓存 / 突发的余量        ~400MB      页面缓存、上传临时文件、构建缓存
#   ────────────────────────────────────────
#   空闲合计约 510MB,连打 300 次首页后约 540MB,离 1G 仍有约 460MB 余量。
#   两个上限之和(832m)是「天花板」不是「预订量」——资源是惰性分配的。
#   注:MariaDB 的空闲值偏低是因为 InnoDB buffer pool 按需分配(用到才占),
#       数据涨到几百 MB 后会稳定在 150~200MB,仍在 320m 上限内。
#
# ⚠️ 动手前第一件事:加 swap(1G 机器最有效的一步,不加 swap 遇到瞬时高峰必被 OOM Killer 干掉)
#   sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile
#   sudo swapon /swapfile && echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
#   sudo sysctl -w vm.swappiness=10        # 平时别往下换,只在内存真紧时才用
#
# 快速开始:
#   cp .env.example .env                   # 必填 3 项:MYSQL_ROOT_PASSWORD / MYSQL_PASSWORD / XIEZITAI_JWT_SECRET
#   docker compose -f docker-compose.mariadb.yml up -d
#   docker compose -f docker-compose.mariadb.yml logs -f app     # 见 "Started XiezitaiApplication" 即成功
#   docker stats --no-stream                                     # 看两个容器真实占用
#
# 注 1:变量默认值必须写 `${VAR:-default}`(带横线)。`${VAR:default}` 是非法插值,compose 直接拒绝启动。
# 注 2:`${VAR:?提示语}` 是必填校验 —— 没值时 compose 立刻报错并原样打印提示语。
# 注 3:本文件是**单机**编排,别拿去做多实例扩展(那属于 external-db 那份的活)。
# ---------------------------------------------------------------------------

services:
  # ===========================================================================
  # MariaDB 11.4 —— 参数全部围绕「不把 1G 内存吃光」与「低 IOPS 磁盘」展开
  # ===========================================================================
  db:
    image: ${MARIADB_IMAGE:-mariadb:11.4}
    container_name: xiezitai-db
    restart: unless-stopped
    # InnoDB 需要时间刷脏页 + 归档日志收尾;给 60 秒,别让 SIGKILL 打断(下次启动要恢复)
    stop_grace_period: 60s
    environment:
      TZ: ${TZ:-Asia/Shanghai}
      MARIADB_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?请设置数据库 root 密码,例如 export MYSQL_ROOT_PASSWORD=$(openssl rand -hex 16)}
      MARIADB_DATABASE: ${MYSQL_DB:-xiezitai}
      MARIADB_USER: ${MYSQL_USER:-xiezitai}
      MARIADB_PASSWORD: ${MYSQL_PASSWORD:?请设置数据库密码,例如 export MYSQL_PASSWORD=$(openssl rand -hex 16)}
    # -------------------------------------------------------------------------
    # 调参正文。每一项都对应 MySQL/MariaDB 的一个「默认值太大」的点,
    # 注释里写了默认值是多少、为什么要动它 —— 想再省内存就照注释往下压。
    # -------------------------------------------------------------------------
    command:
      # ----- 字符集:中文 / emoji 的正确性,不能省 -----
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci

      # ----- InnoDB 内存三件套(占内存的大头)-----
      - --innodb-buffer-pool-size=96M          # 默认 128M。整个库才几十 MB,96M 足够;想更省可压到 64M
      - --innodb-buffer-pool-chunk-size=32M    # 默认 128M,比上面的 pool 还大 → 不调会被自动降级,显式给 32M
      - --innodb-buffer-pool-instances=1       # 单实例;多实例各有固定开销,小内存机器没意义
      - --innodb-log-buffer-size=8M            # 默认 16M
      - --innodb-log-file-size=48M             # 默认 100M(占磁盘,但影响启动与 checkpoint 频率)

      # ----- 其它引擎的缓存(默认值按几 GB 内存的机器定的)-----
      - --aria-pagecache-buffer-size=32M       # 默认 128M。系统表用 Aria,用不到这么大
      - --key-buffer-size=8M                   # 默认 128M。本项目没有 MyISAM 表

      # ----- 连接与线程 -----
      - --max-connections=32                   # 默认 151。每条连接都要预留排序/网络缓冲
      - --thread-cache-size=8                  # 默认 151。别一直养一堆空闲线程
      - --table-open-cache=64                  # 默认 2000
      - --table-definition-cache=256           # 默认 2000
      - --tmp-table-size=16M                   # 与下面一项保持一致,避免小查询就落磁盘临时表
      - --max-heap-table-size=16M
      - --skip-name-resolve                    # 连接时不做反向 DNS 解析,省一次查询也省一个线程

      # ----- 诊断组件:低配机上是纯浪费 -----
      - --performance-schema=OFF               # MariaDB 默认即 OFF;显式写死,防止别处配置把它打开(可达 100~200MB)

      # ----- 磁盘 IO:甲骨文免费机的块存储 IOPS 很低,控制刷盘节奏 -----
      - --innodb-flush-method=O_DIRECT         # 绕过 OS page cache,避免同一份数据缓存两次(不支持时 InnoDB 会自动退回 fsync)
      - --innodb-io-capacity=200               # 默认 200,保持低值让后台刷脏页更温和
      - --innodb-io-capacity-max=400           # 突发上限也压住,避免刷盘把 1 核 CPU 和磁盘打满

      # ----- 可选:更激进的一档(用「宕机可能丢最后 1 秒事务」换更少的 fsync)-----
      # 个人博客可接受;介意数据安全就保持注释状态(默认 1 = 每次提交都刷盘)
      # - --innodb-flush-log-at-trx-commit=2
    volumes:
      - xiezitai_db:/var/lib/mysql
    # 内存硬上限:不设的话 MariaDB 会按宿主机总内存(1G)来算,能把自己撑爆并连累系统。
    # 320m 对应上面那套参数:空闲实测 ~53MB,数据涨满后约 150~200MB,留有充足缓冲。
    mem_limit: ${DB_MEM_LIMIT:-320m}
    healthcheck:
      # 官方镜像自带 healthcheck.sh,比手搓 /dev/tcp 更准(会真的检查 InnoDB 是否初始化完)
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s
    logging:
      # ⚠️ 低配机必配:默认 json-file 不轮转,日志能把几十 G 的磁盘写满
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    # 不映射 3306 到宿主机:应用走内部网络直连,数据库没必要暴露在公网
    # (需要本机连进去调试时:docker compose -f docker-compose.mariadb.yml exec db mariadb -uroot -p)

  # ===========================================================================
  # 应用容器 —— 关键是 JVM 参数:默认按宿主机内存自动算堆,1G 机器上算出来的堆是灾难
  # ===========================================================================
  app:
    image: ${XIEZITAI_IMAGE:-zhongdaiqi/xiezitai:latest}
    container_name: xiezitai
    restart: unless-stopped
    depends_on:
      db:
        # 等到 MariaDB 真的能连上再启动应用,否则首次启动会连不上库而退出
        condition: service_healthy
    environment:
      TZ: ${TZ:-Asia/Shanghai}

      # ---------- JVM:1G 机器上最要命的一段配置 ----------
      # 不显式限制的话,JVM 默认按「容器可用内存」算堆(1G 机器上 MaxHeap 会到 256M+,
      # 再加上元空间、代码缓存、线程栈、直接内存,很容易把机器压死)。
      # • -Xmx320m  堆上限,对博客足够;-Xms96m 让启动时不一次性提交全部堆
      # • MaxMetaspaceSize  Spring Boot + JPA + Thymeleaf 的类元数据大约 90~110M,给 112m 封顶
      # • ReservedCodeCacheSize  默认 240M 是给多核大内存机器的,1 核机器 48m 够用
      # • MaxDirectMemorySize  文件/网络 NIO 用,24m 足够
      # • UseSerialGC  单核场景下最省内存的收集器(没有 GC 线程池开销),1 核机器反而更快
      # • ActiveProcessorCount=1  让 JVM 按 1 核来算各种默认线程数(否则可能按宿主机核数放大)
      # • Xss512k  线程栈减半 —— Tomcat 线程池 + JVM 内部线程数量不小,积少成多
      # • ExitOnOutOfMemoryError  真 OOM 就直接退出让 restart 策略拉起,别拖着半死不活
      JAVA_OPTS: "${JAVA_OPTS:--Xmx320m -Xms96m -XX:MaxMetaspaceSize=112m -XX:ReservedCodeCacheSize=48m -XX:MaxDirectMemorySize=24m -XX:+UseSerialGC -XX:ActiveProcessorCount=1 -Xss512k -XX:+ExitOnOutOfMemoryError -Djava.security.egd=file:/dev/./urandom}"

      # ---------- Web 容器:默认线程数是按大机器给的 ----------
      SERVER_TOMCAT_THREADS_MAX: ${TOMCAT_MAX_THREADS:-20}   # 默认 200,每个线程 ~0.5M 栈
      SERVER_TOMCAT_THREADS_MIN_SPARE: "2"                   # 默认 10,空闲时白占栈内存
      SERVER_TOMCAT_ACCEPT_COUNT: "100"                      # 默认 100,等待队列
      SERVER_TOMCAT_MAX_CONNECTIONS: "200"                   # 默认 8192,每连接都有内核缓冲

      # ---------- 数据库 ----------
      MYSQL_HOST: db                     # 同一个 compose 网络里直接用服务名
      MYSQL_PORT: "3306"
      MYSQL_DB: ${MYSQL_DB:-xiezitai}
      MYSQL_USER: ${MYSQL_USER:-xiezitai}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD:?请设置数据库密码,例如 export MYSQL_PASSWORD=$(openssl rand -hex 16)}
      SPRING_DATASOURCE_HIKARI_MAXIMUM_POOL_SIZE: ${DB_POOL_SIZE:-4}   # 默认 10;1 核机器 4 条足够,也压住 MariaDB 侧连接数
      SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE: "1"                       # 默认同 maximum;空闲时别养着 10 条连接
      # 连接串默认由 MYSQL_* 拼装(镜像内置,characterEncoding 已是 UTF-8),本编排无需额外配置。
      # 注意:在 .env 里写 SPRING_DATASOURCE_URL **在本文件不生效** —— compose 只有显式声明
      # 某变量才会把它传进容器,.env 只提供「插值用的值」。真要整条覆盖(开 SSL、加参数),
      # 把下面这行取消注释,同时在 .env / shell 里设置它(characterEncoding 只能写 UTF-8):
      # SPRING_DATASOURCE_URL: ${SPRING_DATASOURCE_URL}

      # ---------- 站点 ----------
      XIEZITAI_JWT_SECRET: ${XIEZITAI_JWT_SECRET:?请设置至少 32 位随机字符串,例如 export XIEZITAI_JWT_SECRET=$(openssl rand -hex 32)}
      XIEZITAI_SITE_URL: ${XIEZITAI_SITE_URL:-http://localhost:8080}
      XIEZITAI_UPLOAD_DIR: /app/data/uploads
      # 首次启动且库为空时写入示例内容(4 篇文章 + 关于/友链页面 + 几条评论);已有数据的库不受影响
      XIEZITAI_SEED_DEMO: ${XIEZITAI_SEED_DEMO:-true}

      # ⚠️ 可选覆盖项不要写 ${VAR:-}:空字符串会被注入容器并顶掉镜像内置默认值。
      #    需要时把下面几行取消注释并赋值(详见 docker-compose.external-db.yml 的同类说明):
      #
      # XIEZITAI_AI_BASE_URL: ${XIEZITAI_AI_BASE_URL}
      # XIEZITAI_AI_API_KEY: ${XIEZITAI_AI_API_KEY}
      # XIEZITAI_AI_MODEL: ${XIEZITAI_AI_MODEL}
      # XIEZITAI_AI_IMAGE_MODEL: ${XIEZITAI_AI_IMAGE_MODEL}
    ports:
      # 只让本机访问、由 Nginx 反代的话改成 "127.0.0.1:${APP_PORT:-8080}:8080"
      - "${APP_PORT:-8080}:8080"
    volumes:
      - xiezitai_data:/app/data
    mem_limit: ${APP_MEM_LIMIT:-512m}
    healthcheck:
      # 基础镜像自带 bash,用 bash 的 /dev/tcp 探活,不依赖 curl / wget
      test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/8080"]
      interval: 15s
      timeout: 5s
      retries: 5
      start_period: 90s        # 1 核机器启动慢,给足 90 秒别被误判为失败
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

volumes:
  xiezitai_db:      # MariaDB 数据目录 /var/lib/mysql —— 换容器务必保留
  xiezitai_data:    # 上传的图片 / 视频,容器内 /app/data

# ---------------------------------------------------------------------------
# 附 1:宿主机侧的优化(容器里改不到的,但要一起做才有效果)
#
# (1) swap —— 1G 机器必做,见文件顶部。查看:`free -h` / `swapon --show`
#     想更快可以再叠一层 zram(压缩内存盘当 swap,比磁盘 swap 快得多):
#       sudo apt install zram-tools && echo -e "ALGO=zstd\nPERCENT=50" | sudo tee /etc/default/zramswap && sudo systemctl restart zramswap
#
# (2) 甲骨文云特有的坑:安全列表放行 ≠ 机器放行
#     VCN 安全列表加了 80/443 之后,实例内的 iptables 还会拦一次(Ubuntu 镜像自带规则):
#       sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 80 -j ACCEPT
#       sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 443 -j ACCEPT
#       sudo netfilter-persistent save            # 持久化,重启不丢
#     只有 22 能通、浏览器打不开时,八成就是这一步没做。
#
# (3) 架构:甲骨文 A1(Ampere)是 arm64,E2.1.Micro 是 amd64。
#     `mariadb:11.4` 与 `zhongdaiqi/xiezitai` 都同时提供两种架构,compose 会自动挑对的,
#     不用手写 platform。想确认:`docker image inspect ... --format '{{.Architecture}}'`
#
# (4) 内核参数(1G 内存 + 小站点,重点是别让内核太激进地回收):
#       sudo tee /etc/sysctl.d/99-xiezitai.conf <<'EOF'
#       vm.swappiness=10
#       vm.overcommit_memory=1        # 允许适度超额分配,避免 JVM 预留虚拟内存时失败
#       net.core.somaxconn=512        # Tomcat 的 accept-count 受它限制,默认 128 偏小
#       EOF
#       sudo sysctl --system
#
# (5) 关掉用不上的常驻服务(Ubuntu 云镜像一般自带 snapd、unattended-upgrades 等):
#       systemctl list-units --type=service --state=running     # 先看有什么
#       sudo systemctl disable --now snapd
#
# (6) 上线后还想更省?把应用换成 lite 单容器模式(内置 H2 文件库,省掉整个 MariaDB 的
#     ~200MB),见 docker-compose.lite.yml。单机 + 单写者场景下它完全够用。
#
# 附 2:日常运维命令
#
#   看真实内存占用(最关键的一条,改完参数先用它验证):
#     docker stats --no-stream
#   看容器是否被内存限制杀掉(OOMKilled):
#     docker inspect xiezitai --format '{{.State.OOMKilled}} {{.State.ExitCode}}'
#     dmesg | grep -i 'killed process'
#   等 InnoDB 刷完再停(避免下次启动做崩溃恢复):
#     docker compose -f docker-compose.mariadb.yml stop
#   备份数据库 + 媒体文件:
#     docker compose -f docker-compose.mariadb.yml exec -T db \
#       mariadb-dump -uroot -p"$MYSQL_ROOT_PASSWORD" --single-transaction xiezitai | gzip > xiezitai-$(date +%F).sql.gz
#     docker run --rm -v xiezitai_data:/data -v "$PWD":/backup alpine \
#       tar czf /backup/xiezitai-media-$(date +%F).tgz -C /data .
#   升级应用(数据库不受影响):
#     docker compose -f docker-compose.mariadb.yml pull app && docker compose -f docker-compose.mariadb.yml up -d app
#
# 附 3:排错对照表
#
#   | 现象 | 原因 / 处理 |
#   | --- | --- |
#   | 启动即挂,报 `Unsupported character encoding 'utf8mb4'` | 用了**修复前**的旧镜像(b94efee 之前的 jar 把 JDBC URL 的 characterEncoding 写成了 utf8mb4)。Docker 不会自动更新本地镜像:`docker compose -f docker-compose.mariadb.yml pull app` 再 `up -d --force-recreate app`。确认镜像出处:`docker image inspect zhongdaiqi/xiezitai:latest --format '{{index .Config.Labels "org.opencontainers.image.revision"}}'`(要 b94efee 之后的提交) |
#   | 改了 .env 但容器行为没变 | `restart` / `start` 不会重建容器、也不重载环境变量,要用 `up -d --force-recreate`。另外宿主机 shell / 系统环境里 export 的同名变量优先级高于 .env,会把它盖掉(`env \| grep -i mysql` 查一下) |
#   | 应用容器反复重启,ExitCode 137 | 被内存限制杀了。调大 APP_MEM_LIMIT,或把 -Xmx320m 降到 256m;先看 `docker inspect` 的 OOMKilled |
#   | db 容器起不来,日志里有 unknown variable | 少见的 MariaDB 版本差异。把报错的那个 `--xxx` 参数注释掉再试 |
#   | 应用报 Can't connect to MySQL / Communications link failure | 应用启动时数据库还没就绪。正常由 depends_on: service_healthy 兜住;若手动 `up app` 绕过,等 db healthy 再起 |
#   | 应用报 Access denied for user 'xiezitai'@... | ① .env 里 MYSQL_PASSWORD 与 db 的 MARIADB_PASSWORD 不是同一个值(都取 .env 里的 MYSQL_PASSWORD);② **改过密码**:MariaDB 只在数据卷**首次初始化(空目录)**时按环境变量创建用户,之后再改 .env 不会同步进库 —— 进库 `ALTER USER 'xiezitai'@'%' IDENTIFIED BY '新密码'; FLUSH PRIVILEGES;` 同步,或删卷重建(⚠️ 清空数据) |
#   | 报 Too many connections | 应用池(DB_POOL_SIZE)与 MariaDB 的 --max-connections 一起调,保持「池 < 上限」 |
#   | 中文乱码 / 报 Incorrect string value | 库字符集与连接字符集两处都要 utf8mb4;JDBC URL 里 characterEncoding 只能写 UTF-8(写 utf8mb4 会启动失败) |
#   | 磁盘莫名写满 | 日志没轮转。本文件已配 json-file 10m×3;另检查 /var/lib/docker 与上传目录 |
#   | 数据库连不上但容器都 healthy | 本编排不暴露 3306,属预期。要调试用 `docker compose exec db mariadb -uroot -p` |
#   | 启动日志有 Unknown column 'RESERVED' / Could not obtain connection metadata | Hibernate 用 MySQL 方言去探 MariaDB 元数据时的已知噪音(HHH000339)。表照建、功能正常,**可忽略** |
#   | 启动日志有 MySQLDialect does not need to be specified explicitly | HHH90000025 提示。MariaDB 走 MySQL 方言是正确做法,同样**可忽略** |
#
# 附 4:本编排的实测数据(2026-10 实机跑出,供你对照)
#
#   环境:Docker + 本文件 + 空库首启(含示例内容 seed)
#
#   | 指标 | 空闲 | 压测后(300 次首页 + 60 次 API) |
#   | --- | --- | --- |
#   | app 容器内存 | 256.8 MiB | 280.3 MiB |
#   | db 容器内存 | 52.7 MiB | 53.0 MiB |
#   | app 启动耗时 | 14.9 秒(单核机器会更久,故 start_period 给 90 秒) | — |
#   | OOMKilled / Restarts | false / 0 | false / 0 |
#
#   参数确认生效(`docker exec xiezitai-db mariadb -uroot -p -e "show variables like '...'"`):
#     innodb_buffer_pool_size = 100663296 (96M)   max_connections = 32
#     performance_schema     = OFF                aria_pagecache_buffer_size = 32M
#     key_buffer_size        = 8388608 (8M)
#
#   功能确认:库字符集 utf8mb4 / utf8mb4_unicode_ci;中文标题 char_length 精确;
#   自动建表 7 张(articles / xiezitai_pages / comments / users / files / request_logs / sys_configs);
#   示例内容 4 篇文章 + 2 页面 + 5 评论全部就位。
# ---------------------------------------------------------------------------

配置文件

# =============================================================================
# 写字台 (xiezitai) — 环境变量模板
#
# 用法:
#   cp .env.example .env        然后编辑 .env 把需要的项填上
#   docker compose -f docker-compose.xxx.yml up -d
#
# 说明:
#   • .env 会被 docker compose 自动读取,只用于**变量替换**,不会整包注入容器
#     (比 env_file 干净);该文件已在 .gitignore 里忽略,不会误提交。
#   • 不想用 .env 就直接 export 同名变量,两者等价。
#   • 五份 compose 共用同一套变量名,改一处通用;用不到的项留着不影响。
#   • 值里有特殊字符时:`$` 要写成 `$$`(compose 会再解析一次);
#     含 `#` 或空格的值用引号包起来,例如 MYSQL_PASSWORD="ab#cd ef"。
# =============================================================================

# ------------------------------ 站点 ------------------------------
# 站点对外地址,影响 sitemap.xml / canonical / OG 标签里的绝对链接
XIEZITAI_SITE_URL=https://xiezitai.cn

# JWT 签名密钥,至少 32 位随机串。生成:openssl rand -hex 32
# ⚠️ 必填(external-db 那份没填会直接报错拦住)。换掉后已登录会话全部失效。
XIEZITAI_JWT_SECRET=

# 应用对外端口(容器内固定监听 8080)
APP_PORT=8080

# 固定镜像版本便于回滚(不填跟随 latest)
# XIEZITAI_IMAGE=zhongdaiqi/xiezitai:latest

# ---------------------- 数据库(外部 / 云库) ----------------------
# docker-compose.external-db.yml 用这一组,两项必填:
#   云数据库   → 优先填控制台里的「内网地址」(同 VPC 更快更安全),跨公网才用外网地址
#   宿主机自装 → 填 host.docker.internal
#   同机容器   → 填对方容器名(如 mysql),并保证两者在同一个 docker 网络
MYSQL_HOST=xiezitai-db
MYSQL_PORT=3306
MYSQL_DB=xiezitai
MYSQL_USER=xiezitai
MYSQL_PASSWORD=newmysql

# 本地数据库容器使用的 root 密码
#   docker-compose.yml / docker-compose.hub.yml → mysql:8.4
#   docker-compose.mariadb.yml                  → mariadb:11.4(已按 1G 内存调优)
MYSQL_ROOT_PASSWORD=rootroot

# 连接池上限(应用默认 10)。云库有连接数上限时按「实例数 × 池大小 < 上限」下调;
# docker-compose.mariadb.yml 已默认收敛到 4
# DB_POOL_SIZE=10

# 需要开 SSL、加参数时整条 URL 覆盖(详见 external-db 文件末尾注释)。
# 注意 characterEncoding 只能写 UTF-8(写 utf8mb4 会启动失败)。
# SPRING_DATASOURCE_URL=jdbc:mysql://xiezitai-db:3306/xiezitai?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&sslMode=REQUIRED
SPRING_DATASOURCE_URL=jdbc:mysql://xiezitai-db:3306/xiezitai?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true

# ------------------ 低配机器(1 核 1G,docker-compose.mariadb.yml) ------------------
# 以下都有针对 1G 内存调好的默认值,**一般不用改**;只有想调松/调紧时才取消注释。
# 实测:db 空闲 ~53MB / app 空闲 ~257MB,两容器合计约 510MB,1G 机器有充裕余量。
#
# MariaDB 镜像标签(想钉版本时改)
# MARIADB_IMAGE=mariadb:11.4
# 两个容器的内存硬上限(天花板,不是预订量)
# DB_MEM_LIMIT=320m
# APP_MEM_LIMIT=512m
# JVM 参数。嫌启动慢可调大 -Xmx;想更省内存就压到 256m
# JAVA_OPTS=-Xmx320m -Xms96m -XX:MaxMetaspaceSize=112m -XX:ReservedCodeCacheSize=48m -XX:MaxDirectMemorySize=24m -XX:+UseSerialGC -XX:ActiveProcessorCount=1 -Xss512k -XX:+ExitOnOutOfMemoryError -Djava.security.egd=file:/dev/./urandom
# Tomcat 最大工作线程数(默认 200,低配机收到 20)
# TOMCAT_MAX_THREADS=20

# -------------------- lite 单容器模式(内置 H2 文件库) --------------------
# 一般不用动,仅当要换数据文件位置时才改;容器内默认 /app/data/db/xiezitai
# XIEZITAI_DB_PATH=/app/data/db/xiezitai

# ------------------------------ 内容 ------------------------------
# 首次启动且库为空时写入示例内容(4 篇文章 + 关于/友链页面 + 几条评论);
# 已有数据的库不受影响,写过一次就不再重复写。不想要就改 false。
XIEZITAI_SEED_DEMO=true

# ---------------------------- 大模型(可选) ----------------------------
# 留空 = 用镜像内置的魔搭 ModelScope 默认配置(首次启动写入后台「设置」页)。
# 想换自己的接口,登录后台「设置」里改更省事(存库、优先级更高、不用重启)。
# XIEZITAI_AI_BASE_URL=https://api-inference.modelscope.cn/v1
# XIEZITAI_AI_API_KEY=ms-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# XIEZITAI_AI_MODEL=Qwen/Qwen3.8-27B
# XIEZITAI_AI_IMAGE_MODEL=Qwen/Qwen-Image-2.1

# ------------------------------ 其它 ------------------------------
# 上传媒体文件在容器内的落盘目录(已由 compose 固定,一般不用改)
# XIEZITAI_UPLOAD_DIR=/app/data/uploads
# TZ=Asia/Shanghai

踩坑

甲骨文免费云主机

使用cloudflare的WARP访问,慢。关掉WARP,直接打不开。相当于免费的Oracle主机在国内无法正常访问。通过腾讯云国际版本EdgeOne加速后,站点有的能打开,有的打不开。

mysql vs mariadb

本地是mysql8.4,考虑到服务器的内存有限,oracle免费云主机才1G内存,就换成了mariadb,并让AI结合有限的内存进行了专项优化。

mariadb链接问题

mariadb镜像启动后,宿主机上有了db文件,数据库的密码就固定了,再修改docker compose env配置,跑docker compose编排就会报数据库登陆失败。得把宿主机上的数据删除重新操作,或者登陆到数据库机器里面修改密码。如果是全新docker compose编排不会遇到这个问题。我是之前一直在调整,想着换个密码,把自己绕进去了。在腾讯云部署比较顺利。

免费ssl证书

腾讯云edgeOne界面选择免费证书,生成的证书是WoTrus CA Limited签发的,谷歌浏览器提示不安全。我换成腾讯云ssl界面申请的证书,是TrustAsia TLS RSA Root CA & Certum Trusted Network CA签发的。谷歌浏览器显示正常。

评论

还没有评论,登录后来说两句。