Instalamos docker.io, docker-compose y nginx:

root@debian:~# apt update && apt install docker.io docker-compose nginx

Creamos un fichero de nombre docker-compose.yaml en el que definimos los contenedores que existirán en el escenario, dos para la aplicación joomla y otros dos para nextcloud (base de datos y aplicación):

root@debian:~/proxyinverso# nano docker-compose.yaml

version: '3.1'

services:

  joomla:
    container_name: servidor_joomla
    image: joomla
    restart: always
    environment:
      JOOMLA_DB_HOST: dbjoomla
      JOOMLA_DB_USER: user_joomla
      JOOMLA_DB_PASSWORD: asdasd
      JOOMLA_DB_NAME: bd_joomla
    ports:
      - 8081:80

  dbjoomla:
    container_name: db_joomla
    image: mariadb
    restart: always
    environment:
      MYSQL_DATABASE: bd_joomla
      MYSQL_USER: user_joomla
      MYSQL_PASSWORD: asdasd
      MYSQL_ROOT_PASSWORD: asdasd

  nextcloud:
    container_name: servidor_nextcloud
    image: nextcloud
    restart: always
    environment:
      MYSQL_HOST: dbnextcloud
      MYSQL_USER: user_nextcloud
      MYSQL_PASSWORD: asdasd
      MYSQL_DATABASE: bd_nextcloud
    ports:
      - 8082:80

  dbnextcloud:
    container_name: db_nextcloud
    image: mariadb
    restart: always
    environment:
      MYSQL_DATABASE: bd_nextcloud
      MYSQL_USER: user_nextcloud
      MYSQL_PASSWORD: asdasd
      MYSQL_ROOT_PASSWORD: asdasd

Levantamos el escenario que acabamos de definir:

root@debian:~/proxyinverso# docker-compose up -d
Creating servidor_nextcloud ... done
Creating db_nextcloud       ... done
Creating db_joomla          ... done
Creating servidor_joomla    ... done

Comprobamos que las aplicaciones se están sirviendo en los puertos 8081 y 8082 respectivamente, sin hacer todavía ningún proxy inverso:

nginx1

nginx2

Una vez que son accesibles, es hora de generar dos nuevos VirtualHost en los que haremos proxy inverso desde dos nombres de dominio distintos para acceder a dichas aplicaciones (www.app1.org y www.app2.org):

root@debian:~/proxyinverso# cp /etc/nginx/sites-available/default /etc/nginx/sites-available/app1
root@debian:~/proxyinverso# cp /etc/nginx/sites-available/default /etc/nginx/sites-available/app2

root@debian:~/proxyinverso# nano /etc/nginx/sites-available/app1

server {
        listen 80;
        listen [::]:80;

        index index.html index.htm index.nginx-debian.html;

        server_name www.app1.org;

        location / {
                proxy_pass http://localhost:8081;
        }
}

root@debian:~/proxyinverso# nano /etc/nginx/sites-available/app2

server {
        listen 80;
        listen [::]:80;

        index index.html index.htm index.nginx-debian.html;

        server_name www.app2.org;

        location / {
                proxy_pass http://localhost:8082;
        }
}

Habilitamos dichos VirtualHost creando los correspondientes enlaces simbólicos:

root@debian:~/proxyinverso# ln -s /etc/nginx/sites-available/app1 /etc/nginx/sites-enabled/
root@debian:~/proxyinverso# ln -s /etc/nginx/sites-available/app2 /etc/nginx/sites-enabled/

root@debian:~/proxyinverso# systemctl reload nginx

Modificamos el fichero de resolución estática de nombres /etc/hosts para poder acceder a través de las cabeceras de las peticiones HTTP a los VirtualHost:

root@debian:~/proxyinverso# nano /etc/hosts

127.0.0.1       localhost
127.0.1.1       debian
127.0.0.1       www.app1.org
127.0.0.1       www.app2.org

# The following lines are desirable for IPv6 capable hosts

::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Si tratamos de acceder ahora a www.app1.org y www.app2.org, respectivamente, podremos apreciar lo siguiente:

nginx3

nginx4

Ahora, en lugar de utilizar dos VirtualHost (uno para cada aplicación), vamos a utilizar el mismo para ambas (www.servidor.org), diferenciándolas mediante la ruta que solicitamos tras la /, de manera que es hora de generar un nuevo VirtualHost con dichas características:

root@debian:~/proxyinverso# cp /etc/nginx/sites-available/app1 /etc/nginx/sites-available/servidor

root@debian:~/proxyinverso# nano /etc/nginx/sites-available/servidor

server {
        listen 80;
        listen [::]:80;

        index index.html index.htm index.nginx-debian.html;

        server_name www.servidor.org;

        location /app1/ {
                proxy_pass http://localhost:8081/;
        }

        location /app2/ {
                proxy_pass http://localhost:8082/;
        }
}

Habilitamos el VirtualHost creando el correspondiente enlace simbólico:

root@debian:~/proxyinverso# ln -s /etc/nginx/sites-available/servidor /etc/nginx/sites-enabled/

root@debian:~/proxyinverso# systemctl reload nginx

Modificamos el fichero de resolución estática de nombres /etc/hosts para poder acceder a través de las cabeceras de las peticiones HTTP al VirtualHost:

root@debian:~/proxyinverso# nano /etc/hosts

127.0.0.1       localhost
127.0.1.1       debian
127.0.0.1       www.app1.org
127.0.0.1       www.app2.org
127.0.0.1       www.servidor.org

# The following lines are desirable for IPv6 capable hosts

::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Si tratamos de acceder ahora a www.servidor.org/app1 y www.servidor.org/app2, respectivamente, podremos apreciar lo siguiente:

nginx5

nginx6

El proxy inverso ha funcionado correctamente, sin embargo, al estar haciendo uso de Docker y de rutas virtuales para acceder a las aplicaciones, el contenido estático no se está sirviendo como debería, ya que no es capaz de encontrarlo en la ruta especificada.

Existen determinadas aplicaciones que vienen preparadas para, mediante variables de entorno, indicarles desde dónde se pretende acceder a las mismas, y por tanto, permiten servir el contenido estático sin mayor complicación, pero este no es el caso.