Inside Docker: One Nginx But Different PHP Versions Based on Your Hostname | by Michael Bladowski | Feb, 2022

A sensible use case for the nginx http map module

Okay, right here’s an on a regular basis state of affairs all people ought to know:

You’ve got a typical docker-compose.yml setup with

  • nginx
  • php-fpm (PHP 7)
  • a database (not vital for us right here)

Let’s say your present PHP Model is 7.4 and also you need to improve your software to PHP 8.1 and simply lengthen your docker-compose.yml as a substitute of simply doing a “copy and paste” and duplicating every little thing. The purpose is to maintain each variations operating on the identical time, not changing the present config.

There are tons of the way to do that and all is perhaps okay. With this posting, I simply need to present you a approach even I didn’t know in any case that years.

So your default setup is perhaps fully completely different, so I need to present you mine relating to PHP:

Nothing particular, only a easy nginx/php-fpm combo.
The host.conf:

server 
pay attention 80;
server_name myapp.com;
root /app/public;
embody /and so forth/nginx/php.conf;

The php.conf (simply the vital half):

location ~ .php$ 
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass php-fpm7:9000;
fastcgi_index index.php;
embody fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;

Up to now, so good, nothing particular right here. So let’s say we need to add our new app and hold all that config recordsdata and scale back the duplication right here. I stumbled over a pleasant function of nginx: The ngx_http_map_module — in any case that years, I didn’t know that it exists — until now 🙂

Let me present you ways I’m utilizing this module on this particular case:

Contained in the nginx.conf within the “http” part, I added this:

map $http_host $phpfpm 
'myapp.com' 'php-fpm7'; <--- /app
'new.myapp.com' 'php-fpm8'; <--- /app-new

I lengthen my “host.conf” with the brand new digital host:

server 
pay attention 80;
server_name new.myapp.com
root /app-new/public; <----- completely different folder !
embody /and so forth/nginx/php.conf; <--- identical config

and, as we keep in mind, in our php.conf we have now a hard and fast “fastcgi_pass”:

php-fpm7:9000

as a result of with our new mapping, we are actually capable of substitute this with our new $variable, so the road will get modified to:

$phpfpm:9000

However — one thing I needed to study as effectively with this — as a result of nginx is operating inside Docker, we have now to inform nginx, which resolver nginx ought to use to have the ability to get the proper IP from our mapping hostnames: php-fpm7 and php-fpm8, in order that’s why we have now so as to add this:

resolver 127.0.0.11 ipv6=off;

and right here’s the ultimate results of our php.conf:

location ~ .php$ 
resolver 127.0.0.11 ipv6=off;
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass $phpfpm:9000;
fastcgi_index index.php;
embody fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;

With this setup, nginx is aware of which PHP-Container we need to use primarily based on our area title, cool 😉

In fact, we have now to increase our docker-compose.yml:

On the “nginx” service we have now to mount the listing of your “app-new”:

- /residence/app-new:/app-new

And we add one other PHP service with the identical mapping and
title it php-fpm8.

The top consequence seems like this:

Once more, many options come to the identical consequence, however I personally needed to see how this “mapping” works and tips on how to use it, I’m pleased with that answer, as a result of:

  • I can re-use my current important config: php.conf
  • I can use completely different PHP Variations in parallel, with the identical APP or with one other model of my app
  • I “might” use my php.conf for each undertaking, not one of the best thought, however potential, as a result of now the “mapping” tells nginx which container to make use of

So in fact, if you wish to take a look at your app with completely different PHP Variations on the identical time, your mapping might appear like this:

map $http_host $phpfpm 
'myapp.com' 'php-fpm5';
'php7.myapp.com' 'php-fpm7';
'php80.myapp.com' 'php-fpm80';
'php81.myapp.com' 'php-fpm81';

It’s simply an instance, you get the thought 😉

For me, it’s a pleasant and clear solution to deal with completely different PHP Variations inside the identical App.

Tip: Put the mapping right into a separate config, in our instance, let’s create
a php_mapping.conf and put the mapping inside (don’t overlook to mount it in your nginx service) and substitute the mapping contained in the “http” part of our nginx.conf with:

embody /and so forth/nginx/php_mapping.conf;

With that, even our nginx.conf has grow to be reusable for some other undertaking!

More Posts