In this example we are going to set up two dockerised PHP-FPM and Nginx applications ("frontend" and "backend") and allow them to communicate each other over the same network. There are three critical points here:



Structure


As you can see below, the structure has been kept the same for simplicity.


Frontend


$ tree
.
├── docker
│ ├── .env
│   ├── docker-compose.yml
│   ├── nginx
│   │   ├── app.conf
│   │   └── Dockerfile
│   └── php
│   ├── Dockerfile
│   └── www.conf
├── index.html
└── index.php

Backend


$ tree
.
├── docker
│ ├── .env
│ ├── docker-compose.yml
│ ├── nginx
│ │ ├── app.conf
│ │ └── Dockerfile
│ └── php
│ ├── Dockerfile
│ └── www.conf
├── index.html
└── index.php

Frontend files


index.html


Success: HTML page (Frontend)

index.php


echo 'Success: PHP page (Frontend)'.PHP_EOL;

//echo file_get_contents('http://backend_nginx');
//echo file_get_contents('http://backend_nginx/index.php').PHP_EOL;

docker/.env


COMPOSE_PROJECT_NAME=inanzzz
REPOSITORY_NAME=frontend
IMAGE_TAG=latest

docker/docker-compose.yml


version: "3"

services:

frontend_php:
build:
context: ./php
image: "${COMPOSE_PROJECT_NAME}/${REPOSITORY_NAME}_php:${IMAGE_TAG}"
container_name: "${REPOSITORY_NAME}_php"
hostname: "${REPOSITORY_NAME}-php"
volumes:
- ..:/app:cached
- ./php/www.conf:/usr/local/etc/php-fpm.d/www.conf:cached
working_dir: /app

frontend_nginx:
build:
context: ./nginx
image: "${COMPOSE_PROJECT_NAME}/${REPOSITORY_NAME}_nginx:${IMAGE_TAG}"
container_name: "${REPOSITORY_NAME}_nginx"
hostname: "${REPOSITORY_NAME}-nginx"
ports:
- "8081:80"
volumes:
- ..:/app:cached
- ./nginx/app.conf:/etc/nginx/conf.d/default.conf:cached
depends_on:
- frontend_php

docker/php/www.conf


[www]

user = www-data
group = www-data

listen = frontend_nginx:9000

pm = dynamic
pm.max_children = 40
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 500

docker/php/Dockerfile


FROM php:7.2-fpm-alpine

ENV PS1="\u@\h:\w\\$ "

RUN apk add --no-cache bash

CMD ["php-fpm"]

docker/nginx/app.conf


server {
listen 80 default_server;

server_name frontend.com www.frontend.com;

root /app;

location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass frontend_php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}

error_log /var/log/nginx/app_error.log;
access_log /var/log/nginx/app_access.log;
}

docker/nginx/Dockerfile


FROM nginx:1.15-alpine

ENV PS1="\u@\h:\w\\$ "

RUN apk add --no-cache bash

Backend files


index.html


Success: HTML page (Backend)

index.php


echo 'Success: PHP page (Backend)'.PHP_EOL;

//echo file_get_contents('http://frontend_nginx');
//echo file_get_contents('http://frontend_nginx/index.php').PHP_EOL;

docker/.env


COMPOSE_PROJECT_NAME=inanzzz
REPOSITORY_NAME=backend
IMAGE_TAG=latest

docker/docker-compose.yml


version: "3"

services:

backend_php:
build:
context: ./php
image: "${COMPOSE_PROJECT_NAME}/${REPOSITORY_NAME}_php:${IMAGE_TAG}"
container_name: "${REPOSITORY_NAME}_php"
hostname: "${REPOSITORY_NAME}-php"
volumes:
- ..:/app:cached
- ./php/www.conf:/usr/local/etc/php-fpm.d/www.conf:cached
working_dir: /app

backend_nginx:
build:
context: ./nginx
image: "${COMPOSE_PROJECT_NAME}/${REPOSITORY_NAME}_nginx:${IMAGE_TAG}"
container_name: "${REPOSITORY_NAME}_nginx"
hostname: "${REPOSITORY_NAME}-nginx"
ports:
- "8081:80"
volumes:
- ..:/app:cached
- ./nginx/app.conf:/etc/nginx/conf.d/default.conf:cached
depends_on:
- backend_php

docker/php/www.conf


[www]

user = www-data
group = www-data

listen = backend_nginx:9000

pm = dynamic
pm.max_children = 40
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 500

