如何为多个PHP-FPM容器构建单一的Nginx Docker镜像教程-linux运维教程

  • 为什么用 Nginx?
  • 第一种方案: 使用 Docker 文档中的方法
  • 使用另一个 Docker 镜像,差点成功
  • 最终解决方案

在使用 Docker 容器来开发 PHP 微服务套件的过程中,作者遇到了容器数量过多的问题。

最近,我一直在使用 Docker 容器来开发 PHP 微服务套件。一个问题是 PHP 应用已经搭建,可以与 PHP-FPM 还有 Nginx(取代了简单的 Apche/PHP 环境)一起工作,因此每个 PHP 微服务需要两个容器(以及两个 Docker 镜像):一个 PHP-FPM 容器和一个 Nginx 容器。
这个应用运行了 6 个以上的服务,做个乘法就知道,在开发和生产之间会有约 30 个容器。于是我决定构建一个单独的 Nginx Docker 镜像,它可以使用 PHP-FPM 的主机名作为环境变量并运行单独的配置文件,而不用为每个容器构建单独的 Nginx 镜像。

如何为多个PHP-FPM容器构建单一的Nginx Docker镜像教程-linux运维教程

在本文中,我介绍了自己从上图中的方法 1 到方法 2 的转换,最后采用的方案中采用了一种新的定制 Docker 镜像。该镜像的代码是开源的,如果读者碰到类似问题,可以提供给大家参考。

为什么用 Nginx?

Nginx 和 PHP-FPM 配合使用能使 PHP 应用的性能更好,但不好的地方在于,和 PHP Apache 镜像不同,PHP-FPM Docker 镜像默认不是和和 Nginx 绑定在一起的。如果需要通过 Nginx 容器和 PHP-FPM 连接,需要在 Nginx 配置里为该后端增加 DNS 记录。比如,如果名为 php-fpm-api 的 PHP-FPM 容器正在运行,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;
    }

如果只服务于单独的 Nginx 容器,Nginx 配置中容器名字写死还可以接受,但如上所述,需要允许多个 Nginx 容器,每个对应于一个 PHP 服务。创建一个新的 Nginx 镜像(以后需要进行维护和升级)会有些痛苦,即使管理一批不同的数据卷,仅仅改变变量名看起来也有很多工作。

第一种方案: 使用 Docker 文档中的方法

最初,我认为这会很简单。Docker 文档中有少许的几个章节讨论如何使用 envsubst 来完成该工作,但不幸的是,在我的 Nginx 配置文件中,这种方法不奏效。

vhosts.conf

server {
    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;
    }
}

该vhosts.conf文件使用了 Nginx 内置变量,因此当依照文档运行 Docker 命令 (/bin/bash -c “envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g ‘daemon off;’”) 时,得到错误提示$uri和$fastcgi_script_name没有定义。这些变量通常通过 Nginx 传入,因此不能简单的识别出他们是什么并传给自身,而且这样会影响容器的动态配置。

使用另一个 Docker 镜像,差点成功

接下来,我开始研究不同的 Nginx 镜像。找到的有两个,但它们都在随后的几年中都没有任何更新。我开始使用 martin/nginx,试图找到可以工作的原型。

Martin 的镜像和其它镜像有点不一样,因为它要求特定的文件夹结构。在 root 下增加Dockerfile:

FROM martin/nginx

接下来,我添加了一个app/空目录和conf/目录,conf/目录下只有一个文件
vhosts.conf:

server {
    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 $ENV{"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;
    }
}

这个文件和之前的配置文件几乎一样,除了有一行的改动:
fastcgi_pass $ENV{“NGINX_HOST”}:9000;。现在想要启动带命名为 php-fpm-api 的 PHP 容器的 Nginx 容器,就可以构建一个新的镜像,让它在以下环境变量下运行:

docker build -t shiphp/nginx-env:test .
docker run -it --rm -e NGINX_HOST=php-fpm-api shiphp/nginx-env:test

它可以正常工作了。但是,这种方法有两个困扰的地方:
正在使用的基础镜像已经有两年了。这会引入安全和性能风险。
有个空的/app目录看起来并不必需,因为文件会被存储在一个不同的目录中。

最终解决方案

我认为作为定制解决方案,从 Martin 镜像开始比较好,因此我给项目建了分叉,创建了新的 Nginx 基础镜像并修复了上述两个问题。现在,如果要在 Nginx 容器中允许动态命名的后端,可以参照:

