专栏名称: 狗厂
目录
相关文章推荐
51好读  ›  专栏  ›  狗厂

为多个PHP-FPM容器量身打造单一Nginx镜像

狗厂  · 掘金  ·  · 2018-06-14 10:08

正文

最近我一直在努力部署一套使用Docker容器的PHP微服务。其中一个问题是我们的PHP应用程序被设置为与PHP-FPM和Nginx一起工作(而不是这里所说的简单的Apache/PHP[1]设置),因此每个PHP微服务需要两个容器(也就是相当于两个Docker镜像):
  • PHP-FPM容器

  • Nginx容器

假设一个应用运行超过六个PHP微服务,算上你的dev和prod环境,那么最终差不多会产生接近30个容器。我决定构建一个单独的Nginx Docker镜像,将PHP-FPM主机名作为环境变量映射到这个镜像里面独特的配置文件中,而不是为每个PHP-FPM微服务的镜像构建独特的Nginx镜像。

在这篇博客文章中,我将概述我从上述方法1到方法2的过程,最后用介绍如何使用新定制Nginx Docker镜像的解决方案来结束这篇博客。
我已经将这个镜像开源GitHub[2],所以如果这刚好是您经常遇到的问题,请随时查看。

为什么是Nginx?

PHP-FPM和Nginx一起使用可以产生更好的PHP应用程序性能[3],但缺点是PHP-FPM Docker镜像默认没有像PHP Apache镜像那样与Nginx捆绑在一起。
如果您想将Nginx容器连接到PHP-FPM后端,则需要将该后端的DNS记录添加到您的Nginx配置中。
例如,如果PHP-FPM容器作为名为php-fpm-api的容器运行,那么您的Nginx配置文件应该这样写:
nginx    location ~ \.php$ {        fastcgi_split_path_info ^(.+\.php)(/.+)$;        # This line passes requests through to the PHP-FPM container        fastcgi_pass php-fpm-api:9000;        fastcgi_index index.php;        include fastcgi_params;        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;        fastcgi_param PATH_INFO $fastcgi_path_info;    }
如果你只服务一个PHP-FPM容器应用,在你的Nginx容器的配置文件中硬编码对应的名字是可以的。但是,如我上面提到的,每个PHP服务都需要一个对应的Nginx容器,我们就需要运行多个Nginx容器。创建一个新的Nginx镜像(我们后面必须维护和升级)将是一件痛苦的事情,因为即使管理一堆不同的卷,对于更改单个变量名称似乎也有很多工作要做。

第一个解决方案:使用Docker文档里提到的方法envsubst

起初,我认为这很容易。在Docker文档中关于如何使用envsubst有一个很好的小章节[4],但不幸的是,这不适用于我的Nginx配置文件:
vhost.conf
nginxserver {    listen 80;    index index.php index.html;    root /var/www/public;    client_max_body_size 32M;    location / {        try_files $uri /index.php?$args;    }    location ~ \.php$ {        fastcgi_split_path_info ^(.+\.php)(/.+)$;        fastcgi_pass ${NGINX_HOST}:9000;        fastcgi_index index.php;        include fastcgi_params;        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;        fastcgi_param PATH_INFO $fastcgi_path_info;    }}
我的vhost.conf文件用到了好几个Nginx内置的环境变量,结果当我运行Docker文档里提到的如下命令行时,提示错误:$uri和fastcgi_script_name未定义。
shell/bin/bash -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
这些变量通常由Nginx本身传入[5],所以不容易搞清楚他们是什么和怎么进行参数传递的,而且这会影响容器的动态可配置性。

另一个差点成功的Docker镜像

接下来,我开始搜索不同的Nginx的基础镜像。找到了两个,但是这两个都是两年没有更新了。我从martin/nginx[6]开始,尝试看看能不能得到一个可以工作的原型。
Martin的镜像有点不太一样,因为它要求特定的文件目录结构。我先在Dockerfile中添加了:
FROM martin/nginx






请到「今天看啥」查看全文