I need to upgrade some very old PHP sites still running PHP 5.6, and since I have other sites running PHP 7 and 8, I figured I'd leverage Docker for this.
I am using the default Docker PHP-FPM and Nginx images from hub.docker.com.
I am running this on Docker for Windows with WSL2 under Ubuntu 20. In case you are also on Windows 10, here is the best guide I could find on setting up WSL2 with Docker for PHP Development to work flawlessly.
Dockerfile
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
COPY site1.conf /etc/nginx/conf.d/site1.conf
COPY site2.conf /etc/nginx/conf.d/site2.conf
nginx.conf
This is the default one in the nginx official image at /etc/nginx/nginx.conf, except for 2 lines where noted.
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;
# added this once some other SO posts suggested it for multiple server_name directives
server_names_hash_bucket_size 64;
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;
# had to add this, the default nginx.conf in the docker image doesn't include sites-enabled
include /etc/nginx/sites-enabled/*.conf;
}
site1.conf
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example1.com www.example1.com;
root /var/www/example1.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
site2.conf
server {
listen 80;
listen [::]:80;
server_name example2.com www.example2.com;
root /var/www/example2.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Directory Structure
/home/me/nginx-test/Dockerfile
/home/me/nginx-test/site1/index.html
/home/me/nginx-test/site1/test.php
/home/me/nginx-test/site2/index.html
/home/me/nginx-test/site2/test.php
Put <h1>Site1</h1> into site1/index.html and <h1>Site2</h1> into site2/index.html respectively so it's obvious we're loading the right one.
/etc/hosts
127.0.0.1 example1.com
127.0.0.1 example2.com
Here is my method for standing this up and testing everything.
$ cd ~/nginx-test
$ docker pull nginx
$ docker pull php:5.6.40-fpm
$ docker build -t web:test .
$ docker run --name php -v /home/me/nginx-test/site1:/var/www/example1 -v /home/me/nginx-test/site2:/var/www/example2 -d php:5.6.40-fpm
$ docker run --name test -p 80:80 -v /home/me/nginx-test/site1:/var/www/example1 -v /home/me/nginx-test/site2:/var/www/example2 --link php:php -d web:test
Notice you have to launch the php container first, and name it php so that when you stand up the web container and --link it to the php container, it can find it. This is also required given the fastcgi_pass php:9000 directive in both nginx config files.
docker ps -a
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
37edb342d7b2 web:test "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp test
45ac2fb3d1d4 php:5.6.40-fpm "docker-php-entrypoi…" 10 seconds ago Up 9 seconds 9000/tcp php
Now, when I browse to http://example1.com and http://example2.com I the respective index.html pages.
docker logs test --follow
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
172.17.0.1 - - [23/Mar/2021:22:29:19 +0000] "GET / HTTP/1.1" 200 135 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" "-"
Now to make it a bit easier to grep logs, let's add the $server_name to nginx.conf log_format. More details on the offical list of nginx variables.
nginx.conf edit, line 16
log_format main '$remote_addr - $remote_user [$time_local] "$server_name $request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
Teardown and rebuild
$ docker stop test && docker rm test && docker stop php && docker rm php
$ docker build -t web:test .
$ docker run --name php -v /home/me/nginx-test/site1:/var/www/example1 -v /home/me/nginx-test/site2:/var/www/example2 -d php:5.6.40-fpm
$ docker run --name test -p 80:80 -v /home/me/nginx-test/site1:/var/www/example1 -v /home/me/nginx-test/site2:/var/www/example2 --link php:php -d web:test
$ docker logs test --follow
172.17.0.1 - - [23/Mar/2021:22:41:25 +0000] "example2.com GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" "-"
172.17.0.1 - - [23/Mar/2021:22:41:36 +0000] "example1.com GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" "-"
172.17.0.1 - - [23/Mar/2021:22:41:41 +0000] "example1.com GET /test.php HTTP/1.1" 200 85924 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" "-"
Here is some more diagnostic details.
did volumes mount?
$ docker exec -it test bash
root#37edb342d7b2:/# cd /var/www/example1
root#37edb342d7b2:/var/www/example1# ls
index.html test.php
yes.
in both containers?
$ docker exec -it php bash
root#45ac2fb3d1d4:/var/www/html# ls -la /var/www/example2
total 16
drwxr-xr-x 2 1000 1000 4096 Mar 23 21:47 .
drwxr-xr-x 1 root root 4096 Mar 23 22:21 ..
-rw-r--r-- 1 1000 1000 135 Mar 23 21:37 index.html
-rw-r--r-- 1 1000 1000 31 Mar 23 20:33 test.php
In the context of asking some questions, I figured everything out, so I decided to keep this up as a guide for future readers.
Read the guide above.
Related
I'm trying to configure nginx config in Docker but when I start "sudo docker-compose up -d" and try to connect to "http://localhost:8098/" I see: File not found. and logs like:
docker-infrastructure_php-fpm_1 | 172.19.0.3 - 03/Mar/2022:21:35:35 +0000 "GET /index.php" 404
docker-infrastructure_nginx_1 | 172.19.0.1 - - [03/Mar/2022:21:35:35 +0000] "GET / HTTP/1.1" 404 27 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36" "-"`
There are my:
nginx.conf
server {
listen 80;
server_name dgtips-backend-local;
root /home/sergey/PhpstormProjects/dgtips-backend/public;
index index.php;
location / {
try_files $uri /$uri /index.php?$query_string;
}
location ~ [^/]\.php(/|$) {
fastcgi_param SCRIPT_FILENAME /home/sergey/PhpstormProjects/dgtips-backend$fastcgi_script_name;
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
}
}
nginx.Dockerfile
FROM nginx
ADD docker/nginx/nginx.conf /etc/nginx/conf.d/default.conf
WORKDIR /home/sergey/PhpstormProjects/dgtips-backend/public
docker-compose.yml
version: "3.3"
services:
nginx:
build:
context: .
dockerfile: docker/nginx/nginx.Dockerfile
ports:
- 8098:80
volumes:
- ./:/home/sergey/PhpstormProjects/dgtips-backend
links:
- php-fpm
php-fpm:
build:
context: .
dockerfile: docker/php-fpm/fpm.Dockerfile
volumes:
- ./:/home/sergey/PhpstormProjects/dgtips-backend
And finally
fpm.Dockerfile
FROM php:7.4-fpm
RUN apt-get update \
&& docker-php-ext-install pdo pdo_mysql
I'm completely sure that I have correct paths to my (local) project and to my index.php file
I am trying to create a docker environment with php-fpm and nginx using docker-compose. I am trying to avoid using the images available for learning purpose.
i have been to stich most of it together but failing at the time when it matters the most, accessing the site.
here is what i have done so far:
created a Dockerfile for nginx
FROM nginx:latest
EXPOSE 80
COPY /etc/nginx.conf /etc/nginx/conf.d/default.conf
COPY . /var/www/wordpress
the nginx.conf is as follows:
server {
listen 80;
listen [::]:80;
server_name _;
#access_log /var/log/nginx/host.access.log main;
location / {
root /var/www/wordpress;
index index.html index.htm index.php;
}
#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 /var/www/wordpress;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
root /var/www/wordpress;
fastcgi_pass php: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;
}
}
PHP-dockerfile is as follows:
FROM php:8.1.1-fpm-buster
RUN echo "$PHP_INI_DIR"
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY /etc/fpm-www.conf /usr/local/etc/php-fpm.d/www.conf
EXPOSE 9000
www.conf is as follows
[global]
daemonize = no
[www]
user = www-data
group = www-data
access.log = /dev/stdout
slowlog = /dev/stdout
listen = 9000
pm = dynamic
pm.max_children = 100
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.status_path = /status
ping.path = /fpm-ping
all this seems to be working file for now, that means:
1- the images are built and the containers are started
2- accessing localhost- I get welcome to nginx
but when i try to access index.php (copied to /var/www/wordpress and is available in the container) I get the following error:
nginx_1 | 172.23.0.1 - - [24/Dec/2021:12:17:49 +0000] "GET /index.php HTTP/1.1" 404 27 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62" "-"
I have tried multiple options and posts available but my knowledge of nginx-php-docker-compose seems to be missing something.
I am certain it is something fundamental which I have overlooked.
Kindly suggest
I know there's a ton of posts regarding 502 Bad Gateway, but I haven't been able to solve this problem. I'm using Docker Compose to create separate containers for Nginx and PHP-FPM.
Error I get loading PHP files in the browser (HTML files render fine):
tc-web | 2018/01/22 19:22:46 [error] 5#5: *4 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: localhost, request: "GET /info.php HTTP/1.1", upstream: "fastcgi://172.18.0.2:9000", host: "localhost:8080"
tc-web | 172.18.0.1 - - [22/Jan/2018:19:22:46 +0000] "GET /info.php HTTP/1.1" 502 575 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
I've tried tweaking the various configs, using Unix socket, etc., for hours, and I still get 502 errors with PHP files. Can you spot what's wrong?
Here are all required files..
docker-composer.yml:
version: '3'
services:
web:
build:
context: ./docker/nginx
image: tc-web:0.1.0
container_name: tc-web
volumes:
# test files
- ./temp.html:/var/www/html/index.html
- ./temp.php:/var/www/html/info.php
ports:
- 8080:80
depends_on:
- php-fpm
php-fpm:
build:
context: ./docker/php-fpm
image: tc-php:0.1.0
container_name: tc-php
volumes:
- ./temp.html:/var/www/html/index.html
- ./temp.php:/var/www/html/info.php
docker/nginx/Dockerfile:
FROM nginx:1.13.8
# Install programs
RUN apt-get update
RUN apt-get install -y nano && \
apt-get install -y git && \
apt-get install -y procps
RUN mkdir -p /var/www/html
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
docker/nginx/nginx.conf:
user www-data;
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"';
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/default.conf;
}
docker/nginx/default.conf:
server {
listen 80;
server_name localhost;
root /var/www/html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~* \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
docker/php-fpm/Dockerfile:
FROM php:7.0-fpm
# Install programs
RUN apt-get update
RUN apt-get install -y nano && \
apt-get install -y procps
RUN mkdir -p /var/www/html
COPY php-fpm.conf /usr/local/etc/php-fpm.conf
COPY www.conf /usr/local/etc/php-fpm.d/www.conf
docker/php-fpm/php-fpm.conf:
[global]
include=etc/php-fpm.d/www.conf
docker/php-fpm/www.conf:
[global]
;daemonize = no
; if we send this to /proc/self/fd/1, it never appears
error_log = /proc/self/fd/2
[www]
user = www-data
group = www-data
listen = 127.0.0.1:9000
;listen = /var/run/php-fpm/php7-fpm.sock
;listen.owner = www-data
;listen.group = www-data
;listen.mode = 0660
access.log = /proc/self/fd/2
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
; Ensure worker stdout and stderr are sent to the main error log.
catch_workers_output = yes
Problem could be in the www.conf file.
You are listening to 127.0.0.1:9000 but this way the service won't be reachable outside the container.
Try binding to 0.0.0.0:9000:
listen = 0.0.0.0:9000
This may sound very obvious, but another common issue would be that php-fpm is not installed. This can happen even though systemctl might say that the service is running but it's not really running anything. In my case, I had also installed PHP 8 with it's own fpm package, so if you have multiple php installations, there could have been a mix up with which fpm version you installed.
I'm fiddling with Docker, trying to setup a Docker composition with Nginx and PHP-FPM running on separate Alpine containers. My setup is available on GitHub at https://github.com/sparkbuzz/lemp_docker, my docker-compose.yml looks as follows:
version: '3'
services:
alpine_nginx:
build: ./nginx
container_name: alpine_nginx
links:
- alpine_php
ports:
- "80:80"
alpine_php:
build: ./php
container_name: alpine_php
ports:
- "9000:9000"
I am able to build the images successfully, and when I visit localhost in my browser, I can see the index.html served by Nginx. However, when trying to access phpinfo.php, I get a 502 - Bad Gateway error
I can docker exec -it ... /bin/ash into both the running instances, and it seems the services are running happily, however, it's clear PHP-FPM on port 9000 is never even hit.
Here's some feedback from my console:
Recreating alpine_php ...
Recreating alpine_php ... done
Recreating alpine_nginx ...
Recreating alpine_nginx ... done
Attaching to alpine_php, alpine_nginx
alpine_php | [06-Nov-2017 21:46:39] NOTICE: fpm is running, pid 1
alpine_php | [06-Nov-2017 21:46:39] NOTICE: ready to handle connections
alpine_nginx | 2017/11/06 21:46:46 [error] 6#6: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: localhost, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://172.20.0.2:9000", host: "localhost"
alpine_nginx | 172.20.0.1 - - [06/Nov/2017:21:46:46 +0000] "GET /index.php HTTP/1.1" 502 568 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36" "-"```
I'm so close, but not sure why Nginx isn't happy with the PHP upstream. Nginx config is as follows:
server {
listen 80;
server_name localhost;
location / {
root /var/www/localhost/htdocs/;
index index.html;
}
location ~* \.php$ {
fastcgi_index index.php;
fastcgi_pass alpine_php:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
}
How do I get Nginx talking to PHP FPM?
You are listen 127.0.0.1 in your php-fpm config.
Add this to php/Dockerfile
RUN sed -i 's/127.0.0.1:9000/0.0.0.0:9000/g' /etc/php7/php-fpm.d/www.conf
I'd like to setup an completely LNMP environment with docker on a machine. But there is something wrong with separated php-fpm & nginx container.
What I'v done is :
pull images from docker.io :
docker pull php:7.1-fpm
docker pull nginx
run with image :
docker run -d --name php-fpm -v /data/Docker/php-fpm/configs/:/usr/local/etc/php-fpm.d -v /data/Docker/nginx/html:/var/www/html php:7.1-fpm
docker run -d --name nginx -v /data/Docker/nginx/configs/:/etc/nginx -v /data/Docker/nginx/html:/var/www/html -p 80:80 --link php-fpm nginx
All directories & files are 755 privileges.
Config files r below :
nginx.conf
server {
listen 80 default_server;
server_name SkyEyeLab;
root /var/www/html;
fastcgi_read_timeout 90;
location ~ \.php {
fastcgi_pass php-fpm:9000;
}
}
And php-fpm.conf(some of important config sections):
listen 0.0.0.0:9000
listen.allowed_clients = any
Then I checked the environment of nginx & php-fpm :
[root#w-Lab01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6faf4a4b4f7e nginx "nginx -g 'daemon off" 19 minutes ago Up 19 minutes 0.0.0.0:80->80/tcp, 443/tcp nginx
9a6caff831d3 php:7.1-fpm "php-fpm" 20 minutes ago Up 20 minutes 9000/tcp php-fpm
[root#w-Lab01 ~]# docker exec 6faf4a4b4f7e ping -c3 php-fpm
PING php-fpm (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.081 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.018 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.041 ms
--- php-fpm ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.018/0.047/0.081/0.026 ms
[root#w-Lab01 ~]# docker exec 9a6caff831d3 ss -apn
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
tcp LISTEN 0 128 *:9000 *:* users:(("php-fpm",pid=1,fd=7))
Everything seems fine. Then I create a.php under /data/Docker/nginx/html(which is mouted to nginx's /var/www/html directory) with following content :
<?php
phpinfo();
?>
Then access http://localhost:80/a.php in web browser.
But I only got an empty page, I checked the access.log of nginx :
[root#w-Lab01 ~]# docker logs 6faf4a4b4f7e
220.181.171.120 - - [11/Oct/2016:10:25:11 +0000] "GET /a.php HTTP/1.1" 200 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0"
220.181.171.120 - - [11/Oct/2016:10:25:12 +0000] "GET /a.php HTTP/1.1" 200 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0"
220.181.171.120 - - [11/Oct/2016:10:31:58 +0000] "GET /a.php HTTP/1.1" 200 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0"
220.181.171.120 - - [11/Oct/2016:10:31:59 +0000] "GET /a.php HTTP/1.1" 200 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0"
It seems a.php is correctly parsed & executed. But why I can not see phpinfo() result in web browser ?
well, after I changed nginx's config file :
server {
listen 80 default_server;
server_name SkyEyeLab;
root /var/www/html;
fastcgi_read_timeout 90;
location ~ \.php {
fastcgi_pass php-fpm:9000;
}
}
to
server {
listen 80 default_server;
server_name SkyEyeLab;
root /var/www/html;
fastcgi_read_timeout 90;
location ~ \.php {
fastcgi_pass php-fpm:9000;
include fastcgi.conf;
}
}
erverything goes fine.
fastcgi.conf is environment config file. you can check under your nginx's config directory(usually /etc/nginx), and see if there is fastcgi.conf or fastcgi_param in it.
maybe, if you want to use the name "php-fpm" in the nginx conf, you need to link the container like this:
docker run -d --name php-fpm -v /data/Docker/php-fpm/configs/:/usr/local/etc/php-fpm.d -v /data/Docker/nginx/html:/var/www/html php:7.1-fpm
and after:
docker run -d --name nginx --link php-fpm:php-fpm -v /data/Docker/nginx/configs/:/etc/nginx -v /data/Docker/nginx/html:/var/www/html -p 80:80 --link php-fpm nginx