


How to tailor a single Nginx image for multiple PHP-FPM containers
This article mainly introduces the method of tailoring a single Nginx image for multiple PHP-FPM containers. It has certain reference value. Now I share it with you. Friends in need can refer to it
Recently I've been working on deploying a set of PHP microservices using Docker containers. One of the issues is that our PHP application is set up to work with PHP-FPM and Nginx (rather than a simple Apache/PHP[1] setup as stated here), so two containers are required per PHP microservice (also It is equivalent to two Docker images):
PHP-FPM container
Nginx container
Assuming that an application runs more than six PHP microservices, including your dev and prod environments, there will eventually be close to 30 containers. Instead of building a unique Nginx image for each PHP-FPM microservice image, I decided to build a separate Nginx Docker image and map the PHP-FPM hostname as an environment variable to a unique configuration file in this image.
In this blog post, I will outline my process from method 1 to method 2 above, concluding with an introduction to how to use the new custom Nginx Docker image. Solution to end this blog.
I have made this image open source on GitHub[2], so if this happens to be a problem you often encounter, please feel free to check it out.
Why Nginx?
PHP-FPM and Nginx used together can produce better PHP application performance [3], but the disadvantage is that the PHP-FPM Docker image does not default to the PHP Apache image. Bundled with Nginx.
If you want to connect an Nginx container to a PHP-FPM backend, you 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, then your Nginx configuration file should read:
nginx location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; # This line passes requests through www.dongfan178.com to the PHP-FPM container fastcgi_pass php-fpm-api:9000; fastcgi_index index.php; 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; }
If you only serve one PHP-FPM container application, It is possible to hardcode the corresponding name in your Nginx container's configuration file. However, as I mentioned above, each PHP service requires a corresponding Nginx container, so we need to run multiple Nginx containers. Creating a new Nginx image (which we will have to maintain and upgrade later) will be a pain because even managing a bunch of different volumes seems like a lot of work to do to change a single variable name.
First solution: Use the method envsubst mentioned in the Docker documentation
At first, I thought it was easy. There is a nice little chapter in the Docker documentation on how to use envsubst[4], but unfortunately this does not work with my Nginx config file:
vhost.conf
nginx 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; } }
my vhost The .conf file uses several Nginx built-in environment variables. As a result, when I run the following command line mentioned in the Docker documentation, an error message appears: $uri and fastcgi_script_name are not defined.
shell /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 in by Nginx itself [5], so it is not easy to figure out what they are and how to pass parameters, and this will affect the dynamic configurability of the container
Another Docker image that almost succeeded
Next, I started searching for different Nginx base images. I found two, but both of them have not been updated in two years. I started with martin/nginx[6] and tried to see if I could get a working prototype.
Martin's image is a little different because it requires a specific file directory structure. I first added to the Dockerfile:
FROM martin/nginx
Next, I added the app/ empty directory and the conf/ directory containing only a vhost.conf file.
vhost.conf
nginx 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; } }
This is similar to my original configuration file, with only one line modified: fastcgi_pass $ENV{"NGINX_HOST"}:9000;. Now when I want to start an Nginx container and a PHP container called php-fpm-api, I can first compile a new image and then pass it the corresponding environment variable when it runs:
shell docker build -t shiphp/nginx-env:test . docker run -it --rm -e NGINX_HOST=php-fpm-api shiphp/nginx-env:test
Success! However, there are two problems that bother me with this method:
The base image version is old and has not been updated in more than two years. This can create security and performance risks.
It seems unnecessary to require an empty directory for an app, plus my files are placed in different directories.
Final solution
I think Martin's mirror is a good custom solution choice. So, I forked his repository and built a new Nginx base image that solved the above two problems. Now, if you want to run a dynamically named backend application with an nginx container, you simply do this:
shell # 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
如果你想自定义这个镜像,添加你自己的文件或者Nginx配置文件,只需要像下面这样扩展你的Dockerfile:
FROM shiphp/nginx-env ONBUILD ADD <PATH_TO_YOUR_CONFIGS> /etc/nginx/conf.d/
现在我所有的PHP-FPM容器都使用单个Nginx镜像的实例,当我需要升级Nginx、修改权限或者配置一些东西的时候,这让我的生活变得简单多了。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
The above is the detailed content of How to tailor a single Nginx image for multiple PHP-FPM containers. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Alipay PHP...

JWT is an open standard based on JSON, used to securely transmit information between parties, mainly for identity authentication and information exchange. 1. JWT consists of three parts: Header, Payload and Signature. 2. The working principle of JWT includes three steps: generating JWT, verifying JWT and parsing Payload. 3. When using JWT for authentication in PHP, JWT can be generated and verified, and user role and permission information can be included in advanced usage. 4. Common errors include signature verification failure, token expiration, and payload oversized. Debugging skills include using debugging tools and logging. 5. Performance optimization and best practices include using appropriate signature algorithms, setting validity periods reasonably,

Session hijacking can be achieved through the following steps: 1. Obtain the session ID, 2. Use the session ID, 3. Keep the session active. The methods to prevent session hijacking in PHP include: 1. Use the session_regenerate_id() function to regenerate the session ID, 2. Store session data through the database, 3. Ensure that all session data is transmitted through HTTPS.

How to debug CLI mode in PHPStorm? When developing with PHPStorm, sometimes we need to debug PHP in command line interface (CLI) mode...

The application of SOLID principle in PHP development includes: 1. Single responsibility principle (SRP): Each class is responsible for only one function. 2. Open and close principle (OCP): Changes are achieved through extension rather than modification. 3. Lisch's Substitution Principle (LSP): Subclasses can replace base classes without affecting program accuracy. 4. Interface isolation principle (ISP): Use fine-grained interfaces to avoid dependencies and unused methods. 5. Dependency inversion principle (DIP): High and low-level modules rely on abstraction and are implemented through dependency injection.

How to automatically set the permissions of unixsocket after the system restarts. Every time the system restarts, we need to execute the following command to modify the permissions of unixsocket: sudo...

Static binding (static::) implements late static binding (LSB) in PHP, allowing calling classes to be referenced in static contexts rather than defining classes. 1) The parsing process is performed at runtime, 2) Look up the call class in the inheritance relationship, 3) It may bring performance overhead.

Sending JSON data using PHP's cURL library In PHP development, it is often necessary to interact with external APIs. One of the common ways is to use cURL library to send POST�...
