使用 Docker 和 Traefik 搭建 Flarum 輕論壇應用

本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或從新修改使用,但須要註明來源。 署名 4.0 國際 (CC BY 4.0)javascript

本文做者: 蘇洋php

建立時間: 2019年07月16日 統計字數: 10682字 閱讀時間: 22分鐘閱讀 本文連接: soulteary.com/2019/07/16/…css


使用 Docker 和 Traefik 搭建 Flarum 輕論壇應用

最近在作社區類型的項目,出於後續從市場招人成本的考慮,不得不優選市場招聘培養難度較低的 PHP,再三挑選,選擇了這款還在 beta 狀態的軟件。html

這是一款 Beta 了差很少 5 年的軟件,在 GitHub 上擁有接近一萬 star 的耀眼成績,第一條提交記錄 是2014年底的 v0.1.0-beta 發佈。前端

本文將介紹使用容器如何簡單快速的搭建 Flarum ,若是你還不熟悉 Traefik,請翻閱以前的文章java

寫在前面

關於選型的顧慮,我想此刻看到文章的你,也必定有所考慮。mysql

前面提到這款軟件還在 beta ,處於不是特別穩定的情況。並且前一陣主要的貢獻者在論壇裏發佈了一條消息,宣佈「farewell」,看起來是狀況不是特別樂觀,那麼除了招聘維護成本的考慮以外,爲何還要選擇它呢:nginx

  • 交互體驗和項目架子搭的還不錯,基本面作的都還行。
  • 做爲開源應用迭代了五年,有提交記錄和開放的代碼,程序不是特別複雜,相對好追溯和解決問題。
  • 項目文檔雖然不全,可是基礎的部分還差很少是有的。
  • 應用市場雖然東西很少,可是插件機制已經建設好了,功能擴展相對比較簡單。
  • 同語言實現的、功能比較強大的某兩款國產軟件,一個論壇中止運營,一個計劃重構(緣由你懂的),顯然噹噹下時間點都不值得託付。
  • WordPress 的 BuddyPress 生態能夠考慮,可是作一樣需求改動量會更大一些,由於冗餘內容更多。

構建 PHP 容器

官方安裝文檔對於環境要求是這樣的git

  • 支持 URL Rewrite 的服務器軟件:Apache、Nginx…
  • PHP 7.1+,以及 domgdjsonmbstringopenssl, 、 pdo_mysqltokenizer 組件。
  • MySQL 5.6+MariaDB 10.0.5+
  • Composer

因此,Docker Hub 默認的提供的 PHP 鏡像是使用不了的,須要進行額外配置,安裝以上須要的軟件。咱們默認不容許在已經運行起來的軟件中執行插件卸載(刪除程序部分文件),因此最後一點提到的 composer 能夠在本地安裝,或者乾脆不進行安裝。github

這裏以 PHP-FPM-ALPINE 7.3.2 爲例:

FROM php:7.3.2-fpm-alpine

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8
ENV LC_ALL=en_US.UTF-8

RUN echo '' > /etc/apk/repositories && \
    echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.9/main"         >> /etc/apk/repositories && \
    echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.9/community"    >> /etc/apk/repositories && \
    echo "Asia/Shanghai" > /etc/timezone

RUN apk --no-cache --no-progress update && \
    apk --no-cache --no-progress upgrade

RUN apk add libpng libpng-dev libjpeg-turbo-dev libwebp-dev zlib-dev libxpm-dev

RUN docker-php-ext-install pdo pdo_mysql mbstring gd

ENTRYPOINT ["docker-php-entrypoint"]

STOPSIGNAL SIGQUIT

EXPOSE 9000
CMD ["php-fpm"]
複製代碼

使用 build 命令將容器構建起來:

docker build -t php-fpm-flarum:7.3.2  -f Dockerfile .
複製代碼

使用 docker images 查看構建後的 PHP 鏡像,一百兆出頭。

REPOSITORY                               TAG                     IMAGE ID            CREATED             SIZE
php-fpm-flarum                           7.3.2                   ef5ad124a35d        3 minutes ago       105MB
複製代碼

搭建數據庫

上一小節有提到過,官方對於數據庫方面的要求是:MySQL 5.6+MariaDB 10.0.5+,因此你能夠根據本身喜愛來搞,若是有性能要求,建議使用雲廠商的 RDS 產品。

下面給出一個數據庫編排文件示例:

version: '3.6'

services:

  database:
    image: ${DB_IMAGE}
    restart: always
    container_name: ${DB_HOST}
    ports:
      - 3306:3306
    networks:
      - traefik
    environment:
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASS}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
    volumes:
      - ./data:/var/lib/mysql

