用docker compose部署flarum论坛系统带msmtpd redis Meilisearch

原文永久链接:https://forum.piwind.com/d/18-yong-docker-composebu-shu-flarumlun-tan-xi-tong-dai-msmtpd-redis-meilisearch

Date: 2025-06-09

鉴于很多人问和搜索如何使用docker compose部署flarum论坛系统,并且配置msmtpd作为邮件发送服务器,redis作为缓存,meilisearch作为搜索引擎。这里单独发送一个帖子来讨论这个。

注意,此文为分支,汇总贴地址:flarum轻量化开源论坛系统部署 - Piwind Forum

查看部署案例:https://forum.piwind.com/

看到官方没有提供docker部署方式,在dockerhub上找到这个项目:

官方指定的安装方式为:依赖nginx/apache,php 7.3+,mysql 5.6+/8.0.23+,安装PHP仓库管理软件Composer,并通过Composer来下载flarum项目。

本次技术路线:第三方crazymax/flarum构建的docker镜像,后端数据库使用MariaDB,再添加几个辅助容器(msmtpd作为SMTP服务器,redis作为缓存,meilisearch作为搜索引擎)

1. 安装flarum

先从镜像中提取要映射的文件,或者直接手写相应的初始文件(手写注意配owner和权限):

【容器中的/opt/flarum/config.php是每次启动时动态生成的,因此不推荐映射出来,而是通过修改容器环境变量实现修改】

