本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或從新修改使用,但須要註明來源。 署名 4.0 國際 (CC BY 4.0)php
本文做者: 蘇洋css
建立時間: 2020年03月15日 統計字數: 14188字 閱讀時間: 29分鐘閱讀 本文連接: soulteary.com/2020/03/15/…html
距離寫完《使用 Docker 和 Traefik 搭建 Flarum 輕論壇應用》已通過去了十個月。前端
在上一篇搭建教程中,我描述過這個應用的優劣勢,由於缺少開發者,因此時隔近一年的時間裏,軟件除了可以保持緩慢前行外,並無實質的變化。國內相關社區一樣由於缺乏活力,依舊還在使用陳舊的迭代方案,短時間來看,應該不會有太多驚喜出現,不過做爲一款輕量社區來說,flarum 是合格的。mysql
本文將介紹如何使用 Docker 來對 Flarum 最新版 v0.1.0-beta.12 進行容器封裝,以及如何搭配 traefik v2 一塊兒使用。nginx
在這篇「搭建RSS工具」文章的末尾,我提過:git
以前寫文章老是考慮沒有閱讀基礎的同窗,而忽略了一直訂閱、關注着個人同窗,將來重複的內容,我將會和本文同樣,給予簡短的指引,不贅述基礎建設,只聊主題相關的核心部分。github
爲了保證內容的簡潔,相關資料能夠自行從網站歷史資料找翻閱,學習這件事只有探索折騰纔有意思,不是麼?web
單機論壇能夠考慮使用下面的編排文件,啓動項目所需的數據庫和緩存服務。redis
version: '3.6'
services:
mysql:
container_name: ${DOCKER_MYSQL_HOST}
image: ${DOCKER_MYSQL_IMAGE}
restart: always
expose:
- 3306
networks:
- traefik
environment:
MYSQL_USER: ${DOCKER_MYSQL_USER}
MYSQL_PASSWORD: ${DOCKER_MYSQL_PASS}
MYSQL_DATABASE: ${DOCKER_MYSQL_NAME}
MYSQL_ROOT_PASSWORD: ${DOCKER_MYSQL_ROOT}
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --default-storage-engine=INNODB --max_allowed_packet=256M --transaction-isolation=READ-COMMITTED --binlog_format=row --ngram_token_size=2
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
- ./db:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "/etc/init.d/mysql status"]
interval: 30s
redis:
image: ${DOCKER_REDIS_IMAGE}
restart: always
container_name: ${DOCKER_REDIS_HOST}
expose:
- 6379
networks:
- traefik
healthcheck:
test: ["CMD", "redis-cli", "ping"]
environment:
TZ: Asia/Shanghai
networks:
traefik:
external: true
複製代碼
將上面的內容保存爲 docker-compose.yml
,而後繼續配置 .env
環境變量文件。
DOCKER_REDIS_IMAGE=redis:5.0.8-alpine
DOCKER_REDIS_HOST=flarum-redis.lab.com
DOCKER_MYSQL_IMAGE=mysql:5.7
DOCKER_MYSQL_HOST=flarum-db.lab.com
DOCKER_MYSQL_USER=flarum
DOCKER_MYSQL_PASS=flarum
DOCKER_MYSQL_NAME=flarum
DOCKER_MYSQL_ROOT=flarum
複製代碼
兩個文件都準備好後,使用 docker-compose up -d
,啓動數據庫和緩存服務便可。
爲了讓 flarum 支持搜索中文內容,全文檢索以配置好,最小搜索長度爲 2,若是有特殊需求能夠修改 --ngram_token_size=2
爲適合你的數值。
若是你不須要使用 Redis Session 功能,能夠刪除掉 Redis 相關內容。
爲了項目的可維護性,咱們通常須要將應用和其依賴組件進行版本鎖定。因此這裏建議使用 composer 將代碼下載下來後,做爲「代碼基」使用代碼倉庫單獨管理保存,而非在容器中進行下載構建,這樣對於每次軟件變動都能作到心中有數。
和以前同樣,咱們使用下面的命令能夠將 flarum 當前最新的 beta 版本下載到本地。
composer create-project flarum/flarum ./codebase --stability=beta
複製代碼
若是長時間不能完成下載,能夠在命令行後添加 -vvv
,能夠輔助判斷是由於什麼問題致使下載出現異常。
若是是由於網絡問題,能夠考慮使用下面的方法,將 composer 源修改成Aliyun或其餘國內 CDN 地址(以aliyun爲例):
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
複製代碼
修改完畢以後,可使用下面的命令驗證修改是否成功。
composer config -g -l repo.packagist | grep repositories.packagist.org.url
# 輸出以下則修改爲功
[repositories.packagist.org.url] https://mirrors.aliyun.com/composer/
複製代碼
修改完畢以後,再次執行 create-project
命令便可。
若是是使用 flarum 作線上業務,此處能夠考慮使用生產環境的私有 composer 搭配持續集成進行操做,安全性和可靠性會有極大的提高,細節可參考下面兩篇文章:《搭建高性能的私有 Composer 鏡像服務》、《如何搭配 CI 系統使用 Composer》。
準備好的 codebase 目錄結構以下:
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
├── composer.lock
├── extend.php
├── flarum
├── public
├── site.php
├── storage
└── vendor
複製代碼
確認 codebase 目錄內已經保存了完整的 flarum 程序後,咱們開始編寫容器鏡像配置文件。
以前文章中,我使用了當時最新的 PHP 7.3.2
,現在 PHP 7.4
已經到來,因此這裏將使用最新版本的 PHP 封裝 Flarum 的運行環境,我當前選擇的版本是:php:7.4-fpm-alpine3.11
。
Dockerfile 文件內容可參考下面:
FROM php:7.4-fpm-alpine3.11
LABEL maintainer="soulteary@gmail.com"
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8
ENV LC_ALL=en_US.UTF-8
ARG USE_CHINA_MIRROR=0
RUN if [ "$USE_CHINA_MIRROR" = 1 ]; then \
echo 'use china mirror' && \
echo '' > /etc/apk/repositories && \
echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.11/main" >> /etc/apk/repositories && \
echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.11/community" >> /etc/apk/repositories && \
echo "Asia/Shanghai" > /etc/timezone; \
fi
RUN apk --no-cache --no-progress update && \
apk --no-cache --no-progress upgrade
RUN apk add libpng libpng-dev libjpeg-turbo libjpeg-turbo-dev libwebp libwebp-dev zlib-dev libxpm-dev freetype freetype-dev oniguruma-dev
RUN docker-php-ext-install pdo pdo_mysql mbstring
RUN docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ && \
docker-php-ext-install -j$(getconf _NPROCESSORS_ONLN) gd
ENTRYPOINT ["docker-php-entrypoint"]
WORKDIR /var/www/html
RUN set -eux; \
cd /usr/local/etc; \
if [ -d php-fpm.d ]; then \
# for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
else \
# PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
mkdir php-fpm.d; \
cp php-fpm.conf.default php-fpm.d/www.conf; \
{ \
echo '[global]'; \
echo 'include=etc/php-fpm.d/*.conf'; \
} | tee php-fpm.conf; \
fi; \
{ \
echo '[global]'; \
echo 'error_log = /proc/self/fd/2'; \
echo; echo '; https://github.com/docker-library/php/pull/725#issuecomment-443540114'; echo 'log_limit = 8192'; \
echo; \
echo '[www]'; \
echo '; if we send this to /proc/self/fd/1, it never appears'; \
echo 'access.log = /proc/self/fd/2'; \
echo; \
echo 'clear_env = no'; \
echo; \
echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
echo 'catch_workers_output = yes'; \
echo 'decorate_workers_output = no'; \
} | tee php-fpm.d/docker.conf; \
{ \
echo '[global]'; \
echo 'daemonize = no'; \
echo; \
echo '[www]'; \
echo 'listen = 9000'; \
} | tee php-fpm.d/zz-docker.conf
# Override stop signal to stop process gracefully
# https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/sapi/fpm/php-fpm.8.in#L163
STOPSIGNAL SIGQUIT
EXPOSE 9000
CMD ["php-fpm"]
複製代碼
上面的配置文件主要作了幾件事:
將內容保存爲 Dockerfile
後,可使用下面的命令構建咱們所須要的鏡像:
docker build -t soulteary/flarum:v0.1.0-beta.12 -f Dockerfile .
複製代碼
若是是在國內網絡環境編譯,可使用下面的命令,加速編譯構建過程。
docker build --build-arg USE_CHINA_MIRROR=1 -t soulteary/flarum:v0.1.0-beta.12 -f Dockerfile .
複製代碼
準備好運行鏡像後,咱們就能夠準備運行目錄和容器編排配置文件了。
咱們提供給 flarum 使用的目錄結構以下:
├── Dockerfile
├── conf
├── docker-compose.yml
├── logs
├── start.sh
└── wwwroot
複製代碼
將以前準備好的 「CodeBase」 目錄中的如下內容複製到 wwwroot 目錄下:
考慮到後續會安裝/卸載 flarum 插件,這個工做能夠交給啓動腳原本作,至於啓動腳本怎麼編寫,能夠耐心繼續往下看。
由於使用 FPM 模式的 PHP 環境,咱們須要藉助 Apache / Nginx 的幫助來提供 Web 服務,我這裏選擇 Nginx。
使用 Nginx,須要分別配置兩個文件,先配置 conf/docker-nginx.conf
:
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;
# 交給 Traefik 或者 SLB 處理,不開啓 Gzip
#gzip on;
include /etc/nginx/conf.d/*.conf;
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;
}
複製代碼
接着來配置 conf/vhost.conf
文件:
server {
listen 80;
server_name lab.com lab.io;
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 = /get-health {
access_log off;
default_type text/html;
return 200 'alive';
}
# Pass requests that don't refer directly to files in the filesystem to index.php
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;
}
# Gzip 交給 Traefik , 不針對文件類型作壓縮
}
複製代碼
上面配置中的 server_name
須要改成你的目標站點名稱。將兩個配置文件保存好後,咱們繼續處理容器編排文件,完整的內容以下:
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
- ./conf/vhost.conf:/etc/nginx/conf.d/vhost.conf
- ./wwwroot:/wwwroot
links:
- php:php
extra_hosts:
- "${DOCKER_DOMAIN_NAME}:127.0.0.1"
networks:
- traefik
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik"
- "traefik.http.routers.www-flarum.middlewares=https-redirect@file"
- "traefik.http.routers.www-flarum.entrypoints=http"
- "traefik.http.routers.www-flarum.rule=Host(`$DOCKER_DOMAIN_NAME`)"
- "traefik.http.routers.ssl-flarum.middlewares=content-compress@file"
- "traefik.http.routers.ssl-flarum.entrypoints=https"
- "traefik.http.routers.ssl-flarum.tls=true"
- "traefik.http.routers.ssl-flarum.rule=Host(`$DOCKER_DOMAIN_NAME`)"
- "traefik.http.services.ngx-flarum-backend.loadbalancer.server.scheme=http"
- "traefik.http.services.ngx-flarum-backend.loadbalancer.server.port=80"
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: "10m"
php:
image: ${DOCKER_PHP_IMAGE}
restart: always
expose:
- 9000
env_file: .env
volumes:
- ./logs:/var/log
- ./wwwroot:/wwwroot
networks:
- traefik
healthcheck:
test: ["CMD-SHELL", "pidof php-fpm"]
interval: 5s
retries: 12
logging:
driver: "json-file"
options:
max-size: "10m"
networks:
traefik:
external: true
複製代碼
與之對應的 .env
配置內容:
DOCKER_PHP_IMAGE=soulteary/flarum:v0.1.0-beta.12
DOCKER_NGINX_IMAGE=nginx:1.17.1-alpine
DOCKER_DOMAIN_NAME=lab.com
FLARUM_DB_HOST=flarum-db.lab.com
FLARUM_DB_NAME=flarum
FLARUM_DB_USER=flarum
FLARUM_DB_PASS=flarum
FLARUM_REDIS_HOST=flarum-redis.lab.com
FLARUM_REDIS_PORT=6379
FLARUM_REDIS_PASS=
FLARUM_REDIS_DBNO=0
FLARUM_REDIS_CONNECTION_PARAMETERS=
FLARUM_REDIS_CLIENT_OPTIONS=
FLARUM_REDIS_PREFIX=session:
FLARUM_REDIS_LOCKING=1
FLARUM_REDIS_SPIN_LOCK_WAIT=150000
FLARUM_REDIS_HANDLER_OPTIONS=
FLARUM_REDIS_TTS=3600
FLARUM_APP_DEBUG=true
FLARUM_APP_URL=//lab.com
複製代碼
一樣使用 docker-compose up -d
啓動服務,而後就能看到久違的安裝界面了。
參考上圖和上面的 .env
配置,就可以完成 flarum 的安裝了。
默認安裝完畢以後,會在 wwwroot/config.php
路徑生成配置文件:
<?php return array (
'debug' => false,
'database' =>
array (
'driver' => 'mysql',
'host' => 'flarum-db.lab.com',
'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://lab.com',
'paths' =>
array (
'api' => 'api',
'admin' => 'admin',
),
);
複製代碼
爲了更好的進行動態配置和代碼集中管理,這裏可使用環境變量替換掉 hard code 的內容。
<?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,
'engine' => 'InnoDB',
'prefix_indexes' => true,
),
'url' => $_SERVER['FLARUM_APP_URL'],
'paths' =>
array (
'api' => 'api',
'admin' => 'admin',
),
);
複製代碼
完成 config.php 文件的修改後,即可以將文件一樣提交至代碼倉庫,進行保存管理。
另外,由於程序最初設計未考慮到容器環境,因此對於運行目錄並無單獨進行設計,致使簡單封裝後,須要對目錄進行權限調整;以及初次安裝完畢後,從遠端下載的前端資源文件,若是清理緩存後會致使界面不正常;以及前文提到的反覆更新軟件相關插件...
因此咱們須要準備一個啓動腳本:start.sh
#!/usr/bin/env bash
# 關閉服務
echo "嘗試中止以前啓動的服務"
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 "獲取基礎鏡像"
docker pull $image
fi
done
# 清理以前存在的歷史文件,並將新文件同步到執行目錄中
if [ -d "wwwroot/vendor" ]; then
echo "清理已經存在的 Vendor 文件"
rm -rf wwwroot/vendor
fi
if [ -d "../codebase" ]; then
echo "同步 Vendor 文件"
cp -r ../codebase/vendor/ wwwroot/
fi
echo '備份前端資源'
cp -r wwwroot/public/assets/* ./backup-assets
mkdir -p ./backup-assets
# 清理 & 重建目錄
echo '清理緩存目錄'
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 '還原前端資源'
rm -rf ./wwwroot/public/assets
mkdir -p ./wwwroot/public/assets
cp -r ./backup-assets/* ./wwwroot/public/assets/
# 重啓服務
echo '重啓服務'
docker-compose up -d
# 修正文件權限
docker ps -q -f status=running -f name=_php_1 | while read container ; do
echo "修正容器 $container 權限"
docker exec $container chown -R www-data:www-data /wwwroot
docker exec $container chmod -R 755 /wwwroot/storage
docker exec $container chmod -R 755 /wwwroot/public/assets
done
複製代碼
其實更好的方案是使用 ELK 插件去作全文檢索,可是其實使用 MySQL 開啓全文檢索,對於訪問量不大的站點影響不大。
尤爲是在幾乎不須要付出額外的成本,使用的機器資源也相對較低的前提下。
隨手寫一個 PHP 腳本,執行下面兩條命令,稍等片刻,flarum 就可以支持中文、日文的索引了。
ALTER TABLE flarum_posts DROP INDEX content;
CREATE FULLTEXT INDEX content ON `flarum_posts` (`content`) WITH PARSER ngram;
ALTER TABLE flarum_discussions DROP INDEX title;
CREATE FULLTEXT INDEX title ON `flarum_discussions` (`title`) WITH PARSER ngram;
複製代碼
爲了提升可維護性,這裏建議對不使用的插件進行卸載,以 flarum/auth-twitter` 和 `flarum/auth-facebook
爲例,在 codebase 目錄執行:
composer remove flarum/auth-twitter flarum/auth-facebook
複製代碼
成功卸載插件,將看到下面的提示。
Dependency "flarum/core" is also a root requirement, but is not explicitly whitelisted. Ignoring.
Dependency "flarum/core" is also a root requirement, but is not explicitly whitelisted. Ignoring.
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 0 installs, 0 updates, 4 removals
- Removing league/oauth2-facebook (2.0.1)
- Removing league/oauth1-client (1.7.0)
- Removing flarum/auth-twitter (v0.1.0-beta.12)
- Removing flarum/auth-facebook (v0.1.0-beta.12)
Writing lock file
Generating autoload files
複製代碼
完成以後,記得從新執行上面的啓動腳本,將程序源碼作一次新的同步。
有一位網友(@csineneo)作的中文語言包,質量相對比較不錯,和上面卸載無用插件相似,使用 composer 進行安裝:
composer require csineneo/lang-simplified-chinese
複製代碼
安裝完畢以後,將看到相似日誌。
Using version ^1.12 for csineneo/lang-simplified-chinese
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing csineneo/lang-simplified-chinese (1.12.4): Downloading (100%)
Writing lock file
Generating autoload files
複製代碼
一樣的,須要在再次執行啓動腳本,同步更新過的代碼到flarum運行目錄。
除了搭建 Flarum 主體外,完成持續集成的環境也很重要,能夠考慮使用以前這篇文章中的方案一個 Git Server,配置自動部署。
或許將來我會聊聊在十個月前,咱們是如何對 Flarum 進行調整,使它適合用於多機環境的,以及如何打通微信掃碼登陸、如何使用更靠譜的附件上傳...
至於何時寫,或許得等到再有羣友提問,能激發起個人興趣的時候吧,:)
--EOF
我如今有一個小小的折騰羣,裏面彙集了一些喜歡折騰的小夥伴。
在不發廣告的狀況下,咱們在裏面會一塊兒聊聊軟件、HomeLab、編程上的一些問題,也會在羣裏不按期的分享一些技術沙龍的資料。
喜歡折騰的小夥伴歡迎掃碼添加好友。(請註明來源和目的,不然不會經過審覈)