在 Alpine 容器中手动搭建 Discuz 全攻略(小白友好版 + 带步骤序号架构流程图)

这篇指南专为刚接触 Docker 和 Linux 的小白设计。我们会逐词逐句解释每条命令是干什么的、为什么要这样写,并用生动的比喻帮助你理解。我们还加入了带步骤序号的架构流程图和实现原理,让你彻底明白 Discuz 论坛是如何在容器中跑起来的。跟着操作,你就能在自己的电脑/服务器上跑起一个属于自己的论坛网站!


🧭 整体架构与请求流程(带步骤序号)

下面这张图清晰地标出了从用户浏览器到容器内各组件的完整请求步骤(数字序号表示先后顺序):

请添加图片描述

📌 步骤说明

步骤动作说明
1用户浏览器 → 宿主机 :8080用户在地址栏输入 http://服务器IP:8080,发起访问请求
2宿主机 → 容器 :80Docker 的端口映射把请求转发到容器内部的 80 端口
3aNginx → 静态文件如果请求的是图片、CSS、JS 等静态资源,Nginx 直接读取并返回
3bNginx → PHP-FPM如果请求的是 .php 文件(如 forum.php),Nginx 把请求转给 PHP-FPM 处理
4PHP-FPM → MariaDBDiscuz 执行过程中需要读取或保存数据(帖子、用户、版块等),PHP 连接数据库查询
5MariaDB → PHP-FPM数据库返回查询结果(比如帖子列表、用户信息)
6PHP-FPM → DiscuzPHP 调用 Discuz 程序逻辑处理数据
7Discuz → PHP-FPMDiscuz 生成完整的 HTML 页面,返回给 PHP-FPM
8PHP-FPM → NginxPHP 把生成的 HTML 页面返回给 Nginx
9容器 → 宿主机Nginx 把响应发送回 Docker 宿主机
10宿主机 → 用户浏览器宿主机把响应返回给用户的浏览器,用户看到完整的 Discuz 论坛页面

💡 核心流程总结
用户 → 宿主机 → 容器 → Nginx → (如果是 PHP) → PHP-FPM → 数据库 → PHP-FPM → Discuz → Nginx → 宿主机 → 用户。
静态文件请求则跳过 PHP-FPM 和数据库,由 Nginx 直接返回。

💡 各组件角色速记

  • Nginx = 门卫,负责接待访客(接收请求),决定是直接给文件还是找人处理
  • PHP-FPM = 翻译员,把 PHP 代码翻译成网页内容
  • MariaDB = 仓库管理员 + 账房先生,存储所有论坛数据
  • Discuz = 论坛程序本身,就是那栋你要住进去的"房子"

📦 第一部分:准备工作 —— 安装 Docker

什么是 Docker?

Docker 就像是一个"集装箱系统"。你可以把论坛、数据库、应用程序全部装进一个独立的"集装箱"(容器)里,这个箱子可以在任何安装有 Docker 的电脑上运行,不用担心环境不一致的问题。就像海运的集装箱,无论在哪个港口,用什么起重机,打开后里面的货物都是完好无损的。

在 openEuler 24.03 上安装 Docker

打开你的终端(如果是 Windows 请使用 WSL2 或 PowerShell,但本指南基于 Linux)。一条一条复制下面的命令,按回车执行。

# 1. 更新系统软件包列表(让系统知道有哪些新软件可用)
sudo dnf update -y
  • sudo:以管理员(root)身份执行,因为安装软件需要权限。
  • dnf:openEuler 使用的软件包管理器,类似手机上的"应用商店"。
  • update:刷新软件列表。
  • -y:自动回答"yes",不用手动确认。
# 2. 安装一些必要的工具,帮助 Docker 正常安装
sudo dnf install -y yum-utils device-mapper-persistent-data lvm2
  • yum-utils:提供一些管理软件仓库的工具。
  • device-mapper-persistent-datalvm2:Docker 存储数据需要用到的底层驱动。
# 3. 添加 Docker 官方软件源(告诉系统去哪里下载 Docker)
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
  • yum-config-manager:管理软件源配置。
  • --add-repo:添加一个新的软件源地址。
# 4. 修正软件源中的版本号(因为 openEuler 兼容 CentOS 8)
sudo sed -i 's/$releasever/8/g' /etc/yum.repos.d/docker-ce.repo
  • sed:一个文本替换工具。
  • -i:直接修改文件内容。
  • s/旧/新/g:把文件里所有的 $releasever 替换成 8,确保能正确下载。
# 5. 正式安装 Docker
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
  • docker-ce:Docker 社区版(免费)。
  • docker-ce-cli:Docker 命令行工具。
  • containerd.io:容器运行时。
  • docker-compose-plugin:用于管理多个容器的工具(稍后会用到)。
# 6. 启动 Docker 服务
sudo systemctl start docker
  • systemctl:管理系统服务的命令。
  • start docker:让 Docker 后台进程运行起来。
# 7. 设置 Docker 开机自动启动(免得每次重启电脑都要手动启动)
sudo systemctl enable docker
# 8. 验证 Docker 是否安装成功
sudo docker run hello-world
  • docker run:运行一个容器。
  • hello-world:一个测试镜像。如果看到一段欢迎文字,说明 Docker 正常工作。

至此,你已经拥有了 Docker 这个"集装箱码头",可以开始装货了!


🚀 第二部分:启动一个 Alpine 容器并进入它的"内部世界"

什么是 Alpine?

Alpine 是一个极其轻量级的 Linux 发行版,整个系统只有 5MB 左右。它就像一个小小的"毛坯房",非常适合用来自己搭建环境。相比 Ubuntu 或 CentOS,Alpine 更小、更快、更省资源。

docker run -it --name my-discuz alpine:latest /bin/sh
  • docker run:创建并启动一个新容器。
  • -it:两个参数的合体:
    • -i(interactive):保持输入流打开,让你可以敲命令。
    • -t(tty):分配一个虚拟终端,让你看到输出。
    • 合起来就是"交互式终端"。
  • --name my-discuz:给这个容器起个名字叫 my-discuz,方便后续管理。
  • alpine:latest:使用 Alpine 的最新版本镜像。: 后面是标签(tag),latest 表示最新版。
  • /bin/sh:容器启动后执行的第一个程序。/bin/sh 是一个 shell(命令解释器),让你可以输入命令。

执行后,你的命令行提示符会变成 / #,说明你已经进入容器内部了。你可以把它想象成 ssh 进了一台全新的微型服务器。

💡 你现在站在一个空空如也的"毛坯房"里,接下来我们要装修它、安装家具(软件)!


🧰 第三部分:安装 LNMP 环境