networks:
  traefik:
    external: true
複製代碼

將上面的配置保存爲 docker-compose.yml ,繼續編寫配置須要的 .env 文件。我這邊爲了測試方便,就都用弱密碼了,實際使用應改爲安全度較高的複雜密碼。

DB_IMAGE=mysql:5.7.26
DB_HOST=flarum
DB_NAME=flarum
DB_USER=flarum
DB_PASS=flarum
DB_ROOT_PASS=flarum
複製代碼

而後執行 docker-compose up -d 數據庫就運行起來啦。

搭建應用運行框架

時至今日,官方提供的安裝方案也從傳統的軟件壓縮包變成了一條簡約的命令:

composer create-project flarum/flarum . --stability=beta
複製代碼

可是這樣作對於持續迭代的項目的開發部署體驗是不友好的,即便使用版本鎖定功能,項目構建仍是時間會變長,把代碼都打到容器裏由顯得笨重,而且形成了相同應用的代碼割裂,維護成本頗高。

並且後續須要在程序框架上作一些改動,還要解決和將來的版本更新合併的問題,並不僅是簡單的安裝使用就完事了,因此這裏須要將應用代碼儲存下來。

安裝 Composer PHP 包管理軟件

由於軟件發佈模式變化,因此咱們下載軟件包須要使用 Composer (PHP 環境安裝不贅述)。

wget -O composer-setup.php https://getcomposer.org/installer

php composer-setup.php --install-dir=bin --filename=composer
複製代碼

Composer 在國內下載比較慢,這裏能夠選擇藉助阿里雲的加速鏡像,使用方法很簡單,就一條命令。

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
複製代碼

下載 Flarum 程序代碼

接着使用下面的命令將軟件下載至 flarum 目錄。

`composer create-project flarum/flarum ./flarum --stability=beta`
複製代碼

完成安裝後的目錄結構是下面的樣子:

flarum
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
├── composer.lock
├── extend.php
├── flarum
├── public
│   ├── assets
│   └── index.php
├── storage
│   ├── cache
│   ├── formatter
│   ├── less
│   ├── locale
│   ├── logs
│   ├── sessions
│   ├── tmp
│   └── views
└── vendor
複製代碼

如今軟件還運行不起來,咱們須要繼續配置應用的運行環境。

配置軟件運行環境

在上面的操做都就緒以後,咱們就能夠進行程序運行環境搭建了。這裏使用 Nginx 做爲 PHP 的前端,整個環境搭建很是簡單。

version: "3.6"

services:

  nginx:
    image: ${DOCKER_NGINX_IMAGE}
    restart: always
    expose:
      - 80
    volumes:
      - ./logs:/var/log/nginx
      - ./conf/docker-nginx.conf:/etc/nginx/nginx.conf
      - ./wwwroot:/wwwroot
    links:
      - php:php
    extra_hosts:
      - "${DOCKER_DOMAIN_NAME}:127.0.0.1"
    networks:
      - traefik
    labels:
      - "traefik.enable=true"
      - "traefik.port=80"
      - "traefik.frontend.rule=Host:${DOCKER_DOMAIN_NAME}"
      - "traefik.frontend.entryPoints=https,http"
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider --proxy off http://${DOCKER_DOMAIN_NAME}/get-health || exit 1"]
      interval: 5s
      retries: 12
    logging:
        driver: "json-file"
        options:
            max-size: "100m"

  php:
    image: ${DOCKER_PHP_IMAGE}
    restart: always
    expose:
      - 9000
    volumes:
      - ./logs:/var/log
      - ./wwwroot:/wwwroot
    extra_hosts:
      - "${DOCKER_DOMAIN_NAME}:127.0.0.1"
    networks:
      - traefik
    healthcheck:
      test: ["CMD-SHELL", "pidof php-fpm"]
      interval: 5s
      retries: 12
    logging:
      driver: "json-file"
      options:
        max-size: "100m"

networks:
  traefik:
    external: true
複製代碼

搭配使用的 .env 能夠這麼寫:

DOCKER_DOMAIN_NAME=flarum.lab.com
DOCKER_PHP_IMAGE=php-fpm-flarum:7.3.2
DOCKER_NGINX_IMAGE=nginx:1.17.1-alpine
複製代碼

Nginx 的配置則能夠參考下面的文件:

