今天收到了Secure Dragon LLC的邮件,明年OVZ服务器全线涨价:
OpenVZ 128MB plans are increasing to $24.99/year and the new pricing will take effect on the next invoice of 2025.
比locvps的特价香港机都贵了,只好搬到自己服务器上用 Docker 搭建了。
制作 Docker 构建配置
系统选型
- 肯定是 alpine 了。
- 因为 Typecho 1.2.1 对最新的 PHP 8.3 有一点兼容问题,而最新的 apline 3.20 默认安装的是 PHP 8.3,我偷懒直接选择 alpine 3.18 作为基准镜像,这样 apk 命令安装的 PHP 就是 8.1 版了。
环境还原
- 原版的 OVZ 主机是安装了 dropbear,容器内也会装上
- php-fpm 也是少了的
- 安装 typecho 依赖的 php 扩展
AI 生成配置
这年头不会全自己写了,先丢给 GPT,然后自己检查了一般,最终得到下边的Dockerfile
# 使用 Alpine 作为基础镜像
FROM alpine:3.18
# 设置时区为上海
RUN apk add --no-cache tzdata && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone && \
apk del tzdata
# 安装必要的工具和依赖
RUN apk add --no-cache curl unzip dropbear lighttpd php php-ctype php-curl php-dom php-fpm php-iconv php-gd php-json php-openssl php-pdo php-pdo_sqlite php-sqlite3 php-xml php-xmlreader php-phar php-posix php-ftp php-session php-bcmath php-sockets php-mbstring php-tokenizer bc
# 动态获取 php.ini 路径
RUN PHP_INI_PATH=$(ls /etc/php*/php.ini | head -n 1) && \
sed -i "s|;*cgi.fix_pathinfo=.*|cgi.fix_pathinfo=1|i" $PHP_INI_PATH && \
sed -i 's@^;date.timezone.*@date.timezone = Asia/Shanghai@' $PHP_INI_PATH && \
sed -i "s@^memory_limit.*@memory_limit = 12M@" $PHP_INI_PATH && \
PHPFPM_CONF_PATH=$(ls /etc/php*/php-fpm.d/www.conf | head -n 1) && \
sed -i "s@^user = nobody@user = lighttpd@" $PHPFPM_CONF_PATH && \
sed -i "s@^group = nobody@group = lighttpd@" $PHPFPM_CONF_PATH
# 创建 lighttpd 的日志目录
RUN mkdir -p /var/log/lighttpd && \
chown -R lighttpd:lighttpd /var/log/lighttpd
# 设置工作目录
WORKDIR /srv
# 暴露 lighttpd 端口
EXPOSE 80 443
# 暴露 dropbear 端口(使用参数设定)
ARG DROPBEAR_PORT=22
ENV DROPBEAR_PORT=${DROPBEAR_PORT}
EXPOSE ${DROPBEAR_PORT}
# 启动脚本
COPY start.sh /start.sh
RUN chmod +x /start.sh
# 启动 dropbear 和 lighttpd
CMD ["/start.sh"]
以及start.sh
#!/bin/sh
# 检查 /srv/index.php 是否存在
if [ ! -f /srv/index.php ]; then
# 下载并解压最新的 Typecho 版本
curl -L -o typecho.zip $(curl -s https://api.github.com/repos/typecho/typecho/releases/latest | grep 'browser_download_url' | cut -d '"' -f 4)
unzip typecho.zip -d /srv
rm typecho.zip
fi
# 设置权限
chown -R lighttpd:lighttpd /srv
# 检查并创建 /config/dropbear 目录
if [ ! -d /config/dropbear ]; then
mkdir -p /config/dropbear
fi
# 生成 dropbear 主机密钥到 /config/dropbear 目录
if [ ! -f /config/dropbear/dropbear_rsa_host_key ]; then
dropbearkey -t rsa -f /config/dropbear/dropbear_rsa_host_key
fi
if [ ! -f /config/dropbear/dropbear_ecdsa_host_key ]; then
dropbearkey -t ecdsa -f /config/dropbear/dropbear_ecdsa_host_key
fi
if [ ! -f /config/dropbear/dropbear_ed25519_host_key ]; then
dropbearkey -t ed25519 -f /config/dropbear/dropbear_ed25519_host_key
fi
# 检查并创建 /config/lighttpd 目录
if [ ! -d /config/lighttpd ]; then
mkdir -p /config/lighttpd
fi
# 检查 /config/lighttpd/lighttpd.conf 是否存在,如果不存在则复制 /etc/lighttpd 目录下的所有文件到 /config/lighttpd 目录下
if [ ! -f /config/lighttpd/lighttpd.conf ]; then
cp -r /etc/lighttpd/* /config/lighttpd/
fi
# 运行 PHP
/usr/sbin/php-fpm81 -c /etc/php81/php-fpm.conf
# 检查并运行 /srv/boot.sh 如果存在
if [ -f /srv/boot.sh ]; then
chmod +x /srv/boot.sh
/srv/boot.sh & # 在后台运行
fi
# 启动 dropbear,指定密钥文件路径
/usr/sbin/dropbear -E -p ${DROPBEAR_PORT} -r /config/dropbear/dropbear_rsa_host_key -r /config/dropbear/dropbear_ecdsa_host_key -r /config/dropbear/dropbear_ed25519_host_key &
# 启动 lighttpd,指定配置文件路径
/usr/sbin/lighttpd -D -f /config/lighttpd/lighttpd.conf
构建并运行容器
把上边两个文件放在/data/32mb
下,然后进入这个目录执行命令
docker build -t alpine-typecho .
接着是运行容器,这个容器必须限制到32MB内存以及32MB交换分区(SWAP)
docker run -d --memory 32m --memory-swap 64m -p 80:80 -p 443:443 -p 22:22 -v ~/.ssh:/root/.ssh -v /data/32mb/config:/config -v /data/32mb/www:/srv --name typecho-container --restart always alpine-typecho
# -v /data/32mb/config:/config 是映射配置目录
# -v /data/32mb/www:/srv 是映射 typecho 目录
启动容器后会自动安装Typecho到/srv
目录,也就是VPS上的/data/32mb/www
目录,lighttpd的配置文件也会生成到/data/32mb/config/lighttpd/lighttpd.conf
修改配置
直接执行下边的命令启动相关模块
sed -i 's/# include "mod_fastcgi_fpm.conf"/ include "mod_fastcgi_fpm.conf\ninclude "mod_ssl.conf""/g' /data/32mb/config/lighttpd/lighttpd.conf sed -i 's/# "mod_rewrite","/ "mod_rewrite","/g' /data/32mb/config/lighttpd/lighttpd.conf sed -i 's/# "mod_redirect","/ "mod_redirect","/g' /data/32mb/config/lighttpd/lighttpd.conf cat > /data/32mb/config/lighttpd/mod_ssl.conf << EOF server.modules += ("mod_openssl") server.modules += ("mod_setenv") $HTTP["scheme"] == "https" { setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=63072000; includeSubdomains; ") } EOF
- 这里不单独说明 SSL 证书申请了网上都有
新增虚拟主机,修改
/data/32mb/config/lighttpd/lighttpd.conf
,在最后一行之前加入# virtual host $HTTP["host"] =~ "^(www.)?32mb.cc" { server.document-root = "/srv" accesslog.filename = "/config/logs/32mb.cc.log" $HTTP["scheme"] == "http" { # redirect to https, port 443: url.redirect = (".*" => "https://%0$0") } } $SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/config/32mb.cc.pem" $HTTP["host"] =~ "(^|www\.)32mb.cc" { ssl.pemfile = "/config/32mb.cc.pem" # 这是 typecho 的伪静态规则,其他程序自行修改 url.rewrite-if-not-file = ( "^/(admin|usr)/(.*)" => "/$1/$2", "^/(.*)$" => "/index.php/$1" ) } }
然后重启容器访问绑定好的域名就行了
docker restart alpine-typecho
题外话
因为使用Docker跑web服务,无需SSH就能执行命令了,甚至可以关闭dropbear把内存压缩到16M,12M的样子,不过没测过。