qpixel 0.13.0 Docker Compose 部署指南
qpixel v0.13.0 官方源码 compose 三服务栈部署实录:bullseye EOL 的 apt 修复、MySQL 数据目录初始化双坑排障、健康检查编排、双层环境变量体系与等价 docker run,HTTP/数据层验证回显。
qpixel 0.13.0 Docker Compose 部署指南
目标:在 Linux 宿主机上用官方源码仓库自带的 docker-compose.yml,把 qpixel v0.13.0(Codidact 问答平台,Rails 8.1.3.1 + MySQL 8.4 + Redis)三服务栈完整拉起并通过 HTTP/数据层验证。本文全部命令与回显均为 2026-11-02 实测,含构建与数据库初始化两次真实故障的完整排障实录。
一、环境信息
- 操作系统:Ubuntu 系 Linux(x86_64)
- 容器运行时:Docker 29.9.2(storage driver overlayfs,runc)
- 编排工具:Docker Compose v5.6.1(
docker compose version实测回显:Docker Compose version v5.6.1) - 软件版本:qpixel v0.13.0(官方最新稳定版,GitHub Release 2026-09-12 发布,2026-11-02 查询;认知与选型见《qpixel 介绍与选型指南》)
- 应用栈技术组成(启动日志实测):Rails 8.1.3.1、Ruby 3.4.5、Puma 7.2.1、MySQL 8.4.2、Redis
- 部署根目录:
/opt/data/quzuo/tmp/qpixel/qpixel-0.13.0(v0.13.0 归档包解包目录,即 compose 文件所在的应用根) - compose 项目名:
qpixel-0130-stack(compose 文件写name: qpixel-0.13.0-stack,Docker 归一化去掉点号后落到资源名前缀) - 网络:
qpixel-v0.13.0-net,自定义 bridge,显式子网10.89.68.0/24 - Web 映射:宿主
8131→ 应用3000(8128–8152 段内取空闲端口,ss -ltn预检) - 初始社区:
Dev Community;演示账号admin/q1w2e3r4(全局管理员,admin@example.com) - 运行环境:
RAILS_ENV=development(官方 compose 路线即开发模式,见文末官方说明)
三服务一览(docker compose ps 实测回显):
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
qpixel-0130-stack-db-1 qpixel-0130-stack-db "/bin/bash /docker/e…" db About an hour ago Up About an hour (healthy) 3306/tcp, 33060/tcp
qpixel-0130-stack-redis-1 redis:latest "docker-entrypoint.s…" redis About an hour ago Up About an hour (healthy) 6379/tcp
qpixel-0130-stack-uwsgi-1 qpixel-0130-stack-uwsgi "/bin/bash /code/doc…" uwsgi About an hour ago Up About an hour 80/tcp, 443/tcp, 0.0.0.0:8131->3000/tcp, [::]:8131->3000/tcp
二、镜像选型说明
qpixel 不发布官方运行时镜像,官方部署路线(仓库 docker/README.md)是拿源码包自带的 docker-compose.yml 本地构建两个镜像,Redis 直接用官方镜像:
| 服务 | 镜像 | 来源 | 基础镜像 | 实测占用 |
|---|---|---|---|---|
db | qpixel-0130-stack-db | 仓库 docker/Dockerfile.db 构建 | mysql:8.4.2 | 800MB |
redis | redis:latest | Docker Hub 官方镜像直接拉取 | — | — |
uwsgi | qpixel-0130-stack-uwsgi | 仓库 docker/Dockerfile 构建(CLIENT_DOCKERFILE 指定) | ruby:3.4.5-bullseye + 从 node:12.18.3-slim 拷入 Node/Yarn | 2.23GB |
(占用为 docker images 实测 SIZE 列。)
两个自建镜像的要点:
- db:
Dockerfile.db全文只有 4 行——FROM mysql:8.4.2、COPY docker/mysql-init.sql /docker-entrypoint-initdb.d/、ENTRYPOINT ["/bin/bash"]、CMD ["/docker/entrypoint.sh"]。注意它把 ENTRYPOINT 改成了 bash,真正的启动命令是 compose 绑挂进来的docker/db-entrypoint.sh(见第七章),这直接导致了后文「首次 up 数据库起不来」的坑。 - uwsgi:服务名叫 uwsgi 是历史遗留,实际进程是 Puma(启动日志
=> Booting Puma)。docker/Dockerfile为多阶段构建:ruby:3.4.5-bullseye装系统依赖和 gem(bundle install),再从node:12.18.3-slim挑文件拷入 node/npm/yarn(前端资产编译用)。 - 构建配置二选一:
CLIENT_DOCKERFILE默认指docker/Dockerfile(类生产配置,起服务);另有docker/Dockerfile.dev(本地开发配置,内置 Firefox,但不自动起 Rails,需手动rails server -b 0.0.0.0)。本文用默认值。 - ⚠️ bullseye 已 EOL:
ruby:3.4.5-bullseye的 apt 源指向deb.debian.org,Debian 11 归档后该源 404,官方 Dockerfile 原样构建必失败,必须先做第四章 4.5 节的源修复。
三、前置条件
docker compose version # 要求 2.x+(本文 v5.6.1)
docker info >/dev/null && echo docker-ok # docker daemon 在跑
ss -ltn | grep ':8131' || echo port-8131-free # Web 端口空闲
- 宿主机已装 Docker Engine 与 compose plugin(官方 README 提示 Debian 系可
sudo apt-get install docker-compose-plugin)。 - 构建需要外网:拉
ruby:3.4.5-bullseye、node:12.18.3-slim、mysql:8.4.2、redis:latest四个基础镜像,构建中访问archive.debian.org(修复后)、RubyGems 与 npm 源。 - 磁盘余量 ≥ 5GB(两个产物镜像实测合计约 3GB,加构建缓存与 MySQL 数据目录)。
- 自定义网络显式指定子网(本文
10.89.68.0/24),避免与同宿主机其他栈冲突。
四、部署步骤
4.1 获取 v0.13.0 源码归档
qpixel 官方 compose 路线要求源码目录整体在场(compose 把源码目录 bind 进应用当运行目录),用 Git tag 对应的归档包:
cd /opt/data/quzuo/tmp/qpixel
curl -sSL -o qpixel-v0.13.0.tar.gz https://codeload.github.com/codidact/qpixel/tar.gz/refs/tags/v0.13.0
tar xzf qpixel-v0.13.0.tar.gz
实测:归档 4,205,661 字节,顶层目录 qpixel-0.13.0/;下载 URL 当日 HEAD 请求回显 HTTP/2 200。
4.2 一键初始化配置文件(local-setup.sh)
官方脚本把 5 个样例文件复制为正式配置:
cd qpixel-0.13.0
chmod +x docker/local-setup.sh
docker/local-setup.sh
脚本内容(实测 cat):
#!/bin/bash
cp ./docker/dummy.env ./docker/env
cp ./docker/compose-env .env
cp config/database.docker.yml config/database.yml
cp config/storage.docker.yml config/storage.yml
cp ./.sample.irbrc ./.irbrc
即:.env(compose 插值层)来自 docker/compose-env,docker/env(注入应用的密钥层)来自 docker/dummy.env,config/database.yml、config/storage.yml 来自对应 .docker.yml 模板。
4.3 调整 .env(compose 插值层)
实测修改后的 .env 全文:
COMPOSE_FILE=./docker-compose.yml
LOCAL_DEV_PORT=8131
COMMUNITY_NAME=Dev Community
MAILER_PROTOCOL=https
RAILS_ENV=development
CONFIRMABLE_ALLOWED_ACCESS_DAYS=2
ENV_FILE_LOCATION=./docker/env
CLIENT_DOCKERFILE=docker/Dockerfile
与默认 compose-env 的差异只有 LOCAL_DEV_PORT(默认 3000 → 8131)。官方 README 特别强调:编辑 .env 只影响 compose 文件里的插值变量,不会改变运行环境内的环境变量;后者要改 docker/env。
4.4 调整 docker/env(应用密钥层)
docker/dummy.env 只带 4 个 MySQL 变量,管理员三件套需补上。实测最终文件全文:
MYSQL_ROOT_PASSWORD=qpixel
MYSQL_DATABASE=qpixel
MYSQL_USER=qpixel
MYSQL_PASSWORD=qpixel
COMMUNITY_ADMIN_USERNAME=admin
COMMUNITY_ADMIN_PASSWORD=q1w2e3r4
COMMUNITY_ADMIN_EMAIL=admin@example.com
官方 README 要求 COMMUNITY_ADMIN_PASSWORD 至少 6 字符,否则初始管理员不会创建(见第十一章 Q4)。
4.5 修复 Dockerfile 的 EOL apt 源
直接 docker compose build 第一次失败,回显节选(build.log 实录):
18.72 E: Failed to fetch http://deb.debian.org/debian-security/pool/updates/main/libf/libfcgi/libfcgi0ldbl_2.4.2-2%2bdeb11u1_amd64.deb 404 Not Found [IP: 146.75.122.132 80]
18.73 E: Failed to fetch http://deb.debian.org/debian-security/pool/updates/main/libx/libxslt/libxslt1-dev_1.1.34-4%2bdeb11u3_amd64.deb 404 Not Found [IP: 146.75.122.132 80]
18.73 E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
------
Dockerfile:10
--------------------
10 | >>> RUN apt-get update && \
11 | >>> apt-get install -y bison \
--------------------
target uwsgi: failed to solve: process "/bin/sh -c apt-get update && ..." did not complete successfully: exit code: 100
BUILD_EXIT=1
原因:bullseye(Debian 11)EOL,其包已从 deb.debian.org 移除。给 docker/Dockerfile 的 apt 安装步骤前插入两行修复(sed 换 archive 源 + 关闭有效期检查):
RUN sed -i 's|http://deb.debian.org/debian-security|http://archive.debian.org/debian-security|; s|http://deb.debian.org/debian|http://archive.debian.org/debian|g' /etc/apt/sources.list \
&& echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf.d/99no-check-valid-until \
&& apt-get update && \
apt-get install -y bison \
...
4.6 构建
docker compose build
第二次构建成功(build2.log 回显节选):
#36 [uwsgi] exporting to image
#36 naming to docker.io/library/qpixel-0130-stack-uwsgi:latest done
#36 unpacking to docker.io/library/qpixel-0130-stack-uwsgi:latest 5.9s done
#37 [uwsgi] resolving provenance for metadata file
#37 DONE 0.0s
Image qpixel-0130-stack-db Built
Image qpixel-0130-stack-uwsgi Built
BUILD_EXIT=0
只重建单个服务可用 docker compose build uwsgi / docker compose build db。
4.7 启动(含一次数据库初始化故障实录)
docker compose up -d
首败:db 起不来,日志报:
mysqld: File './binlog.index' not found (OS errno 13 - Permission denied)
原因:compose 把宿主 bind 目录 docker/mysql 挂到 /var/lib/mysql,该目录属 root,而 MySQL 进程 uid=999。处理:
chown -R 999:999 docker/mysql
仍 unhealthy,新报错:
File ./ibdata1: 'open' returned OS error 71
原因(读 docker/db-entrypoint.sh 定位):qpixel 的 db 镜像把 ENTRYPOINT 换成了 bash,db-entrypoint.sh 直接裸跑 mysqld,完全绕开了官方 mysql 镜像的初始化流程——空数据目录里没有 ibdata1 可谈。官方镜像初始化必须借道完成一次:
rm -rf docker/mysql/*
docker run --rm -v "$(pwd)/docker/mysql:/var/lib/mysql" \
-e MYSQL_ROOT_PASSWORD=qpixel -e MYSQL_DATABASE=qpixel \
-e MYSQL_USER=qpixel -e MYSQL_PASSWORD=qpixel \
mysql:8.4.2
回显节选:
[Note] [Entrypoint]: Initializing database files
[Warning] [MY-010453] root@localhost is created with an empty password ! ...
[Note] [Entrypoint]: Creating database qpixel
[Note] [Entrypoint]: Creating user qpixel
[Note] [Entrypoint]: MySQL init process done. Ready for start up.
/usr/sbin/mysqld: ready for connections. Version: '8.4.2' ... port: 3306
(该一次性进程跑完自动退出,数据文件已落在 bind 目录。)随后再次 docker compose up -d,三服务全部起来,db/redis 状态 healthy。
4.8 应用层初始化(自动)
uwsgi 的启动脚本 docker/entrypoint.sh 首次运行会串完整个建库流程(实测日志 uwsgi-init.log 节选):
Created database 'qpixel_dev'
Created database 'qpixel_test'
PostType: created 5
CloseReason: created 5
License: created 5
TagSet: created 2
PostHistoryType: created 16
User: created 1
Ability: created 7
CommunityUser: created 1
Filter: created 4
Category: created 2
PostFlagType: created 5
Post: created 23
ReactionType: created 3
SiteSetting: skipped 112
=> Booting Puma
=> Rails 8.1.3.1 application starting in development
Puma starting in single mode...
* Puma version: 7.2.1 ("On The Corner")
* Ruby version: ruby 3.4.5 (2025-07-16 revision 20cda200d3) +PRISM [x86_64-linux]
* Min threads: 5
* Max threads: 5
* Environment: development
* PID: 104
* Listening on http://0.0.0.0:3000
(SiteSetting: skipped 112 是 entrypoint 设计里第二次 rails db:seed 的输出——种子幂等跳过,属正常。)
4.9 验证
curl -sS -o /dev/null -w "HTTP %{http_code}\n" http://localhost:8131/
实测回显:
HTTP 200
页面标题实测:[DEV] Q&A - QPixel。数据层验证(rails runner,实测):
docker compose exec -T uwsgi rails runner 'puts Community.first.name'
# => Dev Community
docker compose exec -T uwsgi rails runner 'u = User.find_by(username: "admin"); puts "admin user: id=#{u.id} global_admin=#{u.is_global_admin} email=#{u.email}"'
# => admin user: id=1 global_admin=true email=admin@example.com
邮件预览入口实测:curl -sS -o /dev/null -w "HTTP %{http_code}" http://localhost:8131/letter_opener → HTTP 200。
浏览器打开 http://localhost:8131,Sign in 用 admin / q1w2e3r4 登录。
4.10 部署后必做的分类配置
官方 README 明确:发帖前必须给每个分类绑定 Tag Set,否则无法发帖。进 /categories/,对每个分类点 edit,在 "Tag Set" 字段选择(如 Meta 分类选 "Meta"、Q&A 分类选 "Main"),保存。然后即可建帖。
五、数据持久化说明
| 数据 | 落点 | 持久化方式 |
|---|---|---|
| MySQL 全部库(qpixel_dev/qpixel_test 及 binlog、ibdata1) | 宿主 ./docker/mysql | bind mount → /var/lib/mysql,down/重建镜像均不丢 |
| 应用源码(即运行代码本体) | 宿主 ./(部署根) | bind mount → /code,改代码重启即生效 |
| 静态资产 | ./static | bind mount → /var/www/static |
| 上传图片 | ./images | bind mount → /var/www/images |
| Redis | 无卷 | 仅作缓存/队列,重启清空可接受 |
首次初始化标记 /db-created | 应用运行环境文件系统内 | 不持久。镜像重建后 entrypoint 会重跑 db:create/db:schema:load/种子(种子实测幂等:Post: skipped 23、SiteSetting: skipped 112) |
备份口径:停栈后直接 rsync ./docker/mysql 即可整库冷备;热备走 mysqldump 或仓库自带 scripts/database_backup.rb(默认注释停用,见《qpixel 0.13.0 常用 CLI 命令与工具详解》)。
六、环境变量表
6.1 .env(compose 插值层)
| 变量 | 本文取值 | 默认(compose-env) | 作用 |
|---|---|---|---|
COMPOSE_FILE | ./docker-compose.yml | 同左 | compose 入口文件,可换自定义编排 |
LOCAL_DEV_PORT | 8131 | 3000 | 宿主映射端口("${LOCAL_DEV_PORT}:3000") |
COMMUNITY_NAME | Dev Community | Dev Community | 初始社区名(仅数据库初始化时消费) |
MAILER_PROTOCOL | https | https | 邮件链接协议 |
RAILS_ENV | development | development | Rails 环境 |
CONFIRMABLE_ALLOWED_ACCESS_DAYS | 2 | 2 | 未确认账号允许访问天数 |
ENV_FILE_LOCATION | ./docker/env | 同左 | 密钥文件位置 |
CLIENT_DOCKERFILE | docker/Dockerfile | 同左 | uwsgi 构建用 Dockerfile(可换 docker/Dockerfile.dev) |
6.2 docker/env(env_file 注入 db 与 uwsgi)
| 变量 | 本文取值 | 必需 | 作用 |
|---|---|---|---|
MYSQL_ROOT_PASSWORD | qpixel | 是 | root 口令(初始化用) |
MYSQL_DATABASE | qpixel | 是 | 初始化库名 |
MYSQL_USER / MYSQL_PASSWORD | qpixel / qpixel | 是 | 应用连接账号(与 config/database.yml 一致) |
COMMUNITY_ADMIN_USERNAME | admin | 是* | 初始管理员用户名(仅建库时用) |
COMMUNITY_ADMIN_PASSWORD | q1w2e3r4 | 是* | 初始管理员口令,≥6 字符 |
COMMUNITY_ADMIN_EMAIL | admin@example.com | 是* | 初始管理员邮箱 |
(* 官方 README 标注 "Only required on database init"。)
6.3 应用内实测注入清单
uwsgi 运行环境 env 实测(节选):
COMMUNITY_ADMIN_EMAIL=admin@example.com
COMMUNITY_ADMIN_PASSWORD=q1w2e3r4
COMMUNITY_ADMIN_USERNAME=admin
COMMUNITY_NAME=Dev Community
CONFIRMABLE_ALLOWED_ACCESS_DAYS=2
LOCAL_DEV_PORT=8131
MAILER_PROTOCOL=https
RAILS_ENV=development
6.4 代码有默认值、本文未注入的可选变量
| 变量 | 默认值 | 出处(源码实测) |
|---|---|---|
PORT | 3000 | config/puma.rb |
RAILS_MAX_THREADS / RAILS_MIN_THREADS | 5 | config/puma.rb |
PIDFILE | tmp/pids/server.pid | config/puma.rb |
WEB_CONCURRENCY | 2(该行被注释,未启用) | config/puma.rb |
REDIS_URL | redis://localhost:6379/1 | config/cable.yml |
MAILER_DELIVERY_METHOD | 未设则 :letter_opener_web | config/environments/development.rb |
MAILER_HOST | meta.codidact.com | config/environments/development.rb |
ALL_REQUESTS_LOCAL | true | config/environments/development.rb |
PERFORM_CACHING / LOG_LEVEL / RAISE_DELIVERY_ERRORS | 未设走代码默认 | config/environments/development.rb |
参数语义与调优口径详见《qpixel 0.13.0 配置参数详解》。
七、配置参数说明(compose 编排层)
docker-compose.yml 全文实测要点:
name: qpixel-0.13.0-stack
services:
db:
restart: on-failure:3
build: { context: ".", dockerfile: docker/Dockerfile.db }
volumes:
- ./docker/db-entrypoint.sh:/docker/entrypoint.sh
- ./docker/mysql:/var/lib/mysql
env_file: [ ${ENV_FILE_LOCATION} ]
cap_add: [ SYS_NICE ]
healthcheck:
test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD
start_period: 5s
interval: 5s
timeout: 5s
retries: 12
uwsgi:
restart: on-failure:3
build: { context: ".", dockerfile: ${CLIENT_DOCKERFILE} }
depends_on:
db: { condition: service_healthy }
redis: { condition: service_healthy }
ports: [ "${LOCAL_DEV_PORT}:3000" ]
volumes:
- .:/code
- ./static:/var/www/static
- ./images:/var/www/images
links: [ redis, db ]
redis:
restart: on-failure:3
image: redis:latest
healthcheck: { test: ["CMD", "redis-cli", "ping"] }
networks:
default:
name: qpixel-v0.13.0-net
ipam: { config: [ { subnet: 10.89.68.0/24 } ] }
- 启动顺序靠健康检查把关:
depends_on ... condition: service_healthy,db 用mysqladmin ping($$是 compose 转义,取容器内环境变量),12 次×5s 重试给足 MySQL 初始化时间。 cap_add: SYS_NICE:MySQL 8 调整调度优先级需要,缺省会刷告警。- db 启动命令(
docker/db-entrypoint.sh全文实测):
#!/bin/bash
mysqld --init-file=/docker-entrypoint-initdb.d/mysql-init.sql \
--mysql-native-password=on \
--skip-mysqlx
--mysql-native-password=on 兼容 mysql2 gem 老认证握手;--skip-mysqlx 关掉 X 协议(33060 端口仅监听不服务);--init-file 执行 docker/mysql-init.sql 授权(实测内容:对 qpixel_dev/qpixel_test/qpixel_dump/qpixel 四库 GRANT ALL ON ... TO qpixel)。
- uwsgi 的 entrypoint(
docker/entrypoint.sh):无/db-created标记时依次跑rails db:create→rails db:schema:load→rails r db/scripts/create_tags_path_view.rb→rails db:migrate(两遍,第二遍显式RAILS_ENV=development)→rails r docker/create_admin_and_community.rb→UPDATE_POSTS=true rails db:seed,然后再跑一遍rails db:seed(脚本注释:不重跑会在首页 500),最后rails server -b 0.0.0.0。 - 初始管理员创建逻辑(
docker/create_admin_and_community.rb):四个必需 ENV 缺任一即打印缺失项并exit 1;社区host写成localhost:${LOCAL_DEV_PORT},用户直接以is_global_admin: true, is_global_moderator: true, staff: true, confirmed_at: DateTime.now落库(免邮箱确认)。
八、配置文件挂载
| 宿主文件 | 挂载点 | 生效方式 |
|---|---|---|
.env | 不挂载(compose 启动时读取做插值) | 改后需 docker compose up -d 重建才生效(插值发生在编排层) |
docker/env | 不挂载(env_file 注入进程环境) | 改后 docker compose up -d --force-recreate 对应服务 |
docker/db-entrypoint.sh | db:/docker/entrypoint.sh | 改后重启 db 服务 |
config/database.yml、config/storage.yml | 随源码目录整体挂载进 /code | 改后重启 uwsgi 服务(Rails 启动时读取) |
static/、images/ | /var/www/static、/var/www/images | 文件级即时生效 |
config/database.yml 实测全文(由 database.docker.yml 模板复制):
default: &default
adapter: mysql2
encoding: utf8mb4
collation: utf8mb4_unicode_ci
host: db
port: 3306
username: qpixel
password: qpixel
development:
<<: *default
database: qpixel_dev
test:
<<: *default
database: qpixel_test
production:
<<: *default
database: qpixel
redis_default: &redis_default
host: redis
port: 6379
redis_development:
<<: *redis_default
redis_test:
<<: *redis_default
redis_production:
<<: *redis_default
要点:host: db / host: redis 是 compose 服务名解析;username/password 必须与 docker/env 一致(官方 README 第 2 步专门提醒)。
九、等价 docker run
不使用 compose 时的等价三条原生命令(网络、卷、端口与编排一致;db 的健康门控需改为手工确认起后再拉 uwsgi):
docker network create --subnet 10.89.68.0/24 qpixel-v0.13.0-net
docker run -d --name qp-db \
--network qpixel-v0.13.0-net \
--cap-add SYS_NICE \
--env-file ./docker/env \
-v "$(pwd)/docker/db-entrypoint.sh:/docker/entrypoint.sh" \
-v "$(pwd)/docker/mysql:/var/lib/mysql" \
qpixel-0130-stack-db
docker run -d --name qp-redis \
--network qpixel-v0.13.0-net \
redis:latest
docker run -d --name qp-app \
--network qpixel-v0.13.0-net \
-p 8131:3000 \
--env-file ./docker/env \
-e COMMUNITY_NAME="Dev Community" \
-e RAILS_ENV=development \
-e MAILER_PROTOCOL=https \
-e CONFIRMABLE_ALLOWED_ACCESS_DAYS=2 \
-e LOCAL_DEV_PORT=8131 \
-v "$(pwd):/code" \
-v "$(pwd)/static:/var/www/static" \
-v "$(pwd)/images:/var/www/images" \
qpixel-0130-stack-uwsgi
注意 --env-file 只能注入 KEY=VALUE 平面变量,compose 里 ${LOCAL_DEV_PORT} 这类插值仍需 .env 在场(构建期);换端口时 LOCAL_DEV_PORT 与 -p 映射要保持一致(初始社区 host 由它拼出)。
十、常用运维命令
cd /opt/data/quzuo/tmp/qpixel/qpixel-0.13.0
docker compose ps # 三服务状态(本文第一章回显)
docker compose logs -f --tail 50 uwsgi # 跟踪应用日志(Puma 访问/报错)
docker compose logs --tail 30 db # 查看 MySQL 日志
docker compose restart uwsgi # 改 config/*.yml、代码后重启应用
docker compose exec -T uwsgi rails runner '<Ruby 代码>' # 数据层操作入口
docker compose exec -T db sh -c 'mysql -uqpixel -pqpixel qpixel_dev -e "SHOW TABLES"' # 直查库
docker compose stop / start # 停/起(数据保留)
docker compose down # 删容器与网络(bind 数据保留)
docker compose down -v # 本栈无命名卷,效果同 down;数据在 ./docker/mysql,删它才是清库
十一、常见问题
Q1:docker compose build 在 apt 步骤报一堆 404。
A:bullseye EOL,deb.debian.org 已移除其包。按 4.5 节换 archive.debian.org 并关闭 Check-Valid-Until。本文实测第一次 build 因此失败(exit code: 100),修复后 BUILD_EXIT=0。
Q2:首次 up 后 db 一直 unhealthy,日志 File './binlog.index' not found (OS errno 13 - Permission denied)。
A:bind 数据目录属 root 而 MySQL 进程 uid=999。chown -R 999:999 docker/mysql。
Q3:chown 后仍起不来,报 File ./ibdata1: 'open' returned OS error 71。
A:qpixel 的 db 镜像 ENTRYPOINT 被改成 bash 裸跑 mysqld,不会自动初始化空数据目录。按 4.7 节用官方 mysql:8.4.2 镜像带同样 bind 目录跑一次初始化(Initializing database files → MySQL init process done),再 up -d。
Q4:登录页用 admin 登不进去。
A:检查 COMMUNITY_ADMIN_PASSWORD 是否 ≥6 字符——官方 README 明说口令过短则用户根本不会创建;另外 entrypoint 里四个必需 ENV 缺任一,创建脚本会直接 exit 1(打印 XXX is required)。
Q5:首页 500,报 posts 相关错误。
A:entrypoint 源码注释写明:rails db:seed 不跑第二遍就会在首页 500。手工补一次:docker compose exec -T uwsgi rails db:seed。
Q6:注册/发帖按钮不可用。 A:先完成 4.10 节分类 Tag Set 配置;帖子正文/标题有字符要求且至少一个标签(官方 README 第 7 步)。
Q7:收不到确认邮件。
A:该编排默认不发真邮件,letter_opener_web 拦截,浏览器开 http://localhost:8131/letter_opener 查看(实测 HTTP 200)。
Q8:每次执行 rails/rake 命令都刷 fatal: not a git repository 和 To use retry middleware with Faraday v2.0+...。
A:正常噪音。前者因 config/initializers/zz_cache_setup.rb 调 git rev-parse 取版本信息而源码是 tar 包解出(无 .git);后者是 Faraday v2 的 gem 提示。读回显直接跳过。
Q9:改端口后页面跳转/邮件链接端口不对。
A:初始社区的 host 在建库时按 localhost:${LOCAL_DEV_PORT} 写死进 communities 表(docker/create_admin_and_community.rb),换端口需同步更新该记录(rails runner 改 Community.first.update(host: ...))。
十二、参考链接
- qpixel 仓库(含 docker-compose.yml 与全部 Dockerfile):https://github.com/codidact/qpixel
- 官方 Docker 安装说明:https://github.com/codidact/qpixel/blob/develop/docker/README.md
- 官方安装总文档:https://github.com/codidact/qpixel/blob/develop/INSTALLATION.md
- Codidact 官方站点:https://codidact.com
- 站内互链:《qpixel 介绍与选型指南》、《qpixel 0.13.0 配置参数详解》、《qpixel 0.13.0 常用 CLI 命令与工具详解》