A single nginx image tailored to multiple php-fpm containers

Source: Internet
Author: User
Tags docker hub docker run

I've been trying to deploy a PHP micro-service that uses Docker containers recently. One of the problems is that our PHP application is set up to work with PHP-FPM and nginx (not the simple apache/php[1] setting here), so each PHP microservices requires two containers (that is, two Docker images):

    • PHP-FPM container

    • Nginx Container

Assuming that an application runs more than six PHP microservices, counting your dev and prod environments, it will eventually produce nearly 30 containers. I decided to build a separate nginx docker image, mapping the PHP-FPM hostname as an environment variable into a unique configuration file within the image, rather than building a unique nginx image for each PHP-FPM micro-service mirror.

In this blog post, I'll summarize my process from Method 1 to Method 2, and end this blog with a solution that describes how to use the new custom Nginx docker image.
I already have this image open source github[2], so if this happens to be a problem you often encounter, please feel free to check it.

Why is Nginx?

PHP-FPM with Nginx can produce better PHP application performance [3], but the downside is that the php-fpm Docker image is not bundled with Nginx as the PHP Apache image by default.
If you want to connect the Nginx container to the PHP-FPM backend, you will need to add the DNS records for that backend to your nginx configuration.
For example, if the PHP-FPM container is running as a container named Php-fpm-api, your nginx configuration file should read like this:

Location~ \.php$ {
Fastcgi_split_path_info^ (. +\.php) (/.+) $;
# This line passes requests through www.dongfan178.com to the PHP-FPM container
include Fastcgi_params;
        Fastcgi_param www.huayi1.cn/www.dongfan178.com script_filename $document _root $fastcgi _script_name         Fastcgi_param www.00534.cn path_info $fastcgi _path_info /span>

If you only serve a PHP-FPM container application, it is possible to hardcode the corresponding name in the configuration file of your Nginx container. However, as I mentioned above, each PHP service needs a corresponding Nginx container, we need to run multiple nginx containers. Creating a new Nginx image (which we must maintain and upgrade later) will be a pain, because even if you manage a bunch of different volumes, there seems to be much work to do to change the individual variable names.

First Solution: Use the methods mentioned in the Docker documentation Envsubst

At first, I thought it was easy. There is a nice little chapter on how to use ENVSUBST in the Docker documentation [4], but unfortunately, this does not apply to my Nginx configuration file:

server {
Index index.php index.html;
Location~ \.php$ {
       fastcgi_split_path_ Info ^ (. +\.php) (/.+) $;
        Fastcgi_pass ${nginx_host}:9000 ;
       fastcgi_index index.php;
       < Span class= "Hljs-attribute" >include fastcgi_params;
       fastcgi_param script_filename $document _root $fastcgi _script_name;
       fastcgi_param path_info $ Fastcgi_path_info;

My vhost.conf file uses several Nginx built-in environment variables, resulting in an error when I run the following command line mentioned in the Docker document: $uri and fastcgi_script_name are undefined.

/bin/bash -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g ‘daemon off;‘"

These variables are usually passed into [5] by Nginx itself, so it is not easy to figure out what they are and how to pass the parameters, and this can affect the dynamic configuration of the container.

Another almost-successful Docker image

Next, I started searching for a different nginx base image. Two were found, but both were not updated for two years. I start with martin/nginx[6] and try to see if I can get a working prototype.
Martin's image is a bit different because it requires a specific file directory structure. I first added the following in the Dockerfile:

FROM martin/nginx

Next, I added the app/empty directory, which contains only a conf/directory of vhost.conf files.

server {
Index index.php index.html;
   client_max_body_size 32m;
       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;

This is the same as my original configuration file, only modified one line: Fastcgi_pass $ENV {"Nginx_host"}:9000;. Now when I want to start a nginx container and a PHP container called Php-fpm-api, I can compile a new image and pass it to its corresponding environment variable when it runs:

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

It worked! But there are two problems with this approach that plague me:

    1. The base image version is obsolete and has not been updated for more than two years. This can pose a security and performance risk.

    2. Asking for an empty directory for an app doesn't seem to be necessary, plus my files are placed in different directories.

Final Solution

I think Martin's image is a good choice for custom options. So, I fork out his warehouse and build a new Nginx base image that solves the above two issues. Now, if you want to run a dynamic named back-end app with Nginx containers, you just need to do it simply:

# pull down the latest From Docker Hub
docker pull Shiphp/nginx-env:latest
# Run a PHP container named "Php-fpm-api"
docker run--name php-fpm-api-v $ (pwd) :/var/www php:fpm
# Start this NGinx container linked to the PHP-FPM container
Docker run--link php-fpm-api-e nginx_host=php-fpm-api shiphp/nginx-env

If you want to customize this image, add your own files or nginx config files, just expand your dockerfile as follows:

FROM shiphp/nginx-env

Now all of my php-fpm containers use an instance of a single nginx image, which makes my life a lot easier when I need to upgrade Nginx, modify permissions, or configure something.
All the code is on the github[2]. If you find any problems or want to make suggestions for improvement, please feel free to create issue. If you have any questions about this issue or docker, you can talk to me at twitter[7.
RELATED links:

    1. Https://www.shiphp.com/blog/2017/php-web-app-in-docker

    2. Https://github.com/shiphp/nginx-env

    3. https://blog.a2o.si/2009/06/24/apache-mod_php-compared-to-nginx-php-fpm/

    4. https://docs.docker.com/samples/library/nginx/#using-environment-variables-in-nginx-configuration

    5. Http://nginx.org/en/docs/varindex.html

    6. https://hub.docker.com/r/martin/nginx/

    7. Https://twitter.com/shiphpnow

Original link: https://www.shiphp.com/blog/2018/nginx-php-fpm-with-env

Kubernetes Introduction and Advanced combat training

A single nginx image tailored to multiple php-fpm containers

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.