ecnelises Bonvenon al la malpura mondo

把服务器迁移回Debian和Docker

去年,运行这个网站和Mastodon实例的服务器是一台Debian 9,后来跳级升级到Debian 11后,遇到一些零散的版本不兼容问题。年初,因为自己在折腾ZFS的NAS,所以我也将服务器迁移到了FreeBSD. 老实说FreeBSD在很多方面比起Linux更「原汁原味」,比如严格区分第三方软件的/usr/local/etc和系统/etc目录;而且没有systemd,采用的更传统风格的rc.d启动脚本。

如果你的服务器也是FreeBSD系统,且也想在其上运行Mastodon实例的话,分享一下我的Mastodon实例启动脚本,放在/usr/local/etc/rc.d目录下,然后在rc.conf文件启用即可。注意ruby和node需要通过rbenv和nodenv等工具自行安装。

再次切换回Linux的起因是,我尝试升级PostgreSQL到14版本,但包管理器提示PostgreSQL 14和PHP PostgreSQL驱动相互冲突,会导致PHP数据库驱动被卸载。更新系统,以及将PHP升级到8.2后依然存在该问题。再者,自从迁移至FreeBSD后,各项服务的响应速度一直不如Linux快,总是要慢一截。我当然不愿相信是FreeBSD性能真的不如Linux,但一时也没找到确切原因,甚至让我对ZFS留下了一些不好的印象。加之FreeBSD在服务器提供商那里没有现成的监控工具,不支持Swift语言等原因,我最终决定迁移回Debian系统,并且尝试以全Docker方式部署服务。

在此之前我对Docker并没有那么多经验,只在大学某些课程项目和工作时需要的测试环境里短暂尝试过。甚至一度因为macOS运行Docker需要虚拟机,忘记了原因是依赖Linux内核功能,而习惯性认为Linux服务器上也需要一层虚拟化运行Docker造成性能损失。所以一直没有在自己的服务器上尝试使用Docker环境。由于服务规模没有那么大,就不折腾Kubernetes或Swarm这些东西了,直接用Docker Compose就好。

我自己修改过的docker-compose.yml文件就不完整贴在这里了,需要的朋友可以基于Mastodon的这个参考文件编写。需要注意的几点:

  • 参考文件里的数据卷(Volume)映射用的是相对路径,如果你有很多个服务,可能不会想在clone下来的mastodon源码目录里运行其他所有服务,所以要修改一下路径,或者干脆改成绝对路径
  • 从Docker Hub拉下来的tootsuite/mastodon:latest镜像已经是构建完成的了,所以请把build: .注释掉
  • 如果一个服务只有internal_network,那么不光它无法接受外部请求,也不能向外界发出任何网络请求。所以如果有服务需要向外面抓取信息,请加入external_network
  • Docker Compose的内部网络里通信的服务之间,主机名将不再是localhost,请留意docker-compose up时输出的实例名,通常来说是「启动服务时所在目录_服务名_1
  • 如果你使用Let’s Encrypt,特别是从一个已有Let’s Encrypt目录的服务器迁移过来,请记得,(/usr/local)/etc/letsencrypt/live中的证书不是真实文件,而是指向../../archive目录的符号链接!单纯映射live目录会导致Docker环境无法找到证书
  • 如果你不是用root用户管理一切,那么Docker内部的PHP可能没有修改映射目录内容的权限,导致WordPress能PHP服务无法自更新,请chown一下

另外,默认的PHP镜像并没有安装很多常用的数据库扩展,我们需要写一个自己的Dockerfile,放在某个目录里,然后在docker-compose.yml中PHP服务一项指定build:值。Dockerfile参考:

FROM php:8-fpm-bullseye

RUN apt-get update

RUN apt-get install -y libpq-dev libzip-dev libicu-dev libpng-dev \
    && docker-php-ext-install mysqli \
    && docker-php-ext-configure pgsql --with-pgsql=/usr/local/pgsql \
    && docker-php-ext-install pdo pdo_pgsql pgsql zip exif gd intl

如果有什么Cronjob需要利用Docker内部环境执行也很简单,使用docker exec CONTAINER_NAME COMMAND即可,注意如果是给cronjob执行,不要加-it选项,否则会有invalid tty错误;如果是终端里手动执行,需要加上。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注