分享如何将自定义容器镜像切换到 Bitnami 容器镜像,以及如何搭配反向代理软件(如 Traefik)配置使用。
写在前面
去年曾分享过一篇关于 Phabricator 的内容,《使用 Docker 和 Traefik v2 搭建 Phabricator》,当时介绍了如何构建自定义的容器镜像,以及如何搭配汉化补丁使用应用。
时隔一年,伴随着软硬件升级,Phabricator 的服务迁移也被提上了日程。
考虑到尽可能省心的长期使用,我选择将镜像切换至了 Bitnami 的镜像,这样可以使用到每小时都由 GitHub 构建的透明可信的镜像,以及更少的操心各种安全补丁和升级的事情。
梳理问题
Bitnami 的镜像提供非常多的环境变量配置,用来应对各种场景。然而针对以下两个场景的支持缺不够完善:
- 使用已有数据库运行软件,而非从零到一进行初始化。
- 使用反向代理服务,而非直接提供服务。
收集线索
浏览仓库代码中的 Dockerfile ,可以看到项目启动前的入口脚本和预执行脚本各有一个文件:
ENTRYPOINT [ "/opt/bitnami/scripts/phabricator/entrypoint.sh" ]
CMD [ "/opt/bitnami/scripts/phabricator/run.sh" ]
复制代码
观察 entrypoint.sh 脚本,可以看到这个脚本调用了 Web 服务器、数据库、以及应用初始化相关的脚本。
#!/bin/bash
# shellcheck disable=SC1091
set -o errexit
set -o nounset
set -o pipefail
# set -o xtrace # Uncomment this line for debugging purpose
# Load Phabricator environment
. /opt/bitnami/scripts/phabricator-env.sh
# Load libraries
. /opt/bitnami/scripts/libbitnami.sh
. /opt/bitnami/scripts/liblog.sh
. /opt/bitnami/scripts/libwebserver.sh
print_welcome_page
if [[ "$1" = "/opt/bitnami/scripts/phabricator/run.sh" || "$1" = "/opt/bitnami/scripts/$(web_server_type)/run.sh" || "$1" = "/opt/bitnami/scripts/nginx-php-fpm/run.sh" ]]; then
info "** Starting Phabricator setup **"
/opt/bitnami/scripts/"$(web_server_type)"/setup.sh
/opt/bitnami/scripts/php/setup.sh
/opt/bitnami/scripts/mysql-client/setup.sh
/opt/bitnami/scripts/phabricator/setup.sh
/post-init.sh
info "** Phabricator setup finished! **"
fi
echo ""
exec "$@"
复制代码
其中有一个脚本路径 /opt/bitnami/scripts/phabricator/setup.sh 比较可疑,对这个脚本进行 phabricator/setup.sh 翻阅,可以看到除了一些检查环境就绪与否的准备工作外,还可以找到两个基础依赖:
...
# Load libraries
. /opt/bitnami/scripts/libphabricator.sh
. /opt/bitnami/scripts/libwebserver.sh
...
复制代码
继续翻阅 /opt/bitnami/scripts/libphabricator.sh 这个脚本,会看到这个脚本真正定义了 phabricator 所有的应用配置,有一部分和容器环境变量(包含未被文档说明的),也和这个脚本进行了绑定,所以从这里入手进行修改,再合适不过了。
调整脚本:添加时区设置
如果想让 phabricator 时间展示正确,需要进行时区设置,我们找到 phabricator_initialize 函数,在其中添加对 phabricator.timezone 的设置:
########################
# Ensure Phabricator is initialized
# Globals:
# PHABRICATOR_*
# Arguments:
# None
# Returns:
# None
#########################
phabricator_initialize() {
# Check if Phabricator has already been initialized and persisted in a previous run
local -r app_name="phabricator"
local -r port="${WEB_SERVER_HTTP_PORT_NUMBER:-"$WEB_SERVER_DEFAULT_HTTP_PORT_NUMBER"}"
if ! is_app_initialized "$app_name"; then
info "Creating Phabricator configuration file"
# Modified by @soulteary
phabricator_conf_set "phabricator.timezone" "Asia/Shanghai"
复制代码
调整脚本:更新数据库命名空间
找到 phabricator_configure_database_credentials 函数,对 storage.default-namespace 配置项目进行更新,如果你没有设置过,需要将这个项目删除或注释掉,避免应用启动之后找不到之前的数据:
#########################
# Configure Phabricator database
# Globals:
# PHABRICATOR_*
# Arguments:
# $1 - database user name
# $2 - database user password
# Returns:
# None
#########################
phabricator_configure_database_credentials() {
local -r db_user="${1:?missing database user}"
local -r db_pass="${2:?missing database password}"
info "Configuring database"
phabricator_conf_set "mysql.host" "$PHABRICATOR_DATABASE_HOST"
phabricator_conf_set "mysql.port" "$PHABRICATOR_DATABASE_PORT_NUMBER"
phabricator_conf_set "mysql.user" "$db_user"
phabricator_conf_set "mysql.pass" "$db_pass"
# Modified by @soulteary
# phabricator_conf_set "storage.default-namespace" "bitnami_phabricator"
phabricator_conf_set "storage.mysql-engine.max-size" "0"
}
复制代码
调整编排文件:设置数据库
因为我们要直接使用老数据库,所以这里不能让脚本运行“数据库初始化”那一套流程,需要针对编排文件进行环境变量设置,让脚本认为数据库结构已就绪,不需要进行初始化,并且使用已有的数据库配置提供服务:
...
environment:
...
# 需要和 PHABRICATOR_SKIP_BOOTSTRAP 一起使用,否则还需要设置更多的冗余内容
- ALLOW_EMPTY_PASSWORD=yes
- PHABRICATOR_SKIP_BOOTSTRAP=yes
- PHABRICATOR_DATABASE_HOST=database
- PHABRICATOR_DATABASE_PORT_NUMBER=3306
- PHABRICATOR_EXISTING_DATABASE_USER=root
- PHABRICATOR_EXISTING_DATABASE_PASSWORD=QV8}!P![&QmR
...
复制代码
调整脚本:调整应用链接以支持反向代理
为了能够支持反向代理环境,尤其是支持由反向代理网关提供“HTTPS”协议访问的能力,我们需要修改 phabricator_configure_host 和 phabricator_configure_alternate_file_domain 函数,让应用能够在运行在非 HTTPS 状况下,将页面链接渲染为 https:// 协议。
#########################
# Configure Phabricator host
# Globals:
# PHABRICATOR_*
# Arguments:
# None
# Returns:
# None
#########################
phabricator_configure_host() {
local host
local scheme
get_hostname() {
if [[ -n "${PHABRICATOR_HOST:-}" ]]; then
echo "$PHABRICATOR_HOST"
else
dns_lookup "$(hostname)" "v4"
fi
}
host="$(get_hostname)"
if is_boolean_yes "$PHABRICATOR_ENABLE_HTTPS"; then
scheme="https"
[[ "$PHABRICATOR_EXTERNAL_HTTPS_PORT_NUMBER" != "443" ]] && host+=":${PHABRICATOR_EXTERNAL_HTTPS_PORT_NUMBER}"
else
scheme="http"
[[ "$PHABRICATOR_EXTERNAL_HTTP_PORT_NUMBER" != "80" ]] && host+=":${PHABRICATOR_EXTERNAL_HTTP_PORT_NUMBER}"
fi
info "Configuring Phabricator URL to ${scheme}://${host}"
# Modified by @soulteary
scheme="https"
phabricator_conf_set "phabricator.base-uri" "${scheme}://${host}"
}
#########################
# Configure Phabricator alternate file domain
# Globals:
# PHABRICATOR_*
# Arguments:
# None
# Returns:
# None
#########################
phabricator_configure_alternate_file_domain() {
local afd="$PHABRICATOR_ALTERNATE_FILE_DOMAIN"
local scheme
if is_boolean_yes "$PHABRICATOR_ENABLE_HTTPS"; then
scheme="https"
[[ "$PHABRICATOR_EXTERNAL_HTTPS_PORT_NUMBER" != "443" ]] && afd+=":${PHABRICATOR_EXTERNAL_HTTPS_PORT_NUMBER}"
else
scheme="http"
[[ "$PHABRICATOR_EXTERNAL_HTTP_PORT_NUMBER" != "80" ]] && afd+=":${PHABRICATOR_EXTERNAL_HTTP_PORT_NUMBER}"
fi
# Modified by @soulteary
scheme="https"
info "Configuring Phabricator Alternate File Domain to ${scheme}://${afd}"
phabricator_conf_set "security.alternate-file-domain" "${scheme}://${afd}"
}
复制代码
编排文件对应的配置也需要声明:
...
environment:
...
- PHABRICATOR_ENABLE_HTTPS=false
- PHABRICATOR_HOST=board.lab.com
- PHABRICATOR_ALTERNATE_FILE_DOMAIN=board-file.lab.com
...
复制代码
完整的容器编排配置
将上面提到的内容更新到 libphabricator.sh 中,然后编写容器编排配置文件:
version: '3.7'
services:
phabricator:
image: bitnami/phabricator:2021.13.0
expose:
- 8080
environment:
- APACHE_HTTP_PORT_NUMBER=8080
- PHABRICATOR_ENABLE_HTTPS=false
- PHABRICATOR_HOST=board.lab.com
- PHABRICATOR_ALTERNATE_FILE_DOMAIN=board-file.lab.com
- ALLOW_EMPTY_PASSWORD=yes
- PHABRICATOR_SKIP_BOOTSTRAP=yes
- PHABRICATOR_DATABASE_HOST=board.data.lab.com
- PHABRICATOR_DATABASE_PORT_NUMBER=3306
- PHABRICATOR_EXISTING_DATABASE_USER=root
- PHABRICATOR_EXISTING_DATABASE_PASSWORD=QV8}!P























![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)