user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events { worker_connections 1024; }

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    log_format main '$http_x_forwarded_for - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
    access_log off;
    sendfile on;
    keepalive_timeout 65;

    server {
        listen 80;
        server_name flarum.lab.com;
        server_tokens off;
        access_log /var/log/nginx/docker-access.log;
        error_log /var/log/nginx/docker-error.log;
        root /wwwroot/public;
        index index.php index.html;

        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass php:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
        }

        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
        # The following directives are based on best practices from H5BP Nginx Server Configs
        # https://github.com/h5bp/server-configs-nginx
        # Expire rules for static content
        location ~* \.(?:manifest|appcache|html?|xml|json)$ {
            add_header Cache-Control "max-age=0";
        }
        location ~* \.(?:rss|atom)$ {
            add_header Cache-Control "max-age=3600";
        }
        location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|mp4|ogg|ogv|webm|htc)$ {
            add_header Cache-Control "max-age=2592000";
            access_log off;
        }
        location ~* \.(?:css|js)$ {
            add_header Cache-Control "max-age=31536000";
            access_log off;
        }
        location ~* \.(?:ttf|ttc|otf|eot|woff|woff2)$ {
            add_header Cache-Control "max-age=2592000";
            access_log off;
        }
        location = /get-health {
            access_log off;
            default_type text/html;
            return 200 'alive';
        }
        # 能夠考慮交給後面的程序去處理,好比 traefik ...
        # 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/plain
                    text/vcard
                    text/vnd.rim.location.xloc
                    text/vtt
                    text/x-component
                    text/x-cross-domain-policy;
    }
}
複製代碼

將以前下載完畢的 flarum 程序放置到 wwwroot 目錄中,即可以開始程序的安裝了。

使用 docker-compose up -d 將程序運行起來,訪問 flarum.lab.com 對程序進行配置。

安裝應用

簡單填寫安裝界面須要的要素後,點擊安裝按鈕。

親切的安裝界面

片刻以後,程序安裝就完畢了,能夠看到界面仍是十分清爽的。

清爽的界面

管理後臺比較簡單,很難知足咱們的平常使用需求,不過好在如今能夠編寫插件進行功能加強。

管理後臺

對程序運行框架作優化

程序的安裝部分已經結束了,可是考慮到後續的維護,咱們還須要作一些額外的工做。

讓應用自適應運行環境

應用安裝完畢,咱們再次查看應用目錄,發現目錄中多了一個 config.php 文件。

wwwroot
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
├── composer.lock
├── config.php
├── extend.php
├── flarum
├── public
│   ├── assets
│   └── index.php
├── storage
│   ├── cache
│   ├── formatter
│   ├── less
│   ├── locale
│   ├── logs
│   ├── sessions
│   ├── tmp
│   └── views
└── vendor
複製代碼

文件內容以下,記錄了程序運行配置:

<?php return array (
  'debug' => false,
  'database' =>
  array (
    'driver' => 'mysql',
    'host' => 'flarum',
    'port' => 3306,
    'database' => 'flarum',
    'username' => 'flarum',
    'password' => 'flarum',
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => 'flarum_',
    'strict' => false,
    'engine' => 'InnoDB',
    'prefix_indexes' => true,
  ),
  'url' => 'https://flarum.lab.com',
  'paths' =>
  array (
    'api' => 'api',
    'admin' => 'admin',
  ),
);
複製代碼

考慮到程序可能運行在不一樣的環境中(生產、測試、開發),數據庫、網站地址等信息存在變化的可能,若是它可以自動讀取環境變量能夠免除維護多份配置的麻煩事,並簡化發佈過程。

對它進行簡單的修改:

<?php return array (
  'debug' => ($_SERVER['FLARUM_APP_DEBUG'] === 'true'),
  'database' =>
  array (
    'driver' => 'mysql',
    'host' => $_SERVER['FLARUM_DB_HOST'],
    'database' => $_SERVER['FLARUM_DB_NAME'],
    'username' => $_SERVER['FLARUM_DB_USER'],
    'password' => $_SERVER['FLARUM_DB_PASS'],
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => 'flarum_',
    'port' => '3306',
    'strict' => false,
  ),
  'url' => $_SERVER['FLARUM_APP_URL'],
  'paths' =>
  array (
    'api' => 'api',
    'admin' => 'admin',
  ),
);
複製代碼

同時也要對 docker-compose.yml 進行簡單的修改,把 .env 看成環境變量「注入」到應用中。

php:
    image: ${DOCKER_PHP_IMAGE}
    restart: always
    expose:
      - 9000
    env_file: .env
複製代碼

最後,在 .env 裏聲明上面配置文件須要的變量名稱便可。