docker/php/Dockerfile


FROM php:7.2-fpm-alpine

ENV PS1="\u@\h:\w\\$ "

RUN apk add --no-cache bash

CMD ["php-fpm"]

docker/nginx/app.conf


server {
listen 80 default_server;

server_name backend.com www.backend.com;

root /app;

location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass backend_php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}

error_log /var/log/nginx/app_error.log;
access_log /var/log/nginx/app_access.log;
}

docker/nginx/Dockerfile


FROM nginx:1.15-alpine

ENV PS1="\u@\h:\w\\$ "

RUN apk add --no-cache bash

Build


Frontend


frontend/docker$ docker-compose up -d
Creating network "inanzzz_default" with the default driver
Building frontend_php
Successfully tagged inanzzz/frontend_php:latest
Building frontend_nginx
Successfully tagged inanzzz/frontend_nginx:latest
Creating frontend_php ... done
Creating frontend_nginx ... done

Backend


backend/docker$ docker-compose up -d
Creating network "inanzzz_default" with the default driver
Building backend_php
Successfully tagged inanzzz/backend_php:latest
Building backend_nginx
Successfully tagged inanzzz/backend_nginx:latest
Creating backend_php ... done
Creating backend_nginx ... done

Verify


Images


$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
inanzzz/backend_nginx latest e96f12e76433 About a minute ago 21.6MB
inanzzz/frontend_nginx latest e96f12e76433 About a minute ago 21.6MB
inanzzz/backend_php latest cec808e6aa5c About a minute ago 79.5MB
inanzzz/frontend_php latest cec808e6aa5c About a minute ago 79.5MB
nginx 1.15-alpine 63356c558c79 10 days ago 17.8MB
php 7.2-fpm-alpine 9966b8ea0bdc 3 weeks ago 78.1MB

Containers


$ docker ps
CONTAINER ID IMAGE COMMAND PORTS NAMES
fdd64ac7a7cb inanzzz/backend_nginx:latest "nginx -g 'daemon of…" 0.0.0.0:8082->80/tcp backend_nginx
45e99c7b3e26 inanzzz/backend_php:latest "docker-php-entrypoi…" 9000/tcp backend_php
0eacaa22ff8f inanzzz/frontend_nginx:latest "nginx -g 'daemon of…" 0.0.0.0:8081->80/tcp frontend_nginx
3d2e0c42e47f inanzzz/frontend_php:latest "docker-php-entrypoi…" 9000/tcp frontend_php

Network


$ docker network ls
NETWORK ID NAME DRIVER SCOPE
b16749701349 inanzzz_default bridge local

$ docker inspect inanzzz_default 
[
{
"Name": "inanzzz_default",
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "192.168.112.0/20",
"Gateway": "192.168.112.1"
}
]
},
"Containers": {
"0eacaa22ff8fad197b94acdfd6abcdab25a782065fc8551996b008603b380dc3": {
"Name": "frontend_nginx",
"IPv4Address": "192.168.112.3/20"
},
"3d2e0c42e47fda99ada7f53414130fff35b0f4e708d8ce83e55d564ef3e4f81e": {
"Name": "frontend_php",
"IPv4Address": "192.168.112.2/20"
},
"45e99c7b3e26669f6c50479ba50982a9b1e9aa230d03595ebd44d251734c5272": {
"Name": "backend_php",
"IPv4Address": "192.168.112.4/20"
},
"fdd64ac7a7cbcce6be75f0f3da3746496aac09ceb553279fd6485c5cc9ade1a5": {
"Name": "backend_nginx",
"IPv4Address": "192.168.112.5/20"
}
},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "inanzzz"
}
}
]

Container bash prompts


$ docker exec -it backend_php bash
root@backend-php:/app#

$ docker exec -it backend_nginx bash
root@backend-nginx:/#

$ docker exec -it frontend_php bash
root@frontend-php:/app#

$ docker exec -it frontend_nginx bash
root@frontend-nginx:/#

Test


Static frontend call.


$ curl http://localhost:8081 # or /index.html
Success: HTML page (Frontend)

Static backend call.


$ curl http://localhost:8082 # or /index.html
Success: HTML page (Backend)

Frontend consuming backend.


$ curl http://localhost:8081/index.php
Success: HTML page (Backend)
Success: PHP page (Backend)

Backend consuming frontend.


$ curl http://localhost:8082/index.php
Success: HTML page (Frontend)
Success: PHP page (Frontend)