# 从 Docker Hub 得到最新版本
docker pull shiphp/nginx-env:latest
# 运行名为"php-fpm-api"的 PHP 容器 
docker run --name php-fpm-api -v $(pwd):/var/www php:fpm
# 允许链接到 PHP-FPM 容器的 NGinx 容器
docker run --link php-fpm-api -e NGINX_HOST=php-fpm-api shiphp/nginx-env

如果想增加自己的文件或 Nginx 配置文件,来定制镜像,用Dockerfile来扩展它就可以:

FROM shiphp/nginx-env
ONBUILD ADD <PATH_TO_YOUR_CONFIGS> /etc/nginx/conf.d/
...

现在所有的 PHP-FPM 容器都能使用单个Docker镜像中自己的实例,这样在升级 Nginx,改变权限或做某些调整时,就变得非常轻松了。

所有的代码都在 Github 上,如果你看到任何问题或有改进建议,可以直接创建 issue。

GitHub 项目链接:https://github.com/shiphp/nginx-env

主题测试文章,只做测试使用。发布者:云大使,转转请注明出处:https://www.xp8.net/server/1003.html

(0)
打赏 微信扫一扫 微信扫一扫
云大使的头像云大使
上一篇 2018年10月16日 下午9:19
下一篇 2018年10月16日 下午9:19

相关推荐

  • IIS8/IIS7/IIS6 出现ADODB.Connection 错误 ‘800a0e7a’的解决办法

    刚买了个服务器支持64位的Windows2003于是想爽一下,装IIS6,只能装64位的NET frameWork   在XP32位下用VS2005发布两个网站:[v_tips]基于于SQL2000[/v_tips][v_tips]基于Office Access[/v_tips]在服务器配置完毕后,A站正常运行,很爽。B站报错,意思于法连接到数据库,郁闷很久…

    服务器运维 2018年7月9日
    2.5K00
  • Linux学习二之Java环境安装配置图文教程方法

    这篇文章主要为大家详细介绍了Linux学习第二篇,Java环境安装配置教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 如果您有服务器咨询问题、购买问题、可以联系我们客服 7271895 690624商祺云-阿里代理、景安代理、西部代理 本文教程为大家分享了Java环境安装配置,供大家参考,具体内容如下 jdk版本:jdk-8u131-linux-x6…

    2019年1月4日
    1.7K00
  • 关于Win2008R2服务器配置VPN服务器的图文教程方法-windows教程-学派吧

    这篇文章主要介绍了Win2008 r2服务器配置VPN服务器教程(图文详解),需要的朋友可以参考下 系统环境:WindowsServer2008R2Enterprise(完全安装) 1、配置准备工作1.1、点击“开始”右边的“服务器管理器”1.2、在“服务器管理器”里点击“角色”1.3、在“角色”上点击右键选译“添加角色”,点击“下一步”1.4、在“角色”里…

    服务器运维 2018年12月2日
    2.9K00
  • debian9安装mariadb apache php7-Linux运维-学派吧

    有需要服务器方面的需求和咨询,可以联系博主 QQ 7271895 一、 apt install apache2 二、 apt install php (安装后测试phpinfo) <?php phpinfo(); ?> 三、 apt install mariadb-server 1、安装完 MariaDB 之后,运行 mysql_secure_i…

    服务器运维 2018年9月30日
    2.1K00
  • 学派吧-Linux自动分区工具的示例详细介绍-linux教程

    注意:由于相关操作可能会导致数据丢失。 所以,执行操作之前,请务必确保已经通过快照等手段对数据进行有效备份,或明确相关数据丢失无影响。 普通云磁盘 适用系统:兼容线上所有非 IO 优化实例的普通云盘的 Liunx 版本。 使用方法:以 root 身份执行命令:bash auto_fdisk.sh。 适用场景:一键式检测是否有尚未分区的数据盘,并能对其格式化和…

    服务器运维 2018年12月12日
    2.4K00

发表回复

登录后才能评论
联系我们

联系我们

18838889666

在线咨询: QQ交谈

邮件:xinyun@88.com

工作时间:周一至周五,9:30-18:30,节假日休息

添加微信
添加微信
分享本页
返回顶部
---------官方优惠叠加渠道折扣:通过我们购买腾讯云/阿里云,价格更低,服务更优。更有专业配置指导与服务。微信同步:18838889666----