The only way I can get it to work if I use a bind mount volume that connects both of the containers totally, when I remove it it doesnt work. Without the shared volume between frontend and backend they both can't communicate. They are also both on the same network.
UPDATED with no volumes, dockerfiles, nginx config, sample call and error message (2nd update added proxy from nginx to php-fpm which is on port 9000)
Compose:
services:
web:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
depends_on:
- api
links:
- api
develop:
watch:
- path: .
target: /var/www/html
action: sync
api:
build:
context: ./libs/php
dockerfile: Dockerfile
ports:
- "9000:9000"
Dockerfiles
FROM nginxinc/nginx-unprivileged
WORKDIR /var/www/html
COPY --chown=nginx:nginx ./conf.d/ /etc/nginx/conf.d/
COPY --chown=nginx:nginx . /var/www/html
FROM php:8.2-fpm
WORKDIR /var/www/html
ARG UID=101
ARG GID=101
//just updating user and group to same as nginx user on frontend
RUN groupadd -g "${GID}" php-fpm \
&& useradd --no-log-init -u "${UID}" -g "${GID}" php-fpm \
&& chown php-fpm:php-fpm -R /var/www/html
USER php-fpm
COPY --chown=php-fpm:php-fpm . .
Request made from jquery script:
$("#submit_1").on("click", () => {
const inputVal = $("#input_1").val();
$.ajax({
url: "/api/",
dataType: "json",
data: {
searchTerm: inputVal,
},
method: "POST",
success: (results) => console.log(results),
error: (obj, details) => console.log(obj, details),
});
}
});
Nginx default.conf
server {
index index.php index.html;
server_name api;
error_log /var/log/nginx/error.log debug;
root /usr/share/nginx/html;
index index.html index.htm;
location /api {
proxy_pass http://api:9000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Enable CORS headers
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "POST, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type";
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass api:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
├── docker-compose.yaml
├── index.html
└── libs/
├── php/
│ ├── geocodeBackend.php # PHP files served by php-fpm
│ └── other_php_files.php
├── js/
│ └── jquery.js # JS, Css and html served by nginx
└── css/
└── styles.css
Error:
web-1 | 2024/11/03 00:58:59 [error] 30#30: *5 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 172.18.0.1, server: api, request: "POST /api HTTP/1.1", upstream: "http://172.18.0.2:9000/", host: "localhost", referrer: "http://localhost/"
web-1 | 172.18.0.1 - - [03/Nov/2024:00:58:59 +0000] "POST /api HTTP/1.1" 502 157 "http://localhost/" "Mozilla/5.0 (X11; Linux x86_64; rv:132.0) Gecko/20100101 Firefox/132.0" "-"
PHP-FPM container has its file
root@124743cd5330:/var/www/html# ls
Dockerfile geocodeBackend.php
NGINX has its
root@b4eba721669f:/usr/share/nginx/html# ls
50x.html compose.dev.yaml favicon.ico libs
README.Docker.md conf.d index.html root
Thanks to changing the nginx default.conf files correctly and updating the js script url to /api/ (extra slash at the end). Below is everything I changed!
default.conf
server {
listen 8080;
index index.php index.html;
server_name api;
root /var/www/html/;
location /api/ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME geocodeBackend.php;
fastcgi_pass api:9000;
}
}
script.js
$.ajax({
url: "/api/",
dataType: "json",
data: {
searchTerm: inputVal,
},
method: "POST",
But after trying for hours the only option is to put it all into the same exact folder in volume which defeats the purpose of containerization.
This is due to the try_files $uri =404;
directive in your nginx config. You don't need to use it at all. Here is documentation on that directive.
web-1 | 2024/11/03 00:58:59 [error] 30#30: *5 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 172.18.0.1, server: api, request: "POST /api HTTP/1.1", upstream: "http://172.18.0.2:9000/", host: "localhost", referrer: "http://localhost/"
This is because you are trying to communicate with your PHP-FPM backend via HTTP protocol while it is expects FastCGI one.
As far as I understand, if you want to pass all /api...
requests to the geocodeBackend.php
PHP script, you need something like
location /api {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /full/path/to/geocodeBackend.php;
fastcgi_pass api:9000;
}
(BTW, I recommend to use /api/...
rather than /api...
).
Some PHP scripts may additionally rely on some other FastCGI variables like SCRIPT_NAME
, DOCUMENT_URI
or DOCUMENT_ROOT
; see the last part of this answer and comment below for more information.