DOCKER_DOMAIN_NAME=flarum.lab.com
DOCKER_PHP_IMAGE=php-fpm-flarum:7.3.2
DOCKER_NGINX_IMAGE=nginx:1.17.1-alpine

FLARUM_DB_HOST=flarum
FLARUM_DB_NAME=flarum
FLARUM_DB_USER=flarum
FLARUM_DB_PASS=flarum

FLARUM_APP_DEBUG=true
FLARUM_APP_URL=//flarum.lab.com
複製代碼

繼續拆分項目結構

前文提過,若是咱們要持續修改完善這個處於 beta 狀態下的軟件,須要對其代碼進行保存維護,可是若是將環境和代碼放置一處,修改調試的效率難免過低。

因此咱們能夠對上面的應用目錄進行簡化操做,將「應用代碼」和「基礎環境」進行拆分,將來調試發佈僅須要更新文件便可,而沒必要對環境進行從新部署、重啓等重操做。

若是你也有相似需求,也能夠參考下圖進行拆分,將應用軟件的基礎環境、Vendor 代碼進行分拆。

拆分項目結構

簡化後的目錄以下:

.
├── LICENSE
├── README.md
├── .env
├── conf
│   └── docker-nginx.conf
├── logs
├── update.sh
└── wwwroot
    ├── config.php
    ├── extend.php
    ├── flarum
    ├── public
    │   └── index.php
    ├── storage
    └── vendor
複製代碼

能夠看到,wwwroot 目錄被簡化到只留下四個 PHP 文件,和幾個空目錄。

對程序進行修改發佈,則可使用 CI 配合 update.sh 更新腳本使用,將程序須要的 vendor 依賴文件進行同步更新,更新腳本能夠參考下面:

#!/usr/bin/env bash 
# 關閉服務
echo "stop services."
docker-compose down --remove-orphans

# 確保容器鏡像存在
cat .env | grep _IMAGE | cut -d '=' -f2 | while read image ; do
  if test -z "$(docker images -q $image)"; then
    echo "prepare docker images."
    docker pull $image
  fi
done

# 清理以前存在的歷史文件,並將新文件同步到執行目錄中
if [ -d "wwwroot/vendor" ]; then
    echo "cleanup wwwroot/vendor."
    rm -rf wwwroot/vendor
fi
if [ -d "/data/forum-test-vendor" ]; then
    echo "update vendor."
    cp -r /data/forum-test-vendor/vendor/ wwwroot/
    cp /data/forum-test-vendor/composer.* wwwroot/
fi


# 清理 & 重建目錄
echo 'cleanup directory'
rm -rf ./wwwroot/storage
mkdir -p ./wwwroot/storage/cache
mkdir -p ./wwwroot/storage/formatter
mkdir -p ./wwwroot/storage/less
mkdir -p ./wwwroot/storage/locale
mkdir -p ./wwwroot/storage/logs
mkdir -p ./wwwroot/storage/sessions
mkdir -p ./wwwroot/storage/tmp
mkdir -p ./wwwroot/storage/views

# 重啓服務
echo 'restart services.'
docker-compose up -d

# 修正文件權限
docker ps -q -f status=running -f name=flarum_php |  while read container ; do
   echo "fix container $container own && mod."
   docker exec $container chown -R www-data:www-data /wwwroot
   docker exec $container chmod -R 755 /wwwroot/storage
done
複製代碼

在進行了目錄拆分後,項目的測試發佈時間將能夠從以前的分鐘級縮短到 5~10s 秒。

最後

關於這個軟件的折騰細節還有很多,後續陸續慢慢寫出來吧。

引用我前一段時間在朋友圈發的內容做爲結束:

合做單位在關鍵時刻因不可抗力取消了合做,週五機器刪除代碼、數據庫下線。全部人五十天的忙碌付諸東流,項目按計劃上線壓力驟大。

只好重定方案,從MVP作起。不得再也不次變身救火隊員👩‍🚒。

從收拾遺留問題、到作新架構設計、搭建各類環境和基礎設施、調通後端基本流程,整了差很少三天。目測再搞一週應該就差很少啦!🎉

感謝各類開源軟件,讓問題變得快速可解,讓我這個月還能空出時間辦個「大事」。


我如今有一個小小的折騰羣,裏面彙集了一些喜歡折騰的小夥伴。

在不發廣告的狀況下,咱們在裏面會一塊兒聊聊軟件、HomeLab、編程上的一些問題,也會在羣裏不按期的分享一些技術沙龍的資料。

喜歡折騰的小夥伴歡迎掃碼添加好友。(請註明來源和目的,不然不會經過審覈)

關於折騰羣入羣的那些事

相關文章
相關標籤/搜索