We see a lot of research over the internet to make Apache & PHP-FPM work on windows.
But the first thing is: there is no php-fpm
on Windows. And many people give up on this, because of too many or
too complex solutions we find over the internet.
For sanity reasons, I will never talk about FPM on Windows, but I will instead talk about FastCGI.
Because FPM stands for FastCGI Process Manager. It’s just a manager for FastCGI processes.
So, let’s make a first reminder about how we use to deal with Apache & PHP on Windows, and then we’ll update our setup
to FastCGI.
Installing Apache and PHP on Windows
For some people, the Apache service is provided by WampServer, EasyPHP or other *AMP-like setup.
I personally hate these pre-built services because upgrading them is a PITA, and
most of the time the setup is not always performant, everything depend on the rest, etc.
In my case, I’m using Apache Lounge which is a stand-alone Apache server for Windows.
Then, I download PHP for Windows on windows.php.net, which
can be installed wherever I want.
⚡⚠ Warning: For mod_php
, you need the thread safe (ts
) version of PHP.
When we’ll install our FastCGI setup, you will have to download PHP again with the non-thread-safe (nts
) version.
I personally have both versions installed in php-ts
and php-nts
directories in my computer, in case of.
I also download a windows version of MariaDB and PostgreSQL for my apps, but it’s not the subject.
All of this decoupled setup is very flexible, and it’s what we need.
Then, let’s configure it.
Before talking about FastCGI, let’s see what we use to do, most of the time.
Configuring Apache and PHP with mod_php
: what everyone says
This is really easy to do, because it’s a few lines in our {ApacheLounge}/conf/httpd.conf
:
# Load PHP module from our setup.
LoadModule php7_module e:\dev\php71\php7apache2_4.dll
# Custom php.ini file, because it's important to have a different file than the command-line.
PHPIniDir "e:/dev/php71/php-apache.ini"
# And the default config to make Apache run PHP for PHP files.
<FilesMatch ".+\.ph(p[345]?|t|tml)$">
SetHandler application/x-httpd-php
</FilesMatch>
# Deny access to raw php sources by default
<FilesMatch ".+\.phps$">
SetHandler application/x-httpd-php-source
Require all denied
</FilesMatch>
# Deny access to files without filename (e.g. '.php')
<FilesMatch "^\.ph(p[345]?|t|tml|ps)$">
Require all denied
</FilesMatch>
And that’s all. Just configure a vhost to point on your project and you’re set:
<VirtualHost *:80>
ServerName 127.0.0.1
DocumentRoot e:/dev/www
<Directory e:/dev/www>
AllowOverride all
Options Indexes FollowSymLinks MultiViews
Require all granted
</Directory>
</VirtualHost>
But here, we’re using mod_php
.
Why FastCGI?
It’s well-known that mod_php
can have some RAM or CPU issues, that projects with lots of calls at the same time can
suffer from timeouts, memory and cache not managed like we would like to, etc.
Also, using this extension prevents you to have multiple PHP versions installed. Because with mod_php
you can have
only one php extension loaded, and only one file handler for the same patterns.
With FastCGI in general, you can configure communication between Apache and PHP in different ways, and
especially between virtual hosts. So if you have your PHP 7.1 app and PHP 5.4 legacy bag of crap you want to maintain on
your same Windows computer, you’re almost forced to use FastCGI.
The only solution to have multiple PHP versions with Apache and mod_php is to comment/uncomment lines of code in your
httpd.conf
everytime you switch projects.
And what if projects communicate together with API calls? Well, you’re f***ed, then…
So, let’s move on to FastCGI.
Configure Apache with FastCGI
First thing to do is to configure apache. We’ll configure PHP later.
Lucky we are: it’s even easier than with mod_php
.
You can remove all the mod_php
config we added before. We’ll replace it with another config. And it was just a
reminder, because it’s cool to know what whe’re doing.
Open your httpd.conf
file, and after removing all mod_php
garbage, activate these two extensions:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
The proxy
module is here to help us using Apache like a proxy.
Nothing fancy here. If we want to explain it simply, let’s say that Apache will sort of be able to delegate some HTTP
requests to another service via a protocol (and this service will sometimes be called a gateway).
The proxy_fcgi
module is just here to add the fcgi
protocol to the Proxy, so we can communicate with a gateway by
using this protocol. But we could have been using other protocols for other needs, like ftp
, http
or even ws
(web-sockets).
When FastCGI proxy is enabled, let’s tell Apache we want to use our PHP config:
<Files ~ "\.php$">
SetHandler "proxy:fcgi://127.0.0.1:9000#"
</Files>
Ok, the PHP config is not ready yet, but what these likes say is that any file matching \.(php|phtml)$
will tell
Apache to handle the request via a proxy
, that will use the fcgi
protocol to send the HTTP request to 127.0.0.1
.
The port 9000
is the one we’ll use in our PHP config, and it’s the default one used in php-fpm
in unix systems.
And the #
seems to come from an issue inside Apache modules that do not send the correct path to the gateway, and this
issue is fixed by adding this character at the end of the handler’s url.
That’s all. We can leave our Apache config and move to PHP one.
Configure PHP CGI module
CGI is very old (1993) and cool. It’s an interface for HTTP servers to be able to execute another program instead of
just displaying the resource asked by the user.
In short words, it’s meant to execute our PHP files instead of just showing the PHP file’s content.
It’s a protocol which is really nice when dealing with stuff like interpreted languages like PHP, Ruby, etc., because it
allow us to just use our web-server without knowing what it does so we don’t learn anything about HTTP web servers and
how our interpreters work. It’s a nice jump into “Damn it doesn’t work!” instead of “I probably did something wrong,
let’s fix this.”.
Just a small reminder: I said in the Installing Apache and PHP on Windows part
that here you must have the nts
version of PHP. Make sure you have the right one starting from her.
Well, we have many options, but I’ll talk about options later.
We need PHP to be run as a service. Dammit, what’s a service in Windows ?
It’s a specific type of process that runs sort of “in the background” in order to process tasks, pop alerts, monitor,
or just make your computer works.
Somehow they can be similarly compared to what you have in your /etc/init.d
in unix systems. But it’s not the same.
Because you know, difference between UNIX and NT stuff, etc.
Why run it as service? Because else, you would have to double-click on the CGI script, and make sure the cmd
window is
not closed, and restarting it will be boring, etc.
Having a service is nice because we can just restart it in the “Services” panel if we need, and it can be automatically
launched on Windows startup.
Create the CGI service
To create a service, we could run into the sc
command in Windows, but I find it very neat that we can setup a service
without torturing ourselves.
So I’m using NSSM to manage my personal services.
It’s great because I’ve set up PHP-CGI, Apache, MariaDB and Blackfire Agent with it, and it’s lovely.
So, download this small executable, run nssm install
, and a cool popup will show.
You’ll fill a few options:
Just an explanation about the options:
php-cgi.exe
is the script we must execute.php.exe
is a command-line interface (CLI), not a CGI one.-c E:\dev\php71\php-apache.ini
is used to specify ourphp.ini
file. I named it like this, but you can change it if
you like.-b 127.0.0.1:9000
is the IP and port that PHP CGI will listen to. We need it to be as closed as possible, so we only
allow requests corresponding to127.0.0.1
. And as said when configuring Apache,9000
is the default port for the
php-fpm
unix config, so let’s use it because it’s a common thing.
That’s all!
Now your project should work.
More flexibility: multiple PHP versions with Apache
This is often asked, so let’s see how we can handle this.
First, if you have multiple PHP versions, you must create multiple php-cgi
services, so this is why nssm
is
really nice: it’s as easy as two lines of config. Just create a new service pointing to your other PHP version, and
change the port to 9001
, 9002
or whatever you like that does not conflict with any other software.
Then, you will have to remove the SetHandler
config from httpd.conf
and move it to your vhosts, like this:
<VirtualHost *:80>
# Our PHP 7.1 application, using the first cgi module listening to port 9000
ServerName php71-app.dev
DocumentRoot e:/dev/www/app1
<Files ~ "\.(php|phtml)$">
SetHandler "proxy:fcgi://127.0.0.1:9000#"
</Files>
<Directory e:/dev/www/app1>
AllowOverride all
Options Indexes FollowSymLinks MultiViews
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:80>
# Our PHP 5.4 application, using the second cgi module listening to port 9001
ServerName php54-app.dev
DocumentRoot e:/dev/www/app2
<Files ~ "\.(php|phtml)$">
SetHandler "proxy:fcgi://127.0.0.1:9001#"
</Files>
<Directory e:/dev/www/app2>
AllowOverride all
Options Indexes FollowSymLinks MultiViews
Require all granted
</Directory>
</VirtualHost>
That’s it, now you can enjoy having multiple PHP versions!
⚠️ If you’re using Apache 2.4.25+, you must specify this directive:
ProxyFCGIBackendType GENERIC
Only necessary for Apache 2.4.26 and higher versions, because this release introduced a new behavior in the FCGI
protocol handled by the mod_proxy_fcgi
module.
If you don’t specify this directive, you will encounter a No input file specified.
error, because it’s related to some
proxy:fcgi://
string that’s passed to PHP that is not interpreted correctly.
This behavior is not needed when using Apache + php-fpm, because we can rely on a unix socket.
While PHP-FPM isn’t available on Windows, you can use mod_fcgid to run PHP as FastCGI under Apache instead.
The Apache Lounge distribution doesn’t ship with mod_fcgid
included by default though, and you have to install it as an extra step which I thought was worth documenting for future reference.
Install PHP
I use Chocolatey to manage packages, so installing PHP is as easy as:
choco install php
The manual installation process is pretty simple too though:
- Download the current either x86 or x64 (depending on your OS) «Non Thread Safe» distribution from PHP for Windows.
- Extract the downloaded ZIP to somewhere on your filesystem. Chocolatey installs to
C:\tools\php84
by default, and the rest of this post will assume the same path. - Add
C:\tools\php84
as an entry in yourPATH
environment variable.
Copy the php.ini-development
or php.ini-production
file to php.ini
and make any required changes.
Check that PHP is working by checking its version:
php -v
You should expect some output such as:
PHP 8.4.3 (cli) (built: Jan 15 2025 11:02:41) (NTS Visual C++ 2022 x64)
Copyright (c) The PHP Group
Zend Engine v4.4.3, Copyright (c) Zend Technologies
Install Apache
While Apache is available in the Chocolatey public feed, it uses the Apache Haus distribution and unfortunately this project is on hold.
Manual installation is similarly easy:
- Download the current Apache release from Apache Lounge, making sure that if you chose an x64 version of PHP that you also choose an x64 version of Apache.
- Extract the downloaded folder to C:\Apache24.
- Add
C:\Apache24\bin
as an entry in yourPATH
environment variable.
Run the following command to install Apache as a service:
C:\Apache24\bin\httpd.exe -k install -n Apache
Make any required changes to C:\Apache24\conf\httpd.conf
to configure the server, such as setting the document root, enabling modules, etc.
Check the syntax of the server configuration file:
httpd -t
You should expect some output such as:
Syntax OK
Install mod_fcgid
We have to install mod_fcgid
manually, as it is not included when installed either through Chocolatey or manually.
- Head to the Apache Lounge downloads page.
- Scroll down to the heading «Apache 2.4 modules VS17».
- Download the
mod_fcgid
module. - Open the downloaded ZIP file, which should contain the following items (and several others that we’re not interested in):
mod_fcgid.so
- Copy these items as follows within
C:\Apache24\Apache24
:- Copy
mod_fcgid.so
tomodules\mod_fcgid.so
- Copy
Now that we have the module installed, we need to load and configure it.
Open conf\extra\httpd-fcid.conf
in a text editor. Replace the content of the file with the following:
<IfModule fcgid_module>
FcgidInitialEnv PHPRC "C:\\tools\\php82"
FcgidInitialEnv PATH "C:\\tools\\php82;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;"
FcgidInitialEnv SystemRoot "C:\\Windows"
FcgidInitialEnv SystemDrive "C:"
FcgidInitialEnv TEMP "C:\\WINDOWS\\TEMP"
FcgidInitialEnv TMP "C:\\WINDOWS\\TEMP"
FcgidInitialEnv windir "C:\\WINDOWS"
FcgidIOTimeout 40
FcgidConnectTimeout 10
FcgidMaxProcesses 8
FcgidOutputBufferSize 64
ProcessLifeTime 240
FcgidMaxRequestsPerProcess 0
FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 0
FcgidInitialEnv PHP_FCGI_CHILDREN 0
FcgidProcessLifeTime 3600
FcgidMinProcessesPerClass 0
<Files ~ "\.php$">
Options ExecCGI SymLinksIfOwnerMatch
AddHandler fcgid-script .php
FcgidWrapper "C:/tools/php82/php-cgi.exe" .php
</Files>
</IfModule>
httpd-fcgid.conf
Open conf\httpd.conf
in a text editor. Add or uncomment the following to the end of the file (or put it next to the other Include directives):
LoadModule fcgid_module modules/mod_fcgid.so
Include conf/extra/httpd-fcgid.conf
httpd.conf
Closing Thoughts
Immediately after switching to mod_fcgid
, there was a perceivable performance improvement. This is most likely due to mod_php
requiring a thread safe version of PHP which will include locks.
The actual upgrade to PHP 8.2 from 8.1 itself also went pretty smoothly, with no breakage to existing code — which is always nice!
Last Updated :
25 Jul, 2024
PHP-FPM stands for PHP FastCGI Process Manager. This is a strong and effective PHP FastCGI setup designed for managing operations on sites with high traffic. Setting up the php-fpm in Windows might seem tough, but with the right instructions, it’s achievable without any problems. This manual will guide you through the complete installation process, covering essential PHP concepts, various installation techniques, and how to confirm the installation’s success. Let’s begin without delay.
Key Terminologies
- PHP: It is one of the most popular general-purpose scripting languages that is mostly suited to web development.
- PHP-FPM: PHP FastCGI Process Manager is a daemon to manage server-based applications using FastCGI.
- FastCGI: This is, however, a simple protocol for interfacing the interactive programs with a web server.
- Windows: This is just an associated group of various proprietary graphical operating systems developed, marketed, and sold by Microsoft.
Step-by-Step Installation Guide
Method 1: Using Windows Subsystem for Linux (WSL)
Step 1: The first step is enabling WSL on your local machine with Windows; this can be done by navigating to Control Panel, then Programs, and after that Turning Windows features on or off.
Step 2: Then, you can set up any of your favourite Linux distributions from the Microsoft Store. Mostly, it is recommended to go with Ubuntu.
Step 3: Now open the Linux terminal and then update the package list with this command:
sudo apt update
Step 4: Then head to install php-fpm with following command:
sudo apt install php7.4-fpm
Step 5: After the steps up, we need to make sure whether the installation takes place by verifying the installation with this command:
sudo systemctl status php7.4-fpm
Method 2: By Using XAMPP
Step 1: First go to the following website and download and install XAMPP from [apachefriends.org](https://www.apachefriends.org/)
Step 2: Then launch the XAMPP Control Panel and start Apache within it and verify that it is running up properly.
Step 3: Now download the PHP-FPM binary from this resource [windows.php.net/downloads/pecl/releases/php_fpm/](https://windows.php.net/downloads/pecl/releases/php_fpm/).
Step 4: After that you need to extract the contents of the downloaded file to the PHP directory in your XAMPP installation which we installed and run previously
Step 5: Configure PHP-FPM by editing php.ini and uncommenting the cgi-fix_pathinfo.
Step 6: After that, start the PHP-FPM by creating the .bat file and double-click on it to run.
After that it will open in the browser.
Installation Verification
To verify the installation, one needs just to open a terminal or command prompt and enter php-fpm -v. If php-fpm is installed correctly, the version information will be printed and displayed on the terminal.
I hope that, with this comprehensive guide, it will be much easier for you to go through these two different installations. Good luck with your setup with WSL or XAMPP for your php-fpm configuration.
Conclusion
Installing php-fpm on Windows is an effective and efficient way of managing PHP applications. By merely following this easy guide, you will be up and running with php-fpm using either the Windows Subsystem for Linux or XAMPP itself. After the installation, do not forget to verify the installation to ensure everything is set up correctly.
PHP-FPM, Apache with *.localhost virtualhosts on WSL
This will help installing simple PHP stack with *.localhost domains on Windows Subsystem for Linux in Windows 10. You’ll have to add sudo
where appropriate.
You’ll need to add an unofficial repository by awesome Ondřej Surý, but it’s been stable for years and can be used in production.
sudo apt-get install -y python-software-properties sudo add-apt-repository -y ppa:ondrej/php sudo apt-get update -y
Install 7.1 (CLI and FPM):
sudo apt-get install php7.1 php7.1-cli php7.1-common php7.1-json php7.1-opcache php7.1-mysql php7.1-mbstring php7.1-mcrypt php7.1-zip php7.1-fpm
Install additional extensions with apt-get install php-7.1-*extension*
. You can get a list of all available PHP packages with sudo apt-cache search php7.1
.
You’ll probably want composer. You know where to get it and what to do with it. It will hint if any PHP packages are missing.
You’ll have to start FPM manually each time system is rebooted, however: service php7.1-fpm start
. Also, remember to restart it if adding or removing extensions.
Apache
Moving on to Apache. Trivial apt-get install apache2
will do. Enable modules:
a2enmod rewrite php7.1-fcgi proxy proxy_fcgi a2enconf php7.1-fpm
We’ll setup our virtualhost in a such way, that a folder test
maps to URL http://test.localhost
. Edit default virtualhost (probably at /etc/apache2/sites-enabled/000-default.conf
by adding following lines:
RewriteEngine On
RewriteMap lowercase int:tolower
RewriteCond %{HTTP_HOST} ^(.*)\.localhost$
RewriteRule ^(.*)$ "/your/webroot/with/hosts/${lowercase:%1}/$1"
Restart apache with service apache2 restart
.
Warning. These rewrite rules might (most probably will) break any local rewrites you might have in .htaccess.
Webroot from Windows to WSL
If you’r development directory is on windows, no biggie. Just mount it under linux.
mkdir /var/www/webroot mount /mnt/[disk]/[your/webroot] /var/www/webroot
- September 10, 2022
- PHP
- Apache and PHP-FPM in Windows
- Install php fpm windows
- Apache and PHP-FPM in Windows
- Setting up PHP, PHP-FPM and NGINX for local development on Docker
- How to install Nginx, PHP, PHP-FPM and MySQL under Windows with Cygwin
Apache and PHP-FPM in Windows
# Load PHP module from our setup.
LoadModule php7_module e:\dev\php71\php7apache2_4.dll
# Custom php.ini file, because it's important to have a different file than the command-line.
PHPIniDir "e:/dev/php71/php-apache.ini"
# And the default config to make Apache run PHP for PHP files.
<FilesMatch ".+\.ph(p[345]?|t|tml)$">
SetHandler application/x-httpd-php
</FilesMatch>
# Deny access to raw php sources by default
<FilesMatch ".+\.phps$">
SetHandler application/x-httpd-php-source
Require all denied
</FilesMatch>
# Deny access to files without filename (e.g. '.php')
<FilesMatch "^\.ph(p[345]?|t|tml|ps)$">
Require all denied
</FilesMatch>
<VirtualHost *:80>
ServerName 127.0.0.1
DocumentRoot e:/dev/www
<Directory e:/dev/www>
AllowOverride all
Options Indexes FollowSymLinks MultiViews
Require all granted
</Directory>
</VirtualHost>
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
<Files ~ "\.php$">
SetHandler "proxy:fcgi://127.0.0.1:9000#"
</Files>
<VirtualHost *:80>
# Our PHP 7.1 application, using the first cgi module listening to port 9000
ServerName php71-app.dev
DocumentRoot e:/dev/www/app1
<Files ~ "\.(php|phtml)$">
SetHandler "proxy:fcgi://127.0.0.1:9000#"
</Files>
<Directory e:/dev/www/app1>
AllowOverride all
Options Indexes FollowSymLinks MultiViews
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:80>
# Our PHP 5.4 application, using the second cgi module listening to port 9001
ServerName php54-app.dev
DocumentRoot e:/dev/www/app2
<Files ~ "\.(php|phtml)$">
SetHandler "proxy:fcgi://127.0.0.1:9001#"
</Files>
<Directory e:/dev/www/app2>
AllowOverride all
Options Indexes FollowSymLinks MultiViews
Require all granted
</Directory>
</VirtualHost>
ProxyFCGIBackendType GENERIC
Install php fpm windows
Here how to setup php-fpm on Windows:
Download the .zip file from http://windows.php.net/download/. The .zip file should be VC9 which has the FastCGI file (php-cgi.exe). Don't download VC6, and don't download the .msi file because it requires that you have IIS setup already in order to install php-fpm. The zip file contains the php-cgi.exe which is what you need for php-fpm. I downloaded a slightly older version, php-5.3.10-Win32-VC9-x86.zip, from here http://windows.php.net/downloads/releases/archives/ because I wanted to match the version running on my production server.
Unzip the file, e.g. unzip into C:\php-5.3.10-Win32-VC9-x86
Edit the php.ini file as needed. What I did:
# nginx security setting
cgi.fix_pathinfo=0
extension_dir = "C:\php-5.3.10-Win32-VC9-x86\ext"
enable the following modules by uncommenting them:
extension=php_curl.dll
extension=php_mbstring.dll
extension=php_mysqli.dll
Create a .bat file somewhere, e.g. start-php-fcgi.bat in webserver directory or in the PHP directory:
@ECHO OFF
ECHO Starting PHP FastCGI...
set PATH=C:\php-5.3.10-Win32-VC9-x86;%PATH%
C:\php-5.3.10-Win32-VC9-x86\php-cgi.exe -b 127.0.0.1:9123 -c C:\php-5.3.10-Win32-VC9-x86\php.ini
Double click the .bat file to start php-fpm. A window will popup and stay open while its running. Its kind of annoying, but just haven't looked into setting it up as service yet.
Configure your webserver. If you wish to use it with nginx, here a config sample for 127.0.0.1:9123:
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9123;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
sudo apt install php php-fpm
Apache and PHP-FPM in Windows
# Load PHP module from our setup.
LoadModule php7_module e:\dev\php71\php7apache2_4.dll
# Custom php.ini file, because it's important to have a different file than the command-line.
PHPIniDir "e:/dev/php71/php-apache.ini"
# And the default config to make Apache run PHP for PHP files.
<FilesMatch ".+\.ph(p[345]?|t|tml)$">
SetHandler application/x-httpd-php
</FilesMatch>
# Deny access to raw php sources by default
<FilesMatch ".+\.phps$">
SetHandler application/x-httpd-php-source
Require all denied
</FilesMatch>
# Deny access to files without filename (e.g. '.php')
<FilesMatch "^\.ph(p[345]?|t|tml|ps)$">
Require all denied
</FilesMatch>
<VirtualHost *:80>
ServerName 127.0.0.1
DocumentRoot e:/dev/www
<Directory e:/dev/www>
AllowOverride all
Options Indexes FollowSymLinks MultiViews
Require all granted
</Directory>
</VirtualHost>
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
<Files ~ "\.php$">
SetHandler "proxy:fcgi://127.0.0.1:9000#"
</Files>
<VirtualHost *:80>
# Our PHP 7.1 application, using the first cgi module listening to port 9000
ServerName php71-app.dev
DocumentRoot e:/dev/www/app1
<Files ~ "\.(php|phtml)$">
SetHandler "proxy:fcgi://127.0.0.1:9000#"
</Files>
<Directory e:/dev/www/app1>
AllowOverride all
Options Indexes FollowSymLinks MultiViews
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:80>
# Our PHP 5.4 application, using the second cgi module listening to port 9001
ServerName php54-app.dev
DocumentRoot e:/dev/www/app2
<Files ~ "\.(php|phtml)$">
SetHandler "proxy:fcgi://127.0.0.1:9001#"
</Files>
<Directory e:/dev/www/app2>
AllowOverride all
Options Indexes FollowSymLinks MultiViews
Require all granted
</Directory>
</VirtualHost>
ProxyFCGIBackendType GENERIC
Setting up PHP, PHP-FPM and NGINX for local development on Docker
mkdir -p "C:/codebase/docker-php/app"
docker run -d --name docker-php -v "C:/codebase/docker-php/app":/var/www php:7.0-cli
docker run // run a container
-d // in the background (detached)
--name docker-php // named docker-php
-v "C:/codebase/docker-php/app":/var/www // sync the directory C:/codebase/docker-php/app on the
// windows host with /var/www in the container
php:7.0-cli // use this image to build the container
$ docker run -d --name docker-php -v "C:/codebase/docker-php/app":/var/www php:7.0-cli
Unable to find image 'php:7.0-cli' locally
7.0-cli: Pulling from library/php
f2aa67a397c4: Pulling fs layer
c533bdb78a46: Pulling fs layer
65a7293804ac: Pulling fs layer
35a9c1f94aea: Pulling fs layer
54cffc62e1c2: Pulling fs layer
153ff2f4c2af: Pulling fs layer
96d392f71f56: Pulling fs layer
e8c43e665458: Pulling fs layer
35a9c1f94aea: Waiting
54cffc62e1c2: Waiting
153ff2f4c2af: Waiting
96d392f71f56: Waiting
e8c43e665458: Waiting
c533bdb78a46: Verifying Checksum
c533bdb78a46: Download complete
35a9c1f94aea: Verifying Checksum
35a9c1f94aea: Download complete
f2aa67a397c4: Verifying Checksum
f2aa67a397c4: Download complete
153ff2f4c2af: Verifying Checksum
153ff2f4c2af: Download complete
54cffc62e1c2: Verifying Checksum
54cffc62e1c2: Download complete
e8c43e665458: Verifying Checksum
e8c43e665458: Download complete
96d392f71f56: Verifying Checksum
96d392f71f56: Download complete
f2aa67a397c4: Pull complete
65a7293804ac: Verifying Checksum
65a7293804ac: Download complete
c533bdb78a46: Pull complete
65a7293804ac: Pull complete
35a9c1f94aea: Pull complete
54cffc62e1c2: Pull complete
153ff2f4c2af: Pull complete
96d392f71f56: Pull complete
e8c43e665458: Pull complete
Digest: sha256:ff6c5e695a931f18a5b59c82b1045edea42203a299e89a554ebcd723df8b9014
Status: Downloaded newer image for php:7.0-cli
56af890e1a61f8ffa5528b040756dc62a94c0b929c29df82b9bf5dec6255321f
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
56af890e1a61 php:7.0-cli "docker-php-entrypoi…" 27 seconds ago Exited (0) 25 seconds ago docker-php
docker run -di --name docker-php -v "C:/codebase/docker-php/app":/var/www php:7.0-cli
[email protected] MINGW64 /
$ docker run -di --name docker-php -v "C:/codebase/docker-php/app":/var/www php:7.0-cli
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from daemon: Conflict. The container name "/docker-php" is already in use by container "56af890e1a61f8ffa5528b040756dc62a94c0b929c29df82b9bf5dec6255321f". You have to remove (or rename) that container to be able to reuse that name.
See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.
docker rm docker-php
[email protected] MINGW64 /
$ docker rm docker-php
docker-php
[email protected] MINGW64 /c/codebase/docker-php
docker run -di --name docker-php -v "C:/codebase/docker-php/app":/var/www php:7.0-cli
7b3024a542a2d25fd36cef96f4ea689ec7ebb758818758300097a7be3ad2c2f6
[email protected] MINGW64 /c/codebase/docker-php
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b3024a542a2 php:7.0-cli "docker-php-entrypoi…" 5 seconds ago Up 4 seconds docker-php
docker exec -it docker-php bash
[email protected] MINGW64 /c/codebase/docker-php
$ docker exec -it docker-php bash
the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty'
winpty docker exec -it docker-php bash
[email protected] MINGW64 /c/codebase/docker-php
$ winpty docker exec -it docker-php bash
[email protected]:/#
[email protected]:/# php -v
PHP 7.0.30 (cli) (built: May 23 2018 23:04:32) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
cd "C:\codebase\docker-php\app"
echo '<?php echo "Hello World (php)\n"; ?>' > hello-world.php
[email protected] MINGW64 /c/codebase/docker-php
$ ls -alh app
total 1,0K
drwxr-xr-x 1 Pascal 197121 0 Mai 28 12:29 ./
drwxr-xr-x 1 Pascal 197121 0 Mai 28 11:46 ../
-rw-r--r-- 1 Pascal 197121 49 Mai 28 12:30 hello-world.php
[email protected]:/# ls -alh /var/www
total 4.5K
drwxr-xr-x 2 root root 0 May 28 10:29 .
drwxr-xr-x 1 root root 4.0K May 28 10:00 ..
-rwxr-xr-x 1 root root 31 May 28 10:31 hello-world.php
php /var/www/hello-world.php
[email protected]:/# php /var/www/hello-world.php
Hello World
pecl install xdebug-2.6.0
[email protected]:/# pecl install xdebug-2.6.0
[...]
Build process completed successfully
Installing '/usr/local/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so'
install ok: channel://pecl.php.net/xdebug-2.6.0
configuration option "php_ini" is not set to php.ini location
You should add "zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so" to php.ini
docker-php-ext-enable xdebug
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so
php -i | grep "additional .ini"
[email protected]:/# php -i | grep "additional .ini"
Scan this dir for additional .ini files => /usr/local/etc/php/conf.d
[email protected]:/# ls -alh /usr/local/etc/php/conf.d
total 12K
drwxr-sr-x 1 root staff 4.0K May 28 13:30 .
drwxr-sr-x 1 root staff 4.0K Apr 30 20:34 ..
-rw-r--r-- 1 root staff 81 May 28 13:30 docker-php-ext-xdebug.ini
[email protected]:/# cat /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so
[email protected]:/# php -m | grep xdebug
xdebug
docker stop docker-php
[email protected] MINGW64 /c/codebase/docker-php
$ docker stop docker-php
docker-php
[email protected] MINGW64 /c/codebase/docker-php
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b3024a542a2 php:7.0-cli "docker-php-entrypoi…" 2 hours ago Exited (137) 7 seconds ago docker-php
docker start docker-php
[email protected] MINGW64 /c/codebase/docker-php
$ docker start docker-php
docker-php
[email protected] MINGW64 /c/codebase/docker-php
$ winpty docker exec -it docker-php bash
[email protected]:/# php -m | grep xdebug
xdebug
docker rm -f docker-php
docker run -di --name docker-php -v "C:/codebase/docker-php/":/codebase php:7.0-cli
inpty docker exec -it docker-php bash
php -m | grep xdebug
[email protected] MINGW64 /c/codebase/docker-php
$ docker rm -f docker-php
docker-php
[email protected] MINGW64 /c/codebase/docker-php
$ docker run -di --name docker-php -v "C:/codebase/docker-php/":/codebase php:7.0-cli
1da17524418f5327760eb113904b7ceec30f22b41e4b4bd77f9fa2f7b92b4ead
[email protected] MINGW64 /c/codebase/docker-php
$ winpty docker exec -it docker-php bash
[email protected]:/# php -m | grep xdebug
[email protected]:/#
mkdir "C:/codebase/docker-php/php-cli/"
touch "C:/codebase/docker-php/php-cli/Dockerfile"
FROM php:7.0-cli
RUN pecl install xdebug-2.6.0 \
&& docker-php-ext-enable xdebug
cd "C:/codebase/docker-php/php-cli/"
docker build -t docker-php-image -f Dockerfile .
"docker build" requires exactly 1 argument.
See 'docker build --help'.
Usage: docker build [OPTIONS] PATH | URL | - [flags]
Build an image from a Dockerfile
[email protected] MINGW64 /c/codebase/docker-php/php-cli
$ docker build -t docker-php-image -f Dockerfile .
Sending build context to Docker daemon 5.12kB
Step 1/2 : FROM php:7.0-cli
---> da771ba4e565
Step 2/2 : RUN pecl install xdebug-2.6.0 && docker-php-ext-enable xdebug
---> Running in ff16ef56e648
downloading xdebug-2.6.0.tgz ...
Starting to download xdebug-2.6.0.tgz (283,644 bytes)
[...]
You should add "zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so" to php.ini
Removing intermediate container ff16ef56e648
---> 12be27256b12
Successfully built 12be27256b12
Successfully tagged docker-php-image:latest
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
docker run -di --name docker-php -v "C:/codebase/docker-php/app":/var/www docker-php-image
[email protected] MINGW64 /c/codebase/docker-php/php-cli
$ docker run -di --name docker-php -v "C:/codebase/docker-php/app":/var/www docker-php-image
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from daemon: Conflict. The container name "/docker-php" is already in use by container "2e84cb536fc573142a9951331b16393e3028d9c6eff87f89cfda682279634a2b". You have to remove (or rename) that container to be able to reuse that name.
See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.
docker rm -f docker-php
docker run -di --name docker-php -v "C:/codebase/docker-php/app":/var/www docker-php-image
[email protected] MINGW64 /c/codebase/docker-php/php-cli
$ docker rm -f docker-php
docker-php
[email protected] MINGW64 /c/codebase/docker-php/php-cli
$ docker run -di --name docker-php -v "C:/codebase/docker-php/app":/var/www docker-php-image
f27cc1310c836b15b7062e1fd381f283250a85133fb379c4cf1f891dec63770b
[email protected] MINGW64 /c/codebase/docker-php/php-cli
$ winpty docker exec -it docker-php bash
[email protected]:/# php -m | grep xdebug
xdebug
[email protected] MINGW64 /c/codebase/docker-php/php-cli
$ docker run docker-php-image php -m | grep xdebug
xdebug
[email protected] MINGW64 /c/codebase/docker-php/php-cli
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
abc9fec8a88b docker-php-image "docker-php-entrypoi…" 4 minutes ago Exited (0) 4 minutes ago distracted_mclean
f27cc1310c83 docker-php-image "docker-php-entrypoi…" 10 minutes ago Exited (137) 6 minutes ago docker-php
docker rm -f $(docker ps -aq)
[email protected] MINGW64 /c/codebase/docker-php/php-cli
$ docker rm -f $(docker ps -aq)
abc9fec8a88b
f27cc1310c83
docker run -di nginx:latest
[email protected] MINGW64 /
$ docker run -di nginx:latest
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
[...]
Status: Downloaded newer image for nginx:latest
15c6b8d8a2bff873f353d24dc9c40d3008da9396029b3f1d9db7caeebedd3f50
$ winpty docker exec -it 15c6b8d8a2bff873f353d24dc9c40d3008da9396029b3f1d9db7caeebedd3f50 bash
[email protected]:/#
bash: ps: command not found" as a response.
apt-get update && apt-get install -y procps
[email protected]:/# apt-get update && apt-get install -y procps
Get:1 http://security.debian.org/debian-security stretch/updates InRelease [94.3 kB]
[...]
associated file /usr/share/man/man1/w.procps.1.gz (of link group w) doesn't exist
Processing triggers for libc-bin (2.24-11+deb9u3) ...
[email protected]:/# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 32608 5148 ? Ss 06:46 0:00 nginx: master process nginx -g daemon off;
nginx 5 0.0 0.1 33084 2388 ? S 06:46 0:00 nginx: worker process
root 14 0.0 0.1 18132 3272 pts/0 Ss 06:50 0:00 bash
root 259 0.0 0.1 36636 2844 pts/0 R+ 06:53 0:00 ps aux
[email protected]:/#
[email protected]:/# nginx -V
nginx version: nginx/1.13.12
built by gcc 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)
built with OpenSSL 1.1.0f 25 May 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/ng
inx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path
=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-
http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module
--with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_
module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.13.12/debian/debuild-base/nginx-
1.13.12=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-specs=/usr/share/dpkg/no-pie-link.specs -Wl,-z,relr
o -Wl,-z,now -Wl,--as-needed -pie'
cat /etc/nginx/nginx.conf
[email protected]:/# cat /etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
ls -alh /etc/nginx/conf.d/
cat /etc/nginx/conf.d/default.conf
[email protected]:/# ls -alh /etc/nginx/conf.d/
total 12K
drwxr-xr-x 2 root root 4.0K Apr 30 13:55 .
drwxr-xr-x 3 root root 4.0K Apr 30 13:55 ..
-rw-r--r-- 1 root root 1.1K Apr 9 16:01 default.conf
[email protected]:/# cat /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
apt-get install curl -y
curl localhost:80
[email protected]:/# apt-get install curl -y
Reading package lists... Done
Building dependency tree
[...]
Running hooks in /etc/ca-certificates/update.d...
done.
[email protected]:/# curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
sed -i "s#/usr/share/nginx/html#/var/www#" /etc/nginx/conf.d/default.conf
mkdir -p /var/www
echo "Hello world!" > /var/www/index.html
nginx -s reload
[email protected]:/# nginx -s reload
2018/05/29 09:22:54 [notice] 351#351: signal process started
[email protected]:/# curl 127.0.0.1:80
Hello world!
C:\codebase\docker-php
+ nginx\
+ conf.d\
- site.conf
- Dockerfile
+ app\
- index.html
- hello-world.php
FROM nginx:latest
server {
listen 80;
server_name localhost;
root /var/www;
}
Hello World
docker rm -f $(docker ps -aq)
cd /c/codebase/docker-php/nginx
docker build -t docker-nginx-image .
[email protected] MINGW64 /c/codebase/docker-php
$ docker rm -f $(docker ps -aq)
15c6b8d8a2bf
[email protected] MINGW64 /c/codebase/docker-php
$ cd nginx
[email protected] MINGW64 /c/codebase/docker-php/nginx
$ docker build -t docker-nginx-image .
Sending build context to Docker daemon 3.584kB
Step 1/1 : FROM nginx:latest
---> ae513a47849c
Successfully built ae513a47849c
Successfully tagged docker-nginx-image:latest
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
docker run -di --name docker-nginx -p 8080:80 -v "C:\codebase\docker-php\nginx\conf.d":/etc/nginx/conf.d/ -v "C:\codebase\docker-php\app":/var/www docker-nginx-image
-p 8080:80 // maps port 8080 on the windows host to port 80 in the container
-v "C:\codebase\docker-php\nginx\conf.d":/etc/nginx/conf.d/ // mounts the conf.d folder on the host to the correct directory in the container
-v "C:\codebase\docker-php\app":/var/www // mounts the "code" directory in the correct place
docker stop docker-nginx
docker run -di --name php-fpm-test php:7.0-fpm
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c5d23b694563 php:7.0-fpm "docker-php-entrypoi…" 4 hours ago Up 4 hours 9000/tcp php-fpm-test
winpty docker exec -it php-fpm-test bash
[email protected]:/var/www/html# php-fpm -i | grep config
Configure Command => './configure' '--build=x86_64-linux-gnu' '--with-config-file-path=/usr/local/etc/php' '--with-config-file-scan-dir=/usr/local/etc/php/conf.d' '--enable-option-checking=fatal' '--disable-c
gi' '--with-mhash' '--enable-ftp' '--enable-mbstring' '--enable-mysqlnd' '--with-curl' '--with-libedit' '--with-openssl' '--with-zlib' '--with-libdir=lib/x86_64-linux-gnu' '--enable-fpm' '--with-fpm-user=www-da
ta' '--with-fpm-group=www-data' 'build_alias=x86_64-linux-gnu'
fpm.config => no value => no value
[...]
grep "include=" /usr/local/etc/php-fpm.conf
[email protected]:/var/www/html# grep "include=" /usr/local/etc/php-fpm.conf
include=etc/php-fpm.d/*.conf
grep -C 6 "include=" /usr/local/etc/php-fpm.conf
[email protected]:/var/www/html# grep -C 6 "include=" /usr/local/etc/php-fpm.conf
; Include one or more files. If glob(3) exists, it is used to include a bunch of
; files from a glob(3) pattern. This directive can be used everywhere in the
; file.
; Relative path can also be used. They will be prefixed by:
; - the global prefix if it's been set (-p argument)
; - /usr/local otherwise
include=etc/php-fpm.d/*.conf
cat /usr/local/etc/php-fpm.d/www.conf
[email protected]:/var/www/html# cat /usr/local/etc/php-fpm.d/www.conf
[...]
; The address on which to accept FastCGI requests.
; Valid syntaxes are:
; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on
; a specific port;
; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
; a specific port;
; 'port' - to listen on a TCP socket to all addresses
; (IPv6 and IPv4-mapped) on a specific port;
; '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = 127.0.0.1:9000
[...]
pecl install xdebug-2.6.0
docker-php-ext-enable xdebug
php-fpm -m | grep xdebug
C:\codebase\docker-php
+ php-fpm\
- Dockerfile
FROM php:7.0-fpm
RUN pecl install xdebug-2.6.0 \
&& docker-php-ext-enable xdebug
docker rm -f php-fpm-test
cd /c/codebase/docker-php/php-fpm
docker build -t docker-php-fpm-image .
docker network ls
[email protected] MINGW64 /
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
7019b0b37ba7 bridge bridge local
3820ad97cc92 host host local
03fecefbe8c9 none null loca
docker network create --driver bridge web-network
[email protected] MINGW64 /
$ docker network create --driver bridge web-network
20966495e04e9f9df9fd64fb6035a9e9bc3aa6d83186dcd23454e085a0d97648
[email protected] MINGW64 /
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
7019b0b37ba7 bridge bridge local
3820ad97cc92 host host local
03fecefbe8c9 none null local
20966495e04e web-network bridge local
docker start docker-nginx
docker network connect web-network docker-nginx
docker run -di --name docker-php-fpm -v "C:\codebase\docker-php\app":/var/www --network web-network docker-php-fpm-image
docker network inspect web-network
[email protected] MINGW64 /c/codebase/docker-php/php-fpm
$ docker network inspect web-network
[
{
"Name": "web-network",
"Id": "20966495e04e9f9df9fd64fb6035a9e9bc3aa6d83186dcd23454e085a0d97648",
"Created": "2018-05-30T06:39:44.3107066Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"3358e813423165880d59c8ebc2cb4c563ee8ad1d401595f8bfcf763ff5db8f4a": {
"Name": "docker-php-fpm",
"EndpointID": "d2f1d6285a0932817e1fb8839bef3a6d178f5306a2116307dba200038ea2a3a3",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"eaa5c05942788985e90a80fa000723286e9b4e7179d0f6f431c0f5109e012764": {
"Name": "docker-nginx",
"EndpointID": "274fa9a6868aff656078a72e19c05fb87e4e86b83aaf12be9b943890140a421d",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
winpty docker exec -ti docker-nginx bash
ping 172.18.0.3 -c 2
[email protected] MINGW64 /c/codebase/docker-php/php-fpm
$ winpty docker exec -ti docker-nginx bash
[email protected]:/# ping 172.18.0.3 -c 2
bash: ping: command not found
apt-get update && apt-get install iputils-ping -y
ping 172.18.0.3 -c 2
[email protected]:/# apt-get update && apt-get install iputils-ping -y
[email protected]:/# ping 172.18.0.3 -c 2
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.142 ms
64 bytes from 172.18.0.3: icmp_seq=2 ttl=64 time=0.162 ms
--- 172.18.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1071ms
rtt min/avg/max/mdev = 0.142/0.152/0.162/0.010 ms
ping docker-php-fpm -c 2
[email protected]:/# ping docker-php-fpm -c 2
PING docker-php-fpm (172.18.0.3) 56(84) bytes of data.
64 bytes from docker-php-fpm.web-network (172.18.0.3): icmp_seq=1 ttl=64 time=0.080 ms
64 bytes from docker-php-fpm.web-network (172.18.0.3): icmp_seq=2 ttl=64 time=0.131 ms
--- docker-php-fpm ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1045ms
rtt min/avg/max/mdev = 0.080/0.105/0.131/0.027 ms
server {
listen 80;
server_name localhost;
root /var/www;
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass docker-php-fpm:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
nginx -s reload
docker run -di --name docker-php -v "C:\codebase\docker-php\app":/var/www --network web-network docker-php-image
docker run -di --name docker-nginx -p 8080:80 -v "C:\codebase\docker-php\nginx\conf.d":/etc/nginx/conf.d/ -v "C:\codebase\docker-php\app":/var/www --network web-network docker-nginx-image
docker run -di --name docker-php-fpm -v "C:\codebase\docker-php\app":/var/www --network web-network docker-php-fpm-image
# tell docker what version of the docker-compose.yml we're using
version: '3'
# define the network
networks:
web-network:
# start the services section
services:
# define the name of our service
# corresponds to the "--name" parameter
docker-php-cli:
# define the directory where the build should happened,
# i.e. where the Dockerfile of the service is located
# all paths are relative to the location of docker-compose.yml
build:
context: ./php-cli
# reserve a tty - otherwise the container shuts down immediately
# corresponds to the "-i" flag
tty: true
# mount the app directory of the host to /var/www in the container
# corresponds to the "-v" option
volumes:
- ./app:/var/www
# connect to the network
# corresponds to the "--network" option
networks:
- web-network
docker rm -f $(docker ps -aq)
cd "C:\codebase\docker-php"
docker-compose up -d
[email protected] MINGW64 /c/codebase/docker-php
$ docker-compose up -d
Creating network "docker-php_web-network" with the default driver
Building docker-php-cli
Step 1/2 : FROM php:7.0-cli
---> da771ba4e565
Step 2/2 : RUN pecl install xdebug-2.6.0 && docker-php-ext-enable xdebug
---> Using cache
---> 12be27256b12
Successfully built 12be27256b12
Successfully tagged docker-php_docker-php-cli:latest
Image for service docker-php-cli was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating docker-php_docker-php-cli_1 ... done
[email protected] MINGW64 /c/codebase/docker-php
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
adf794f27315 docker-php_docker-php-cli "docker-php-entrypoi…" 3 minutes ago Up 2 minutes docker-php_docker-php-cli_1
winpty docker exec -it docker-php_docker-php-cli_1 bash
php /var/www/hello-world.php
[email protected]:/# php /var/www/hello-world.php
Hello World (php)
docker-compose down
[email protected] MINGW64 /c/codebase/docker-php
$ docker-compose down
Stopping docker-php_docker-php-cli_1 ... done
Removing docker-php_docker-php-cli_1 ... done
Removing network docker-php_web-network
# tell docker what version of the docker-compose.yml we're using
version: '3'
# define the network
networks:
web-network:
# start the services section
services:
# define the name of our service
# corresponds to the "--name" parameter
docker-php-cli:
# define the directory where the build should happened,
# i.e. where the Dockerfile of the service is located
# all paths are relative to the location of docker-compose.yml
build:
context: ./php-cli
# reserve a tty - otherwise the container shuts down immediately
# corresponds to the "-i" flag
tty: true
# mount the app directory of the host to /var/www in the container
# corresponds to the "-v" option
volumes:
- ./app:/var/www
# connect to the network
# corresponds to the "--network" option
networks:
- web-network
docker-nginx:
build:
context: ./nginx
# defines the port mapping
# corresponds to the "-p" flag
ports:
- "8080:80"
tty: true
volumes:
- ./app:/var/www
- ./nginx/conf.d:/etc/nginx/conf.d
networks:
- web-network
docker-php-fpm:
build:
context: ./php-fpm
tty: true
volumes:
- ./app:/var/www
networks:
- web-network
docker-compose up -d
[email protected] MINGW64 /c/codebase/docker-php
$ docker-compose up -d
Building docker-nginx
Step 1/1 : FROM nginx:latest
---> ae513a47849c
Successfully built ae513a47849c
Successfully tagged docker-php_docker-nginx:latest
Image for service docker-nginx was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Building docker-php-fpm
Step 1/2 : FROM php:7.0-fpm
---> a637000da5a3
Step 2/2 : RUN pecl install xdebug-2.6.0 && docker-php-ext-enable xdebug
---> Running in 4ec27516df54
downloading xdebug-2.6.0.tgz ...
Starting to download xdebug-2.6.0.tgz (283,644 bytes)
[...]
---> 120c8472b4f3
Successfully built 120c8472b4f3
Successfully tagged docker-php_docker-php-fpm:latest
Image for service docker-php-fpm was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating docker-php_docker-nginx_1 ... done
Creating docker-php_docker-php-cli_1 ... done
Creating docker-php_docker-php-fpm_1 ... done
C:\codebase\docker-php
+ nginx\
+ conf.d\
- site.conf
- Dockerfile
+ php-cli\
- Dockerfile
+ php-fpm\
- Dockerfile
+ app\
- index.html
- hello-world.html
- docker-compose.yml
How to install Nginx, PHP, PHP-FPM and MySQL under Windows with Cygwin
worker_processes 5;
events {
worker_connections 64; # VERY important. Do not leave 1024 there.
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /www;
index index.php index.html;
}
location ~ \.php$ {
root /www;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
}
FPM_SOURCES="fpm.c \
fpm_conf.c \
fpm_signals.c \
fpm_children.c \
fpm_worker_pool.c \
fpm_unix.c \
fpm_cleanup.c \
fpm_sockets.c \
fpm_stdio.c \
fpm_env.c \
fpm_events.c \
fpm_php.c \
fpm_process_ctl.c \
fpm_shm.c \
getaddrinfo.c \
xml_config.c \
zlog.c"
...
# default handling of .php
location ~ \.php {
# remove this line below, as we will not be using it
# try_files @heroku-fcgi @heroku-fcgi;
include fastcgi_params;
fastcgi_buffering off; # This must be here for WSL as of 11/28/2018
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info if_not_empty;
fastcgi_param SERVER_NAME $host;
fastcgi_pass 127.0.0.1:9000;
}
...
# listen = /tmp/heroku.fcgi.${PORT}.sock
listen = 127.0.0.1:9000
# log_level = warning
log_level = alert