老朱

万物之始,大道至简

  • 32
  • 文章数
  • 5
  • 分类数
  • 29
  • 评论数

万物之始,大道至简

老朱

  • 32
  • 文章数
  • 5
  • 分类数
  • 29
  • 评论数
2024/04/14

「  优雅的在一台服务器上部署多个 Typecho 网站  」

前言

前面我们基于joyqi/typecho:nightly-php7.4-apache镜像已经很快速地部署了一个Typecho博客网站,后来又通过自己开发的主题,搭建了一个导航网站。如果一台服务器上只是部署一两个网站,那么这样操作是完全可行的,毕竟省心且维护方便,但如果需要部署更多的网站,服务器资源可能就严重浪费了,架构上就会出现如下图所示的效果。
老方案
这里至少存在以下三个问题:

  1. 每个typecho网站都启动了一个包含Apachephp-fpm进程的容器,造成资源严重浪费;
  2. 如果后续还有其它的php网站,那么还需要再部署更多的php-fpm环境;
  3. Nginx Proxy Manager本身就是Nginx服务器,可以直接托管php网站,完全没有反向代理到Apache的必要。

事实上,typecho也只是一个很普通的php网站而已,不应该特殊对待。基于浪费可耻的原则,我真正希望的部署架构应该是这样的:
新方案

  • Nginx Proxy Manager既充当反向代理服务器,又充当普通的 Web 服务器,也就是说 Web 服务器全局只保留一个即可;
  • 同理,php-fpm也只需部署一次,实现所有php网站全局共享;
  • 不同网站的文件存储在主机的独立目录,通过Nginx的虚拟主机方式托管。

不难看出,这里其实就是部署了一个普通的php运行环境。托管多个网站时,这种架构需要更少的资源,部署新的网站也只需要在Nginx Proxy Manager中添加新的虚拟主机配置即可,容器的数量不会增加,在访问量超载之前,再多的网站也不会带来多少额外的服务器开销,非常方便。

1. 容器部署

为了实现这个架构,让服务器资源达到最大程度的复用,我们需要分别部署Nginx Proxy Managerphp-fpm两个容器,我这里直接通过编写Dockerfiledocker-compose.yml文件一次性部署。

1.1 编写 Dockerfile

由于typecho需要依赖pdo_mysql扩展,而php默认并没有启用,因此我们需要编写一个Dockerfile,用于构建自定义的镜像。

FROM php:8.2-fpm

RUN docker-php-ext-install pdo_mysql

文件内容很简单,只是在官方镜像的基础上安装了pdo_mysql扩展。另外,我这里镜像选择的是较新8.2版本,事实上目前最常用的还是7.4,大家可以根据自己的需要选择合适的版本。

1.2 编写 docker-compose.yml

接下来,我们编写docker-compose.yml,具体如下:

version: "3.8"
services:
  npm:
    image: "jc21/nginx-proxy-manager:latest"
    container_name: "nginx-proxy-manager"
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "81:81"
    volumes:
      - /data/nginx_proxy_manager/data:/data
      - /data/nginx_proxy_manager/letsencrypt:/etc/letsencrypt
      - www_data:/var/www/html
    depends_on:
      - php-fpm
    networks:
      - ilaozhu_net

  php-fpm:
    build:
      context: .
      dockerfile: Dockerfile
    image: "php-fpm:8.2"
    container_name: "php-fpm"
    restart: unless-stopped
    expose:
      - 9000
    volumes:
      - www_data:/var/www/html
    networks:
      - ilaozhu_net
volumes:
  www_data:
    name: www_data

networks:
  ilaozhu_net:
    driver: bridge
    name: ilaozhu_net
    external: true # 使用已存在的网络,如果不存在,则会报错

注意,

  • Nginx Proxy Managerphp-fpm需要挂载到同一个数据卷,并且属于同一网络;
  • Dockerfile要和docker-compose.yml放在同一目录。

最后,执行docker compose up -d就可以了。

2. 迁移 typecho 网站

环境部署好了之后,就要把之前的网站迁移到新的环境中来了。

2.1 迁移网站源文件

/var/lib/docker/volumes/www_data/_data下,用网站域名作为名称创建目录,然后将typecho网站的源文件解压到对应的目录中,可用tree命令查看详细的目录结构,如下图所示:
项目目录

小插曲:
我下载 https://github.com/typecho/typecho中的Release v1.2.1版运行报错,所以直接先部署joyqi/typecho:nightly-php8.2-fpm镜像,然后从中拷出源码解决的。

2.2 修改虚拟主机配置

经过前面的步骤,我们已经把php网站的运行环境部署起来了,并且也把网站的源文件拷贝到了相应的位置,接下来,我们只需要到Nginx Proxy Manager管理后台修改站点的虚拟主机配置即可(Nginx Proxy Manager的详细用法可以参看一款简单易用的反向代理神器),下面以ilaozhu.com为例简要说明,具体修改如下图所示:
修改虚拟主机配置
虚拟主机高级配置

这里的重点是需要在高级选项卡中添加如下配置,使之能够支持fastcgi,从而让php-fpm能够正常工作。

root /var/www/html/ilaozhu.com;
index index.php;
location / {
    try_files $uri $uri/ /index.php?$query_string;
    gzip_static on;
}
location ~ \.php(.*)$ {
    fastcgi_pass   php-fpm:9000;
    fastcgi_index  index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

通常情况下,不同的php网站只需要更换root配置即可。当然,配置修改完成后,别忘了重启Nginx Proxy Manager容器,不出意外的话,接下来就可以访问到你的网站了。
老朱博客

3. 权限问题

在访问typecho网站,进行初始化设置的时候,可能会出现如下两种权限问题。
权限问题
权限问题
这些问题都是由于typecho网站的目录无法写入导致的,如果没有强迫症的话,最简单的做法就是整个网站授予写入权限。

chmod -R o+w /var/lib/docker/volumes/www_data/_data/ilaozhu.com

但这么做授权范围明显有点大了,但如果仅对uploads目录授权,范围又太小,因为我们有可能会通过管理后台修改主题源代码,因此,我这里对usr目录授权。

chmod -R o+w /var/lib/docker/volumes/www_data/_data/ilaozhu.com/usr

然后,根据最后一幅图的提示手动创建config.inc.php文件即可。

最安全的方法应该是直接在 Dockerfile 中通过命令创建用户并授权,但目前还不知道如何实现,所以暂时就先这样了,问题也不大,如果你有好的方法,欢迎留言。

结语

好了,到这里,Typecho 的优化部署就完成了。可以这么说,在服务器访问量不超负荷的前提下,如果说先前的部署方式,一台服务器运行三五个网站就会卡顿的话,那么现在三五十个也不在话下。

评论

    在dockerfile中`RUN chmod -R `应该可以吧

    2024年04月15日 08:49