mkdir -p /data/linux/docker_data/flarum/flarum
touch /data/linux/docker_data/flarum/flarum/extend.php
# 注意替换成实际的PUID:PGID
chown 1000:1000 /data/linux/docker_data/flarum/flarum/*
mkdir -p /data/linux/docker_data/flarum/s6-services/flarum-queue
mkdir -p /data/linux/docker_data/flarum/s6-services/cron
touch /data/linux/docker_data/flarum/s6-services/flarum-queue/run
touch /data/linux/docker_data/flarum/s6-services/cron/run
chmod +x /data/linux/docker_data/flarum/s6-services/flarum-queue/run
chmod +x /data/linux/docker_data/flarum/s6-services/cron/run

编写 /data/linux/docker_data/flarum/flarum/extend.php,内容如下:

<?php

use Flarum\Extend;

return [
    (new FoF\Redis\Extend\Redis([
        'host' => 'flarum_redis',
        'password' => 'testpassword',
        'port' => 6379,
        'database' => 1,
        'queue' => [
            'retry_after' => 120, // seconds
            'block_for' => 5, // seconds
            'after_commit' => true 
        ] 
    ]))
    ->useDatabaseWith('cache', 1)
    ->useDatabaseWith('queue', 2)
    ->useDatabaseWith('session', 3)
];

编写 /data/linux/docker_data/flarum/s6-services/flarum-queue/run,内容如下:

#!/usr/bin/execlineb -P
s6-setuidgid 1000:1000  # 注意替换成实际的PUID:PGID
php /opt/flarum/flarum queue:work

编写 /data/linux/docker_data/flarum/s6-services/cron/run,内容如下:

#!/usr/bin/execlineb -P
foreground {
  redirfd -w 1 /var/spool/cron/crontabs/root
  echo "* * * * * php /opt/flarum/flarum schedule:run"
}
crond -f -L /dev/stdout

在portainer中创建stack,命名为 flarum,注意点如下:

  • 不能把/opt/flarum整个映射出来

  • 修改FLARUM_BASE_URL为实际

  • MEILI_MASTER_KEY可以用 uuidgen 来随机生成一个

  • SMTP_STARTTLS在使用端口587的时候on,使用端口465的时候off

  • REAL_IP_FROM填写可信代理ip,也就是stack的docker network的Subnet,查看方式为:

    docker network inspect flarum_default | grep Subnet
    

内容如下:

name: flarum

services:
  flarum:
    image: crazymax/flarum:1.8.9
    container_name: flarum
    restart: unless-stopped
    ports:
      - '2042:8000'
    volumes:
      - '/data/linux/docker_data/flarum/data:/data'
      - '/data/linux/docker_data/flarum/flarum/extend.php:/opt/flarum/extend.php'
      - '/data/linux/docker_data/flarum/s6-services/flarum-queue:/etc/services.d/flarum-queue'
      - '/data/linux/docker_data/flarum/s6-services/cron:/etc/services.d/cron'
    environment:
      - "TZ=Asia/Hong_Kong"
      - "FLARUM_FORUM_TITLE=Piwind Forum"
      - "DB_HOST=db"
      - "DB_NAME=flarum"
      - "DB_USER=flarum"
      - "DB_PASSWORD=testpassword"
      - "MEMORY_LIMIT=256M"
      - "UPLOAD_MAX_SIZE=16M"
      - "OPCACHE_MEM_SIZE=128"
      - "REAL_IP_FROM=172.21.0.0/16"
      - "REAL_IP_HEADER=X-Forwarded-For"
      - "LOG_IP_VAR=remote_addr"
      - "FLARUM_DEBUG=false"
      - "FLARUM_BASE_URL=http://127.0.0.1:8000"
      - "FLARUM_POWEREDBY_HEADER=false"
      - "FLARUM_REFERRER_POLICY=strict-origin-when-cross-origin"
    depends_on:
      - db
      - msmtpd
      - redis
      - meilisearch

  db:
    image: mariadb:10.11.11
    container_name: flarum_db
    restart: unless-stopped
    command:
      - "mysqld"
      - "--character-set-server=utf8mb4"
      - "--collation-server=utf8mb4_unicode_ci"
    volumes:
      - "/data/linux/docker_data/flarum/db:/var/lib/mysql"
    environment:
      - "TZ=Asia/Hong_Kong"
      - "MARIADB_RANDOM_ROOT_PASSWORD=yes"
      - "MYSQL_DATABASE=flarum"
      - "MYSQL_USER=flarum"
      - "MYSQL_PASSWORD=testpassword"

  msmtpd:
    image: crazymax/msmtpd:1.8.28
    container_name: flarum_msmtpd
    restart: unless-stopped
    environment:
      - "TZ=Asia/Hong_Kong"
      - "SMTP_HOST=smtp.gmail.com"
      - "SMTP_PORT=587"
      - "SMTP_TLS=on"
      - "SMTP_STARTTLS=on"
      - "SMTP_TLS_CHECKCERT=on"
      - "SMTP_AUTH=on"
      - "SMTP_USER=foo"
      - "SMTP_PASSWORD=bar"
      - "SMTP_FROM=foo@gmail.com"

  redis:
    image: redis:7.4.2
    container_name: flarum_redis
    restart: unless-stopped
    command: redis-server --requirepass testpassword
    volumes:
      - "/data/linux/docker_data/flarum/redis:/data"
    depends_on:
      - db

  meilisearch:
    image: getmeili/meilisearch:v1.13.3
    container_name: flarum_meilisearch
    restart: unless-stopped
    command: /bin/meilisearch
    volumes:
      - "/data/linux/docker_data/flarum/meili_data:/meili_data"
    environment:
      - MEILI_MASTER_KEY=xxxxxxxxxxxxxxxx
      - MEILI_NO_ANALYTICS=true
      - MEILI_ENV=production
    depends_on:
      - db
      - redis

补充解释:

  • FLARUM_POWEREDBY_HEADER=false,隐藏网站响应头中的X-Powered-By信息,这个是用来显示技术栈的,比如该应用就是Flarum,没必要暴露出来
  • FLARUM_REFERRER_POLICY=strict-origin-when-cross-origin,默认的same-origin会在跨源请求(Cross-Origin)中不发送referer请求头,会影响防盗链策略

stack启动后还需要配置nginx,创建文件 /etc/nginx/conf.d/forum.piwind.com.conf,内容如下:

    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        http2 on;

        server_name forum.piwind.com;
        ssl_certificate       /data/linux/files/tls_certs/piwind.com.fullchain.cer;
        ssl_certificate_key   /data/linux/files/tls_certs/piwind.com.key;

        # 添加可信代理设置(Docker网关IP范围)
        set_real_ip_from 172.21.0.0/16;
        set_real_ip_from 127.0.0.1;
        real_ip_header X-Forwarded-For;
        real_ip_recursive on;

        # Gzip compression
        gzip on;
        gzip_comp_level 5;
        gzip_min_length 256;
        gzip_proxied any;
        gzip_vary on;
        gzip_types
            application/atom+xml
            application/javascript
            application/json
            application/ld+json
            application/manifest+json
            application/rss+xml
            application/vnd.geo+json
            application/vnd.ms-fontobject
            application/x-font-ttf
            application/x-web-app-manifest+json
            application/xhtml+xml
            application/xml
            font/opentype
            image/bmp
            image/svg+xml
            image/x-icon
            text/cache-manifest
            text/css
            text/javascript
            text/plain
            text/vcard
            text/vnd.rim.location.xloc
            text/vtt
            text/x-component
            text/x-cross-domain-policy;

        location / {
            proxy_pass http://127.0.0.1:2042/;

            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            add_header 'Access-Control-Allow-Origin' $http_origin;
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT';
            add_header 'Access-Control-Allow-Headers' 'Origin, x-requested-with, Content-Type, Accept, Authorization';
            add_header 'Access-Control-Expose-Headers' 'Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma';

            # 处理预检请求
            if ($request_method = 'OPTIONS') {
                # 预检请求缓存时间
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain; charset=utf-8';
                add_header 'Content-Length' 0;
                return 204;
            }

            proxy_connect_timeout 600;
            proxy_read_timeout 600;
        }

    }

为了msmtpd能够使用gmail的SMTP服务,需要在gmail上开启SMTP服务:

  • 登录Google Account,Security - 2-Step Verification,开启两步验证才能设置 App passwords

  • 访问链接:https://myaccount.google.com/apppasswords

    创建一个随机16位的App password

  • 可以在gmail中添加期望的邮箱地址授权为发件人地址并完成验证,以便使用自己的域名邮箱发件

2. 基础配置

通过URL首次登录,输入管理员的默认账密(账号:flarum,密码:flarum)登录

  • 先进入Admin area,Email,设置如下:

    Addresses: no-reply@gmail.com
    Driver: smtp
    Host: msmtpd
    Port: 2500
    
    【这里如果填写的Addresses的和gmail SMTP的邮箱不一致的话】,会在邮件源码中添加一行这个信息例如:
    X-Google-Original-From: Piwind Forum <noreply@piwind.com>
    并且用户收到邮件看到的发件人仍然为SMTP的邮箱地址,而不是这里填写的
    需要在gmail中将期望的邮箱地址授权为发件人地址并完成验证,才能将这个地址替换"From"字段
    
  • 管理员账号修改邮箱,发送修改密码的邮件修改密码

  • 右上角 设置 - 操作 - 编辑,修改昵称和用户名,可以修改为admin

  • Dashboard中,把基础的Features全都开起来(核心插件)

    Flags			帖子旁边添加举报按钮
    Approval		让主题和回复变得需要管理员审批才能公开
    BBCode			传统的论坛文本格式化语法,例如[b]text[/b],还包括登录可见等专属于论坛的语法
    Emoji			表情功能,例如 :cry 就是哭脸表情
    Likes			可以赞帖子【不启用,用fof/gamification来替代,但是注意关闭原生Likes插件会导致基于Likes的插件功能故障】
    Lock			可以锁定帖子不接受回复(默认只有管理员能锁定帖子)
    Markdown		帖子支持markdown(但语法有限,例如表格不行)
    Mentions		帖子可以@用户名或昵称(允许@用户名,开启)
    Nicknames		User Display Name要设置成nickname才能生效,开启唯一昵称,昵称长度6~20
    Pusher			新主题或回复发布后,会立即出现,无需手动刷新页面【需要配置】
    Statistics		方便管理员统计论坛中的数据
    Sticky			管理员可以置顶主题
    Subscriptions	允许用户关注讨论并接收新帖子的通知
    Suspend			允许管理员禁言用户,在点开用户的主页之后操作禁言
    Tags			给论坛添加标签功能,有primary tags和secondary tags,分别起到分类和标签的作用
    

3. 安装插件

使用docker容器里的脚本extension,也可以用composer,命令如下:

## 安装flarum插件
extension require <package> [<package> ...]
## 删除插件
extension remove <package> [<package> ...]
## 列举安装的插件
extension list

## 例如安装 fof/upload
# 其链接为:https://flarum.org/extension/fof/upload
extension require fof/upload
## 可以直接调用,也可以进shell
docker exec -it flarum sh
extension require fof/upload
docker exec -it flarum extension require fof/upload

## 查看所有已安装的composer包(包括 Flarum 核心和插件)【看到296个】
composer show
## 只查看直接依赖的包(不包括依赖的依赖)【看到100个】
composer show --direct
## 查看特定 Flarum 扩展的信息(例如 flarum-tags)
composer show flarum/tags

## Flarum 提供了 info 命令来查看已安装的扩展【看到83个】
php flarum info
## 还可以看composer.json【看到100个】
cat composer.json
## 还有vender下【看到296个】
find vendor/ -maxdepth 2 -mindepth 2 -type d | wc -l

简体中文

docker exec -it flarum extension require flarum-lang/chinese-simplified

在仪表盘中启用即可,再在常规中,设置默认语言,显示语言选择器

Redis配置sessions, cache, queues

docker exec -it flarum extension require fof/redis

检查flarum-redis生效:

默认情况下,队列驱动程序是 sync,会话驱动程序是 file,配置好redis之后在仪表盘可以看到如下:

Image description

完成后还需要配置Laravel 队列以持续监听redis中的队列并执行任务:

(不配置的话会导致用户通知收不到等问题)

方法通常有配置supervisor 或 systemd,本次采用镜像中已有的s6-overlay工具,也就是前面安装flarum过程中配置的 s6-services/flarum-queue/run,在容器进程中能看到php /opt/flarum/flarum queue:work的进程常驻即可。

Meilisearch配置Scout Search【TODO】

docker exec -it flarum extension require clarkwinkelmann/flarum-ext-scout
docker exec -it flarum extension require meilisearch/meilisearch-php

Scout Search,启用,配置如下:

驱动:Meilisearch
处理队列中的索引更新:开
Meilisearch 主机地址:http://flarum_meilisearch:7700
Meilisearch 秘钥:xxxxxxxxxxxxxxxx

配置完之后还需要初始化构建索引:

docker exec -it flarum php flarum scout:import-all

之后就可以正常调用搜索了。

TODO:

  • 在永久删除帖子的时候,会有报错:

    flarum.ERROR: Error: Call to undefined method ClarkWinkelmann\Scout\Job\RemoveFromSearch::getUnqualifiedScoutKeyName() in /opt/flarum/vendor/clarkwinkelmann/flarum-ext-scout/src/Job/RemoveFromSearch.php:22
    

最佳回复best-answer

docker exec -it flarum extension require fof/best-answer

FoF Best Answer,启用,必要配置如下(因为可能会和Scout Search冲突):

问答搜索:关
在主搜索中隐藏:关
在搜索结果中展示标签:关

注意:fof/best-answer插件依赖scheduler实现定时提醒任务,需要在cron中配置:

本次使用s6-overlay工具来守护crond -f的进程,让其每分钟执行php /opt/flarum/flarum schedule:run,,也就是前面安装flarum过程中配置的 s6-services/cron/run,配置成功后在dashboard中可以看到如下:

Image description

Extension Manager

docker exec -it flarum extension require flarum/extension-manager

方便安装和更新扩展程序,可以设置在队列中执行操作,不过没有查看现有扩展列表的功能,管理页面中没有启用的插件,右侧有重置和卸载的按钮

参考链接

本文声明:

  • 此文可能会存在排版、样式不美观,图片无法显示等问题
  • 文章内容在原文永久链接中会定期更新,此文不做同步更新
  • 限于篇幅长度限制,此文可能会有裁剪

建议阅读原文链接

原创作者: piwind 转载于: https://www.cnblogs.com/piwind/p/18921471
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值