现在我们在容器内部(提示符是 / #),需要安装:

  • Nginx:Web 服务器,负责接收浏览器请求并返回网页。就像大楼的门卫。
  • PHP 8.2:动态脚本语言,Discuz 就是用 PHP 写的。推荐使用 PHP 8.2,兼容性最佳
  • PHP-FPM:PHP FastCGI 进程管理器,负责解释执行 PHP 脚本。
  • MariaDB:数据库,存储帖子、用户、版块等数据。就像一个巨大的仓库。
  • wget、unzip:下载和解压工具。

什么是 LNMP?

LNMP = Linux + Nginx + MySQL(MariaDB) + PHP。这是一套经典的网站运行环境,就像做一顿饭需要锅、灶、火一样,网站运行也需要这些组件配合。

⚠️ 为什么使用 PHP 8.2 而不是 PHP 8.3?
Discuz! X3.5 官方推荐的 PHP 版本为 PHP 7.4-8.2。虽然 PHP 8.3 可能也能运行,但部分第三方插件可能存在兼容性问题。为了最佳兼容性,我们选择 PHP 8.2

启用 Alpine Testing 仓库

Alpine 的 PHP 8.2 包在 testing 仓库中,需要先启用:

# 启用 edge 版本的 testing 仓库(包含 PHP 8.2)
echo "https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
apk update
  • echo ... >> /etc/apk/repositories:把 testing 仓库地址追加到仓库列表。
  • apk update:刷新软件包列表,让系统能识别 testing 仓库中的软件。

安装所有软件包

# 安装所有需要的软件(一行命令搞定)
apk add --no-cache nginx php82 php82-fpm php82-mysqli php82-pdo php82-pdo_mysql \
    php82-session php82-json php82-mbstring php82-tokenizer php82-gd php82-curl \
    php82-xml php82-zip php82-ctype php82-dom php82-simplexml php82-fileinfo \
    php82-openssl php82-exif php82-bcmath \
    mariadb mariadb-client wget unzip bash
  • apk add:安装软件包。
  • --no-cache:不缓存下载的包,减小镜像体积。
  • nginx:Web 服务器(门卫)。
  • php82:PHP 8.2 的核心。
  • php82-fpm:PHP FastCGI 进程管理器,负责处理 PHP 脚本。
  • php82-mysqli / php82-pdo / php82-pdo_mysql:让 PHP 能连接 MySQL/MariaDB 数据库。
  • php82-gd:图像处理库,Discuz 生成验证码、头像等需要它。
  • php82-mbstring:多字节字符串支持,中文处理必需。
  • php82-session:会话管理,用户登录状态需要它。
  • php82-json:JSON 数据处理。
  • php82-curl:网络请求,Discuz 与外部通信需要它。
  • php82-xml:XML 数据处理。
  • php82-zip:压缩解压,Discuz 安装插件需要。
  • php82-openssl:HTTPS/SSL 支持,外部 API 调用需要。
  • php82-exif:图片 EXIF 信息读取,头像处理可能需要。
  • php82-bcmath:高精度数学计算,支付功能等需要。
  • php82-ctype / php82-dom / php82-simplexml / php82-fileinfo:各种 PHP 扩展,Discuz 正常运行的保障。
  • mariadb:数据库服务器(仓库管理员)。
  • mariadb-client:数据库客户端工具(比如 mysql 命令)。
  • wget:从网络下载文件的工具。
  • unzip:解压 ZIP 文件。
  • bash:比 sh 更友好的 shell,脚本中需要用到一些 bash 特性。

💡 PHP 扩展说明表

扩展名用途重要性
mysqli/pdo/pdo_mysql数据库连接⭐ 必须
gd图片处理/验证码⭐ 必须
mbstring中文处理⭐ 必须
session用户登录状态⭐ 必须
opensslHTTPS 支持⭐ 必须
curl外部 API 调用⭐ 必须
jsonJSON 数据处理⭐ 必须
zip插件安装⭐ 必须
exif图片 EXIF⭐ 推荐
bcmath高精度计算⭐ 推荐

🗄️ 第四部分:初始化数据库(建仓库和账房先生)

数据库就像一个大仓库,Discuz 的帖子、用户、版块、设置等都存在里面。我们需要先建好仓库,再给 Discuz 分配一个专用账户。

什么是数据库?

想象一个超大型图书馆

  • 数据库 = 整个图书馆建筑
  • 数据表 = 书架(用户表、帖子表、版块表…)
  • 记录 = 书架上的每一本书(每个用户、每篇帖子)
  • 数据库用户 = 图书馆管理员,有权限借阅和归还书籍
# 1. 创建 MySQL 运行时需要的目录(存放进程 ID 和 socket 文件)
mkdir -p /run/mysqld
  • mkdir -p:创建目录,-p 表示如果父目录不存在就一起创建。
  • /run/mysqld 是 MariaDB 保存进程 ID 和 socket 文件的地方。
# 2. 把这个目录的所有权交给 mysql 用户
chown mysql:mysql /run/mysqld
  • chown:修改文件/目录的所有者。格式:chown 用户:组 目标
  • MySQL/MariaDB 需要用自己的用户身份运行,所以要给它分配目录权限。
# 3. 初始化数据库文件(建立系统表)
mysql_install_db --user=mysql --datadir=/var/lib/mysql
  • mysql_install_db:初始化 MariaDB 的数据目录,创建系统表(mysql、information_schema 等)。
  • --user=mysql:用 mysql 用户身份运行。
  • --datadir=/var/lib/mysql:指定数据存储目录。
# 4. 以后台模式启动 MariaDB
mysqld_safe --user=mysql &
  • mysqld_safe:一个启动脚本,会自动重启崩溃的数据库,比直接运行 mysqld 更安全。
  • &:把这个命令放到后台运行,不阻塞当前终端。
# 5. 等待 3 秒,让数据库完全启动
sleep 3
  • sleep 3:暂停 3 秒。数据库启动需要一点时间,我们要等它准备好。
# 6. 设置数据库超级用户 root 的密码(这里用 example,正式环境必须改!)
mysqladmin -u root password 'example'
  • mysqladmin:数据库管理工具。
  • -u root:指定 root 用户。
  • password 'example':把密码设为 example。

⚠️ 安全提示:这里用的 example 是示例密码,仅用于测试。正式环境请使用更复杂的密码!可以用 openssl rand -base64 16 生成随机密码。

# 7. 创建 Discuz 专用的数据库和用户
mysql -u root -p'example' <<EOF
CREATE DATABASE discuz CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'discuz_user'@'localhost' IDENTIFIED BY 'discuz_pass';
GRANT ALL PRIVILEGES ON discuz.* TO 'discuz_user'@'localhost';
FLUSH PRIVILEGES;
EOF
  • mysql -u root -p'example':用 root 身份登录数据库。注意 -p 和密码之间没有空格
  • <<EOF ... EOF:这是一个"内联输入"的写法,把中间的多行命令直接传给 mysql。
  • CREATE DATABASE discuzdiscuz 是数据库名。
  • CHARACTER SET utf8mb4:使用 UTF-8 编码,支持所有 Unicode 字符(包括 emoji),这是论坛必须的。
  • COLLATE utf8mb4_general_ci:排序规则,ci 表示大小写不敏感。
  • CREATE USER 'discuz_user'@'localhost':创建用户 discuz_user,只允许从本机连接。
  • IDENTIFIED BY 'discuz_pass':设置该用户的密码。
  • GRANT ALL PRIVILEGES ON discuz.* TO 'discuz_user'@'localhost':让该用户拥有 discuz 数据库的所有权限。
  • FLUSH PRIVILEGES:刷新权限表,使改动生效。

🎯 结果:现在数据库里有一个空数据库叫 discuz,用户 discuz_user 密码 discuz_pass 可以访问它。

数据库配置备忘(后续安装 Discuz 时会用到):

  • 数据库服务器:localhost
  • 数据库名:discuz
  • 用户名:discuz_user
  • 密码:discuz_pass
  • root 密码:example

📥 第五部分:下载并配置 Discuz

什么是 Discuz?

Discuz! 是国内最流行的论坛社区软件,你可以用它搭建像"百度贴吧"、"天涯社区"那样的讨论论坛。它由 PHP 编写,支持丰富的插件扩展。

# 1. 创建网站根目录(所有网页文件放在这里)
mkdir -p /var/www/localhost
cd /var/www/localhost
  • /var/www 是 Linux 传统的网站目录。
  • localhost 表示本机站点。
  • cd /var/www/localhost:切换到该目录,后续命令都在这里执行。
# 2. 下载 Discuz! X3.5 官方简体中文版(推荐使用官方发布版)
wget https://gitee.com/Discuz/DiscuzX/attach-files/download/Discuz_X3.5_SC_UTF8_20250901.zip -O discuz.zip
  • wget:从网络下载文件。
  • https://gitee.com/Discuz/DiscuzX/attach-files/download/...:Discuz 官方 Gitee 仓库的发布版附件下载地址
  • -O discuz.zip:把下载的文件保存为 discuz.zip

💡 下载地址说明

  • 推荐:官方发布版(经过测试,最稳定):https://gitee.com/Discuz/DiscuzX/attach-files/download/Discuz_X3.5_SC_UTF8_20250901.zip
  • 备选 1:Gitee 仓库归档版:https://gitee.com/Discuz/DiscuzX/repository/archive/v3.5.zip
  • 备选 2:GitHub 发布版:https://github.com/discuz/Discuz/releases/download/v3.5/Discuz_X3.5_SC_UTF8.zip

⚠️ 注意:如果你之前使用的是仓库源码压缩包(archive),请改用上面的官方发布版,因为发布版是经过官方测试的正式版本,文件结构更规范。

# 3. 解压
unzip -q discuz.zip
  • unzip -q:解压 ZIP 文件,-q 表示安静模式,不显示每个文件的解压过程。
# 4. 查看解压后的目录结构
ls -la
  • ls -la:列出目录内容,-l 详细信息,-a 显示隐藏文件。
# 5. Discuz 的程序文件在 upload 目录,我们需要把它移到网站根目录
mv upload/* .
rm -rf upload discuz.zip
  • mv upload/* .:把 upload 目录里的所有内容移动到当前目录。
  • rm -rf upload discuz.zip:删除空的 upload 目录和压缩包,节省空间。
# 6. 查看现在目录里的文件
ls -la

你应该能看到 admin.phpconfig/data/forum.php 等目录和文件。

# 7. 查看目录结构
ls -la ./

正常情况应该看到:

  • admin.php(后台管理入口)
  • forum.php(论坛首页)
  • home.php(个人空间)
  • config/(配置文件目录)
  • data/(数据目录)
  • uc_client/(Ucenter 客户端)
  • uc_server/(Ucenter 服务端)
# 8. 创建 Discuz 需要写入的目录并设置权限
mkdir -p config data uc_client/data uc_server/data
chown -R nginx:nginx /var/www/localhost
chmod -R 777 config data uc_client/data uc_server/data
  • mkdir -p config data uc_client/data uc_server/data:创建 Discuz 需要写入权限的目录。
  • chown -R nginx:nginx /var/www/localhost:把网站目录的所有者改为 nginx 用户,-R 递归处理子目录。
  • chmod -R 777:给所有人读、写、执行权限。Discuz 安装向导需要写入配置文件。

⚠️ 为什么用 777 权限?
这是为了临时方便安装向导写入配置文件。安装完成后,你可以把权限改得更安全:chmod -R 755 config data(只有所有者可写)。

现在 Discuz 程序已经下载并配置好了!


⚙️ 第六部分:配置 Nginx 和 PHP-FPM

什么是 Nginx 配置?

Nginx 是一个"门卫",当浏览器请求 http://你的网站 时,Nginx 决定:

  • 如果是图片、CSS、JS 等静态文件,直接返回。
  • 如果是 PHP 文件(如 forum.php),则转交给 PHP-FPM 处理。

配置 Nginx

# 创建 Nginx 配置文件
cat > /etc/nginx/http.d/default.conf <<'EOF'
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    root /var/www/localhost;
    index index.php index.html index.htm;
    
    # Discuz URL 重写规则
    location / {
        try_files $uri $uri/ /index.php?$uri&$args;
    }
    
    # PHP 请求交给 PHP-FPM 处理
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    
    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
    
    # 禁止访问隐藏文件
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}
EOF
  • cat > 文件 <<'EOF' ... EOF:把中间的内容写入文件。
  • server { ... }:定义一个虚拟主机。
  • listen 80:监听 80 端口(HTTP 默认端口)。
  • root /var/www/localhost:网站文件的根目录(就是刚才解压的 Discuz 文件夹)。
  • index index.php index.html:默认首页文件,先找 index.php
  • location /:处理所有根路径的请求。
  • try_files:尝试按顺序查找文件,如果找不到就重写到 index.php(Discuz 伪静态规则)。
  • location ~ \.php$:匹配以 .php 结尾的请求(~ 表示正则匹配)。
  • fastcgi_pass 127.0.0.1:9000:把 PHP 请求转发给本机 9000 端口(PHP-FPM 监听的地址)。
  • fastcgi_param SCRIPT_FILENAME:告诉 PHP-FPM 要执行哪个脚本文件。
  • location ~* \.(...)$:匹配静态资源,设置 30 天缓存。
  • location ~ /\.:禁止访问以 . 开头的隐藏文件(安全设置)。

配置 PHP-FPM

# 1. 检查 PHP-FPM 配置目录
ls -la /etc/php82/php-fpm.d/
  • 查看 PHP-FPM 的配置文件位置。
# 2. 修改 PHP-FPM 配置,让它监听 9000 端口
sed -i 's/^listen = 127.0.0.1:9000/; listen = 127.0.0.1:9000/' /etc/php82/php-fpm.d/www.conf
echo "listen = 127.0.0.1:9000" >> /etc/php82/php-fpm.d/www.conf
  • 第一句:把原来的 listen = 127.0.0.1:9000 注释掉(在行首加 ;)。
  • 第二句:在文件末尾新增一行 listen = 127.0.0.1:9000
# 3. 把运行 PHP 的用户和组改为 nginx
sed -i 's/^user = nobody/user = nginx/' /etc/php82/php-fpm.d/www.conf
sed -i 's/^group = nobody/group = nginx/' /etc/php82/php-fpm.d/www.conf
  • 把运行 PHP 的用户和组从 nobody 改为 nginx,这样 PHP 创建的文件才能被 Nginx 正常访问。
# 4. 检查 PHP 禁用函数,Discuz 需要这些函数可用
cat /etc/php82/php.ini | grep disable_functions

⚠️ 重要检查:Discuz 需要以下函数不能被禁用。如果下面的命令显示这些函数在列表里,需要移除它们:

  • symlink(符号链接)
  • readlink(读取链接)
  • putenv(设置环境变量)
  • realpath(获取真实路径)
  • shell_exec(执行 shell 命令)
# 5. 如果上述函数被禁用,取消禁用(可选步骤,根据实际情况)
sed -i 's/disable_functions = .*/disable_functions =/' /etc/php82/php.ini
  • 这会把禁用函数列表清空,允许所有函数。如果只想允许特定函数,可以更精细地配置。
# 6. 验证 PHP 配置
php-fpm82 -t
  • -t:测试 PHP-FPM 配置是否正确。

Nginx 和 PHP-FPM 配置完成!


🎯 第七部分:启动服务并完成 Discuz 安装

启动所有服务

# 1. 测试 Nginx 配置语法
nginx -t
  • -t:测试配置文件是否正确,不实际启动。
# 2. 启动 PHP-FPM(前台模式)
php-fpm82 -F &
  • -F:前台运行,方便查看日志。
  • &:放到后台。
# 3. 启动 Nginx(前台模式)
nginx -g 'daemon off;' &
  • -g 'daemon off;':让 Nginx 也以前台方式运行。
  • &:后台运行。
# 4. 检查服务是否启动成功
ps aux | grep -E 'nginx|php-fpm|mysql'
  • ps aux:显示所有进程。
  • grep -E:过滤显示包含 nginx、php-fpm、mysql 的行。

你应该能看到 nginx、php-fpm、mysqld 三个进程都在运行!

# 5. 保持容器不退出(关键步骤!)
tail -f /dev/null
  • tail -f:持续输出文件末尾内容。
  • /dev/null:一个特殊的"黑洞"设备,永远为空。
  • 这个命令会永远阻塞在那里,使得容器不会因为启动完服务就自动退出。

💡 现在所有服务都已启动! 你可以看到类似这样的输出:

[notice] nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
[notice] nginx: configuration file /etc/nginx/nginx.conf test is successful

🌐 第八部分:让外部访问你的 Discuz 论坛

目前容器里的服务只能容器内部访问,我们需要把容器的 80 端口映射到宿主机的某个端口(比如 8080)。

步骤:退出容器并重新映射端口

  1. 退出容器但不停止它:按键盘 Ctrl + P 再按 Ctrl + Q。你会回到宿主机终端,但容器仍在后台运行。

  2. 查看容器 ID

    docker ps -a
    

    输出类似:

    CONTAINER ID   IMAGE           COMMAND       CREATED        STATUS        PORTS     NAMES
    7b9a2500e000   alpine:latest   "/bin/sh"     2 hours ago    Up 2 hours              my-discuz
    

    记下 CONTAINER ID 的前几位(如 7b9a2500e000)。

  3. 把当前容器保存为一个新镜像

    docker commit my-discuz my-discuz:alpine
    
    • docker commit:把容器保存为镜像。
    • my-discuz:源容器名。
    • my-discuz:alpine:新镜像名和标签。
  4. 停止并删除原容器(因为原容器没有映射端口):

    docker stop my-discuz
    docker rm my-discuz
    
  5. 用新镜像重新运行,并映射端口

    docker run -d --name discuz-running -p 8080:80 my-discuz:alpine \
      /bin/sh -c "mysqld_safe --user=mysql & php-fpm82 -F & nginx -g 'daemon off;' & tail -f /dev/null"
    
    • -d:后台运行(detach)。
    • --name discuz-running:给新容器起名。
    • -p 8080:80:把宿主机的 8080 端口映射到容器的 80 端口。这样你访问 http://宿主机IP:8080 就相当于访问容器内的 80 端口。
    • 后面的长字符串是启动命令,让 MariaDB、PHP-FPM、Nginx 都启动起来。
  6. 获取宿主机 IP

    ip addr show | grep inet
    

    或者简单点:hostname -I

  7. 打开浏览器,输入 http://你的宿主机IP:8080。如果是在本机(比如你用 Linux 桌面),可以用 http://localhost:8080。你应该能看到 Discuz 的安装向导页面!


📝 第九部分:完成 Discuz 安装向导

恭喜你!现在你已经成功在 Docker 容器里跑起了 Discuz!接下来是图形化的安装向导。

访问安装向导

在浏览器打开 http://你的IP:8080,你应该会看到 Discuz 安装向导的第一步。

安装向导步骤

第一步:阅读授权协议
  • 勾选"我已阅读并同意此协议"
  • 点击"下一步"
第二步:环境检测

Discuz 会检测你的服务器环境:

检测项状态说明
PHP 版本需要 5.6+,我们装的是 8.2
MySQL/MySQLi已安装 php82-mysqli
PDO MySQL已安装 php82-pdo_mysql
GD已安装 php82-gd
mbstring已安装 php82-mbstring
目录权限✅/⚠️检查 config、data、uc_* 目录是否可写

⚠️ 如果某些目录显示"不可写",回到容器里执行:

docker exec -it discuz-running chmod -R 777 /var/www/localhost/config /var/www/localhost/data /var/www/localhost/uc_client/data /var/www/localhost/uc_server/data

然后点击"重新检查"。

  • 点击"下一步"
第三步:数据库配置

填写数据库信息:

配置项说明
数据库服务器localhostMariaDB 和 Discuz 在同一容器
数据库名discuz之前创建的数据库名
数据库用户名discuz_user之前创建的用户
数据库密码discuz_pass之前设置的密码
表前缀pre_可自定义,默认 pre_ 是推荐值
  • 点击"下一步"
第四步:管理员账号

填写论坛管理员信息:

配置项说明
管理员邮箱你的邮箱用于接收通知
管理员账号admin论坛超级管理员用户名
管理员密码你的强密码建议 12 位以上,包含大小写字母和数字
确认密码再输一遍确认密码正确

⚠️ 管理员账号和密码很重要! 请务必记住,丢了无法找回。

  • 点击"开始安装"
第五步:安装完成

恭喜!Discuz 安装成功!

你会看到:

恭喜!您的论坛已安装完成,请尽快删除 install 目录!

⚠️ 重要安全提示:点击"确定"后,系统会跳转到论坛首页,但你需要手动删除 install 目录:

docker exec -it discuz-running rm -rf /var/www/localhost/install

访问你的论坛

  • 论坛首页http://你的IP:8080
  • 后台管理http://你的IP:8080/admin.php

💾 第十部分:数据持久化(防止丢失数据)

问题:当前容器如果被删除,所有帖子、用户、数据库都会丢失。
解决方案:把重要数据目录挂载到宿主机硬盘上。

# 1. 在宿主机上创建两个目录
mkdir -p /data/discuz/mysql
mkdir -p /data/discuz/www
# 2. 把当前容器里的数据复制出来
docker cp discuz-running:/var/lib/mysql/. /data/discuz/mysql/
docker cp discuz-running:/var/www/localhost/. /data/discuz/www/
# 3. 停止并删除当前容器
docker stop discuz-running
docker rm discuz-running
# 4. 重新运行容器,挂载这两个目录(-v 参数)
docker run -d --name discuz-prod -p 8080:80 \
  -v /data/discuz/mysql:/var/lib/mysql \
  -v /data/discuz/www:/var/www/localhost \
  my-discuz:alpine \
  /bin/sh -c "mysqld_safe --user=mysql & php-fpm82 -F & nginx -g 'daemon off;' & tail -f /dev/null"
  • -v 宿主机目录:容器内目录:把宿主机的目录挂载到容器内部,容器内对这个目录的读写实际上就是读写宿主机硬盘。

现在即使容器被删除,数据依然保存在 /data/discuz/ 下。以后重建容器时,挂载同样的目录即可恢复数据。


📦 第十一部分:将部署打包成镜像(随时随地使用)

你已经成功搭建了 Discuz 论坛,但如果想在另一台服务器上快速部署,或者保存当前环境作为备份,最好的方法就是把整个环境打包成 Docker 镜像。这样你就可以:

  • ✅ 在任何安装了 Docker 的机器上一键启动
  • ✅ 不需要重复安装配置 LNMP 环境
  • ✅ 方便分享给团队成员或迁移到云服务器
  • ✅ 作为环境备份,随时回滚

🏠 为什么要打包镜像?

想象一下:你已经精心装修好了一栋房子(配置好的容器),现在你想在另一个地方也有一模一样的房子。打包镜像就是把整栋房子复制一份,搬到任何地方都能直接入住,不用再重新装修。

方法一:将运行中的容器打包成镜像

如果你已经完成了前面的部署步骤,容器正在运行,可以直接把它打包:

# 1. 查看当前运行的容器
docker ps
  • 找到你的容器名称(如 discuz-runningdiscuz-prod
# 2. 将容器打包成镜像(名字自己取)
docker commit -a "你的名字" -m "Discuz X3.5 on Alpine" discuz-running my-discuz:v1.0
  • docker commit:将容器保存为镜像
  • -a "你的名字":作者信息(可选)
  • -m "描述":镜像说明(可选)
  • discuz-running:源容器名称
  • my-discuz:v1.0:新镜像名称和标签
# 3. 查看生成的镜像
docker images | grep my-discuz
  • 你应该能看到 my-discuz 镜像,大小约 200-300MB

方法二:使用 Dockerfile 构建镜像(推荐)

如果你想从头构建一个干净的镜像,或者需要分享给他人,推荐使用 Dockerfile:

第一步:创建项目目录
# 在宿主机上创建一个目录
mkdir -p ~/discuz-image
cd ~/discuz-image
第二步:编写 Dockerfile
# 创建 Dockerfile 文件
cat > Dockerfile <<'EOF'
FROM alpine:latest

# 维护者信息
LABEL maintainer="your-email@example.com"
LABEL description="Discuz! X3.5 on Alpine Linux with LNMP"

# 启用 testing 仓库获取 PHP 8.2
RUN echo "https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories

# 安装所有依赖(LNMP + 工具)
RUN apk update && apk add --no-cache \
    nginx \
    php82 php82-fpm php82-mysqli php82-pdo php82-pdo_mysql \
    php82-session php82-json php82-mbstring php82-tokenizer \
    php82-gd php82-curl php82-xml php82-zip \
    php82-ctype php82-dom php82-simplexml php82-fileinfo \
    php82-openssl php82-exif php82-bcmath \
    mariadb mariadb-client \
    wget unzip bash openssl

# 创建必要目录
RUN mkdir -p /run/mysqld /var/www/localhost && \
    chown mysql:mysql /run/mysqld

# 设置工作目录
WORKDIR /var/www/localhost

# 下载 Discuz X3.5 官方发布版
RUN wget -q https://gitee.com/Discuz/DiscuzX/attach-files/download/Discuz_X3.5_SC_UTF8_20250901.zip -O discuz.zip && \
    unzip -q discuz.zip && \
    if [ -d "upload" ]; then mv upload/* . && rm -rf upload; fi && \
    rm -f discuz.zip && \
    mkdir -p config data uc_client/data uc_server/data && \
    chown -R nginx:nginx /var/www/localhost && \
    chmod -R 777 config data uc_client/data uc_server/data

# 复制启动脚本
COPY start.sh /start.sh
RUN chmod +x /start.sh

# 暴露端口
EXPOSE 80

# 启动命令
CMD ["/start.sh"]
EOF
第三步:编写启动脚本
# 创建启动脚本
cat > start.sh <<'EOF'
#!/bin/sh
# ============================================
# Discuz X3.5 容器启动脚本
# ============================================

# 初始化数据库(仅首次运行)
if [ ! -d "/var/lib/mysql/mysql" ]; then
    echo ">>> 初始化数据库..."
    mysql_install_db --user=mysql --datadir=/var/lib/mysql > /dev/null 2>&1
fi

# 启动 MariaDB
echo ">>> 启动 MariaDB..."
mysqld_safe --user=mysql &
sleep 3

# 设置数据库密码和创建数据库(仅首次)
if [ ! -f "/var/lib/mysql/.initialized" ]; then
    echo ">>> 配置数据库..."
    mysqladmin -u root password "${DB_ROOT_PASS:-discuz_root_123}"
    mysql -u root -p"${DB_ROOT_PASS:-discuz_root_123}" <<EOSQL
CREATE DATABASE IF NOT EXISTS discuz CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS 'discuz_user'@'localhost' IDENTIFIED BY '${DB_DISCUZ_PASS:-discuz_pass_123}';
GRANT ALL PRIVILEGES ON discuz.* TO 'discuz_user'@'localhost';
FLUSH PRIVILEGES;
EOSQL
    touch /var/lib/mysql/.initialized
    echo ">>> 数据库初始化完成!"
fi

# 配置 Nginx
echo ">>> 配置 Nginx..."
cat > /etc/nginx/http.d/default.conf <<'NGINXCONF'
server {
    listen 80 default_server;
    root /var/www/localhost;
    index index.php index.html index.htm;
    
    location / {
        try_files $uri $uri/ /index.php?$uri&$args;
    }
    
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
    
    location ~ /\. {
        deny all;
    }
}
NGINXCONF

# 配置 PHP-FPM
echo ">>> 配置 PHP-FPM..."
sed -i 's/^listen = .*/; listen =/' /etc/php82/php-fpm.d/www.conf 2>/dev/null || true
echo "listen = 127.0.0.1:9000" >> /etc/php82/php-fpm.d/www.conf
sed -i 's/^user = .*/user = nginx/' /etc/php82/php-fpm.d/www.conf
sed -i 's/^group = .*/group = nginx/' /etc/php82/php-fpm.d/www.conf

# 启动服务
echo ">>> 启动 PHP-FPM..."
php-fpm82 -F &

echo ">>> 启动 Nginx..."
nginx -g 'daemon off;' &

echo "========================================"
echo "  Discuz! X3.5 启动成功!"
echo "  访问地址: http://服务器IP:端口"
echo "========================================"

# 保持容器运行
tail -f /dev/null
EOF
第四步:构建镜像
# 构建镜像(注意最后有个点)
docker build -t my-discuz:v1.0 .
  • -t my-discuz:v1.0:镜像名称和标签
  • .:Dockerfile 所在目录(当前目录)
# 查看构建结果
docker images my-discuz

📤 导出镜像文件

镜像构建完成后,可以导出为文件,方便传输:

# 导出镜像为 tar 文件
docker save -o discuz-image-v1.0.tar my-discuz:v1.0
  • docker save:导出镜像
  • -o discuz-image-v1.0.tar:输出文件名
  • my-discuz:v1.0:要导出的镜像
# 查看文件大小
ls -lh discuz-image-v1.0.tar
  • 文件大小约 250-350MB,可以用 U 盘、网盘等方式传输

📥 在其他机器导入镜像

将 tar 文件传到目标机器后:

# 导入镜像
docker load -i discuz-image-v1.0.tar
  • docker load:导入镜像
  • -i discuz-image-v1.0.tar:镜像文件
# 验证导入成功
docker images | grep my-discuz

🚀 使用镜像快速部署

导入镜像后,一条命令启动 Discuz:

# 启动容器(端口映射)
docker run -d --name my-forum -p 8080:80 \
  -e DB_ROOT_PASS="你的root密码" \
  -e DB_DISCUZ_PASS="你的discuz密码" \
  my-discuz:v1.0
  • -d:后台运行
  • --name my-forum:容器名称
  • -p 8080:80:端口映射
  • -e DB_ROOT_PASS:设置数据库 root 密码(可选,默认 discuz_root_123)
  • -e DB_DISCUZ_PASS:设置 discuz_user 密码(可选,默认 discuz_pass_123)
# 查看容器状态
docker ps

打开浏览器访问 http://服务器IP:8080,即可看到 Discuz 安装向导!

☁️ 推送到 Docker Hub(可选)

如果你有 Docker Hub 账号,可以把镜像推送上去,随时随地拉取:

# 1. 登录 Docker Hub
docker login
  • 输入你的 Docker Hub 用户名和密码
# 2. 给镜像打标签(换成你的用户名)
docker tag my-discuz:v1.0 你的用户名/discuz-alpine:v1.0
# 3. 推送到 Docker Hub
docker push 你的用户名/discuz-alpine:v1.0

推送成功后,任何机器都可以直接拉取:

docker pull 你的用户名/discuz-alpine:v1.0

📋 镜像管理常用命令

命令说明
docker images查看本地所有镜像
docker rmi 镜像名:标签删除镜像
docker tag 旧名 新名给镜像打标签
docker save -o file.tar 镜像名导出镜像为文件
docker load -i file.tar从文件导入镜像
docker push 镜像名推送镜像到仓库
docker pull 镜像名从仓库拉取镜像

⚠️ 注意事项

  1. 数据持久化:上述镜像不包含用户数据(帖子、附件等)。生产环境建议挂载数据卷:

    docker run -d --name my-forum -p 8080:80 \
      -v /data/discuz/mysql:/var/lib/mysql \
      -v /data/discuz/www:/var/www/localhost \
      my-discuz:v1.0
    
  2. 安全设置

    • 导出镜像前,删除敏感信息(密码、密钥)
    • 推送到公开仓库前,确保没有包含敏感配置
  3. 镜像优化

    • 使用 --no-cache 减小镜像体积
    • 多阶段构建可以进一步精简镜像

🚀 第十二部分:一键部署脚本(懒人福音)

如果你觉得手动敲这么多命令太麻烦,下面这个脚本可以帮你全自动完成所有步骤,包括安装 Docker、搭建环境、启动容器。

📜 脚本内容

将以下代码保存为 install_discuz.sh

#!/bin/bash
# ============================================
# 一键部署 Discuz! X3.5 到 Alpine Docker 容器
# 小白友好版 - 自动安装 Docker、自动配置环境
# 使用方法: chmod +x install_discuz.sh && sudo ./install_discuz.sh
# ============================================

set -e  # 遇到任何错误立即停止脚本

# 定义一些颜色,让输出更好看
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}  Discuz! X3.5 一键部署脚本 (Alpine)  ${NC}"
echo -e "${GREEN}========================================${NC}"

# ------------------ 检查并安装 Docker ------------------
if ! command -v docker &> /dev/null; then
    echo -e "${RED}Docker 未安装,正在自动安装...${NC}"
    sudo dnf update -y
    sudo dnf install -y yum-utils device-mapper-persistent-data lvm2
    sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    sudo sed -i 's/$releasever/8/g' /etc/yum.repos.d/docker-ce.repo
    sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
    sudo systemctl start docker
    sudo systemctl enable docker
    echo -e "${GREEN}Docker 安装完成。${NC}"
else
    echo -e "${GREEN}Docker 已安装,跳过安装步骤。${NC}"
fi

# ------------------ 用户输入端口 ------------------
read -p "请输入要映射的宿主机端口 (默认 8080): " HOST_PORT
HOST_PORT=${HOST_PORT:-8080}

# ------------------ 生成随机数据库密码 ------------------
DB_ROOT_PASS=$(openssl rand -base64 12 | tr -d "=+/" | cut -c1-16)
DB_DISCUZ_PASS=$(openssl rand -base64 12 | tr -d "=+/" | cut -c1-16)

echo -e "${YELLOW}数据库 root 密码: ${DB_ROOT_PASS}${NC}"
echo -e "${YELLOW}Discuz 数据库用户 discuz_user 密码: ${DB_DISCUZ_PASS}${NC}"
echo -e "${YELLOW}请保存好这些密码!${NC}"

# ------------------ 创建临时目录 ------------------
TEMP_DIR=$(mktemp -d)
cd $TEMP_DIR

# ------------------ 编写 Dockerfile ------------------
cat > Dockerfile <<'EOF'
FROM alpine:latest
# 启用 testing 仓库获取 PHP 8.2
RUN echo "https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
    apk update && apk add --no-cache \
    nginx php82 php82-fpm php82-mysqli php82-pdo php82-pdo_mysql \
    php82-session php82-json php82-mbstring php82-tokenizer php82-gd php82-curl \
    php82-xml php82-zip php82-ctype php82-dom php82-simplexml php82-fileinfo \
    php82-openssl php82-exif php82-bcmath \
    mariadb mariadb-client wget unzip bash openssl
RUN mkdir -p /run/mysqld /var/www/localhost && chown mysql:mysql /run/mysqld
WORKDIR /var/www/localhost
# 下载官方发布版 Discuz X3.5
RUN wget https://gitee.com/Discuz/DiscuzX/attach-files/download/Discuz_X3.5_SC_UTF8_20250901.zip -O discuz.zip && \
    unzip -q discuz.zip && \
    mv upload/* . && \
    rm -rf upload discuz.zip && \
    mkdir -p config data uc_client/data uc_server/data && \
    chown -R nginx:nginx /var/www/localhost && \
    chmod -R 777 config data uc_client/data uc_server/data
COPY start.sh /start.sh
RUN chmod +x /start.sh
EXPOSE 80
CMD ["/start.sh"]
EOF

# ------------------ 编写启动脚本 start.sh ------------------
cat > start.sh <<'EOF'
#!/bin/sh
# 初始化数据库(仅首次运行)
if [ ! -d "/var/lib/mysql/mysql" ]; then
    mysql_install_db --user=mysql --datadir=/var/lib/mysql > /dev/null 2>&1
fi
# 启动 MariaDB
mysqld_safe --user=mysql &
sleep 5
# 设置密码和创建数据库(仅首次)
if [ ! -f "/var/lib/mysql/.discuz_initialized" ]; then
    mysqladmin -u root password "${DB_ROOT_PASS}"
    mysql -u root -p"${DB_ROOT_PASS}" <<EOSQL
CREATE DATABASE IF NOT EXISTS discuz CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS 'discuz_user'@'localhost' IDENTIFIED BY '${DB_DISCUZ_PASS}';
GRANT ALL PRIVILEGES ON discuz.* TO 'discuz_user'@'localhost';
FLUSH PRIVILEGES;
EOSQL
    touch /var/lib/mysql/.discuz_initialized
fi
# 配置 Nginx
cat > /etc/nginx/http.d/default.conf <<'NGINXCONF'
server {
    listen 80 default_server;
    root /var/www/localhost;
    index index.php index.html index.htm;
    location / {
        try_files $uri $uri/ /index.php?$uri&$args;
    }
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}
NGINXCONF
# 配置 PHP-FPM(使用 php82)
sed -i 's/^listen = 127.0.0.1:9000/; listen = 127.0.0.1:9000/' /etc/php82/php-fpm.d/www.conf
echo "listen = 127.0.0.1:9000" >> /etc/php82/php-fpm.d/www.conf
sed -i 's/^user = nobody/user = nginx/' /etc/php82/php-fpm.d/www.conf
sed -i 's/^group = nobody/group = nginx/' /etc/php82/php-fpm.d/www.conf
# 启动服务(使用 php-fpm82)
php-fpm82 -F &
nginx -g 'daemon off;' &
# 保持容器运行
tail -f /dev/null
EOF

# 把密码变量注入 start.sh
sed -i "s/\${DB_ROOT_PASS}/${DB_ROOT_PASS}/g" start.sh
sed -i "s/\${DB_DISCUZ_PASS}/${DB_DISCUZ_PASS}/g" start.sh

# ------------------ 构建 Docker 镜像 ------------------
echo -e "${GREEN}正在构建 Docker 镜像...(可能需要几分钟)${NC}"
docker build -t my-discuz:auto .

# ------------------ 运行容器 ------------------
echo -e "${GREEN}正在启动容器,映射端口 ${HOST_PORT}:80 ...${NC}"
docker run -d --name discuz-auto -p ${HOST_PORT}:80 my-discuz:auto

# ------------------ 输出访问信息 ------------------
# 获取宿主机 IP
SERVER_IP=$(ip route get 1 | awk '{print $NF;exit}')
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}部署完成!${NC}"
echo -e "论坛首页: ${GREEN}http://${SERVER_IP}:${HOST_PORT}${NC}"
echo -e "后台管理: ${GREEN}http://${SERVER_IP}:${HOST_PORT}/admin.php${NC}"
echo -e "数据库 root 密码: ${YELLOW}${DB_ROOT_PASS}${NC}"
echo -e "数据库 discuz_user 密码: ${YELLOW}${DB_DISCUZ_PASS}${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "${YELLOW}提示: 容器名为 discuz-auto,常用命令:${NC}"
echo -e "  查看日志: docker logs discuz-auto"
echo -e "  停止容器: docker stop discuz-auto"
echo -e "  启动容器: docker start discuz-auto"
echo -e "  进入容器: docker exec -it discuz-auto /bin/sh"
echo -e "${YELLOW}如需持久化数据,请参考文档中的"数据持久化"部分。${NC}"

# 清理临时目录
rm -rf $TEMP_DIR

🔧 如何使用一键脚本

  1. 在宿主机上创建脚本文件

    vi install_discuz.sh
    

    i 进入编辑模式,把上面的脚本内容完整复制进去,然后按 ESC,输入 :wq 保存退出。

  2. 赋予执行权限

    chmod +x install_discuz.sh
    
  3. 运行脚本(需要管理员权限)

    sudo ./install_discuz.sh
    
  4. 按提示输入端口(例如直接回车使用默认 8080,或输入其他如 8888)

  5. 等待几分钟,脚本会自动完成所有工作。最后会输出访问地址和数据库密码。

  6. 打开浏览器,访问显示的地址,就能看到 Discuz 安装向导。按照提示填写数据库信息和管理员账号即可完成安装。

🎉 一键脚本让你彻底告别繁琐的手动配置,再也不用担心敲错命令了!


❓ 第十二部分:常见问题与解决方案

❓ 浏览器打不开页面?

检查步骤

  1. 检查防火墙

    sudo firewall-cmd --add-port=8080/tcp --permanent && sudo firewall-cmd --reload
    

    或者如果是 iptables:

    sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
    
  2. 检查容器是否运行

    docker ps
    

    应该显示 Up 状态。

  3. 在容器内测试

    docker exec -it discuz-running curl -L http://localhost
    

    如果能返回 HTML,说明服务正常,问题在宿主机网络/防火墙。

❓ Discuz 提示"数据库连接失败"?

  1. 检查 MariaDB 是否运行

    docker exec -it discuz-running ps aux | grep mysql
    
  2. 测试数据库连接

    docker exec -it discuz-running mysql -u discuz_user -pdiscuz_pass -e "SELECT 1;"
    

    如果能返回结果,说明数据库连接正常。

  3. 检查数据库配置:确保 Discuz 安装向导中填写的是:

    • 服务器:localhost
    • 数据库名:discuz
    • 用户名:discuz_user
    • 密码:discuz_pass

❓ PHP 页面显示空白或报错?

  1. 查看 PHP-FPM 日志

    docker logs discuz-running 2>&1 | grep -i error
    
  2. 检查 PHP 错误日志

    docker exec -it discuz-running cat /var/log/php82/error.log
    
  3. 检查 PHP 配置

    docker exec -it discuz-running php-fpm82 -i | grep disable_functions
    

    确保 symlinkshell_exec 等函数不在禁用列表中。

❓ 上传文件失败?

  1. 检查上传目录权限

    docker exec -it discuz-running chmod -R 777 /var/www/localhost/data
    
  2. 检查 PHP 上传限制
    /etc/php82/php.ini 中确保:

    upload_max_filesize = 50M
    post_max_size = 50M
    

❓ 如何修改数据库密码?

# 进入容器
docker exec -it discuz-running /bin/sh
# 修改 root 密码
mysqladmin -u root -p'example' password '新密码'
# 修改 discuz_user 密码
mysql -u root -p'新密码' -e "ALTER USER 'discuz_user'@'localhost' IDENTIFIED BY '新新密码';"
# 退出容器
exit

然后修改 Discuz 的数据库配置文件 /var/www/localhost/config/config_global.php/var/www/localhost/config/config_ucenter.php 里的数据库密码。

❓ 如何备份论坛数据?

  • 备份数据库

    docker exec discuz-running mysqldump -u root -p'example' discuz > backup_discuz.sql
    
  • 备份文件

    docker cp discuz-running:/var/www/localhost/. ./discuz-backup/
    

❓ 如何完全卸载/删除?

# 停止并删除容器
docker stop discuz-running
docker rm discuz-running

# 删除镜像
docker rmi my-discuz:alpine

# 如果创建了持久化目录,删除它们
rm -rf /data/discuz

❓ Alpine 提示找不到 php82 包?

确保已正确启用 testing 仓库:

# 检查仓库配置
cat /etc/apk/repositories
# 应该包含 https://dl-cdn.alpinelinux.org/alpine/edge/testing

# 重新更新
apk update

📎 附录

附录 A:常用命令速查表

命令说明
docker ps查看正在运行的容器
docker ps -a查看所有容器(包括停止的)
docker stop 容器名停止容器
docker start 容器名启动容器
docker restart 容器名重启容器
docker rm 容器名删除容器
docker logs 容器名查看容器日志
docker exec -it 容器名 /bin/sh进入容器终端
docker cp 容器名:路径 宿主机路径从容器复制文件到宿主机
docker cp 宿主机路径 容器名:路径从宿主机复制文件到容器
php-fpm82 -t测试 PHP-FPM 配置
nginx -t测试 Nginx 配置

附录 B:配置文件路径速查

软件配置文件路径
Nginx/etc/nginx/http.d/default.conf
PHP-FPM/etc/php82/php-fpm.d/www.conf
PHP 主配置/etc/php82/php.ini
MariaDB 数据/var/lib/mysql/

附录 C:目录结构说明

目录说明
/var/www/localhost/Discuz 程序根目录
/var/www/localhost/config/配置文件目录
/var/www/localhost/data/数据目录(日志、缓存等)
/var/www/localhost/uc_client/Ucenter 客户端
/var/www/localhost/uc_server/Ucenter 服务端
/var/www/localhost/admin.php后台管理入口
/var/www/localhost/forum.php论坛首页
/var/www/localhost/home.php个人空间

附录 D:Discuz 后台管理常用路径

功能URL
后台登录http://你的IP:8080/admin.php
Ucenterhttp://你的IP:8080/uc_server
论坛设置后台 → 全局 → 站点信息
用户管理后台 → 用户 → 用户管理
版块管理后台 → 论坛 → 论坛板块
插件管理后台 → 应用 → 插件

附录 E:技术名词解释

名词解释
Docker容器化平台,把应用和依赖打包成"集装箱",可移植性强
Alpine轻量级 Linux 发行版,体积小(5MB),适合容器环境
LNMPLinux + Nginx + MySQL + PHP 网站运行环境
Nginx高性能 Web 服务器,充当"门卫"接收请求
PHP-FPMPHP FastCGI 进程管理器,解释执行 PHP 脚本
MariaDB开源数据库,MySQL 的分支,存储论坛数据
Discuz!社区论坛软件,国内最流行的论坛系统
端口映射把宿主机的端口转发到容器内部,实现外网访问
数据持久化把容器内数据保存到宿主机,防止删除容器后数据丢失
testing 仓库Alpine 的测试软件仓库,包含尚未进入稳定版的软件(如 PHP 8.2)

附录 F:PHP 版本与扩展对照表

PHP 版本Alpine 仓库包名格式状态
PHP 8.2edge/testingphp82-*推荐
PHP 8.3edge/mainphp83-*⚠️ 第三方插件可能有兼容风险
PHP 8.1edge/mainphp81-*较旧版本

🎉 结语

你从头到尾学习了:

  • Docker 的基本概念和安装
  • 如何进入 Alpine 容器并安装软件
  • 如何手动配置 Nginx、PHP、MariaDB
  • 如何下载和配置 Discuz 论坛
  • 如何让外部访问容器内的服务
  • 如何用一键脚本省去所有麻烦
  • 最重要的是:理解了整个请求的流转路径和各个组件的作用(带步骤序号的流程图)

现在,你已经是一个 Docker + Discuz 的小能手了! 去创建你的论坛社区吧 🚀

如果还有任何疑问,欢迎随时交流~


📝 文档版本:小白友好版 v2.0
📅 更新时间:2025年9月
🔧 适用环境:openEuler 24.03 + Alpine Docker 容器 + Discuz! X3.5 + PHP 8.2
📌 主要更新

  • ✅ PHP 版本从 8.3 降级至 8.2(官方推荐版本)
  • ✅ 启用 Alpine testing 仓库获取 PHP 8.2
  • ✅ 补充缺失的 PHP 扩展(openssl、pdo、pdo_mysql、exif、bcmath)
  • ✅ 更新下载地址为官方发布版
  • ✅ 生成实际架构流程图(PNG 格式)
  • ✅ 所有配置文件路径和命令已更新为 php82

更多推荐