Score:3

Docker NGINX reverse proxy does not work with one docker service, but works with another

vi flag

I'm trying to run a service Mautic (https://hub.docker.com/r/mautic/mautic) behind NGINX reverse proxy in Docker and can't figure out what I am doing wrong.

A little preamble to introduce my setup:

Since Mautic listens on port 80, and I already have NGINX container listening on port 80, so I have changed port 80 to 8081 in the following files inside Mautic image: /etc/apache2/ports.conf /etc/apache2/sites-available/000-default.conf

I have an NGINX container working as a reverse proxy at port 80. I have the following in my NGINX container's /etc/nginx/conf.d/default.conf:

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

    location / {
        proxy_pass http://site-client:4200;
    }

    location /api/ {
        proxy_pass http://site-api:8055/;
    }

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

I have port 8081 for Mautic exposed in docker-compose.yml file.

Now the problematic parts:

  • If I go to http://localhost:8081, the browser's URL changes to http://localhost:8081/s/dashboard and Mautic works fine.
  • However, if I go to http://localhost/mautic/, the browser's URL changes to http://localhost/s/dashboard, which takes me to my site-client service. Somehow the /mautic/ part of the URL got lost here.
  • So, if I go to http://localhost/mautic/s/dashboard, URL stays the same and Mautic loads with a bunch of ERR_ABORTED 404 errors (see the image of Chrome developer console below). Request headers for these files show that the request URL is still missing the /mautic/ part in them (even though I included it manually in the browser's URL), so it makes sense that those files can't be found because the request header URL is wrong. But why is it wrong?

enter image description here

How I tried to fix it:

I had the same problem with my site-api service, which is a Node.js based headless CMS (Directus), and I fixed it by setting its public URL to http://localhost/api in its config. If I go to http://localhost/api/, this service works fine. So I tried the same in Mautic's configuration and set its public URL from http://localhost:8081 to http://localhost/mautic. Now, if I go to http://localhost/mautic/, the browser's URL is set correctly to http://localhost/mautic/s/dashboard, but I still get the same result as can be seen in the image below.

This is my docker-compose.yml with regards to Mautic and NGINX:

reverse-proxy:
    container_name: nginx
    build: ./tools/nginx
    depends_on:
        - site-api
        - site-client
        - mautic
    networks:
        - site-api-network
    ports:
        - 80:80
    restart: always
mautic:
    image: mautic/mautic:v4
    build: ./tools/mautic
    container_name: mautic
    links:
        - mauticdb:mysql
    depends_on:
        - mauticdb
    ports:
        - 8081:8081
    volumes:
         - mautic_data:/var/www/html
    environment:
        - MAUTIC_DB_HOST=mauticdb
        - MYSQL_PORT_3306_TCP=3306
        - MAUTIC_DB_USER=root
        - MAUTIC_DB_PASSWORD=${MAUTIC_DB_PASSWORD}
        - MAUTIC_DB_NAME=${MAUTIC_DB_NAME}
        - MAUTIC_RUN_CRON_JOBS=true
        - MAUTIC_INSTALL_FORCE=true
        - MAUTIC_ADMIN_EMAIL=${MAUTIC_ADMIN_EMAIL}
        - MAUTIC_ADMIN_PASSWORD=${MAUTIC_ADMIN_PASSWORD}
        - MAUTIC_ADMIN_USERNAME=${MAUTIC_ADMIN_USERNAME}
        - MAUTIC_ADMIN_FIRSTNAME=${MAUTIC_ADMIN_FIRSTNAME}
        - MAUTIC_ADMIN_LASTNAME=${MAUTIC_ADMIN_LASTNAME}
        - MAUTIC_TRUSTED_PROXIES=["0.0.0.0/0"]
    networks:
        - site-api-network

networks:
    site-api-network:
        driver: bridge

volumes:
    mautic_db_data:
        driver: local
    mautic_data:
        driver: local

This is reverse-proxy Dockerfile:

FROM nginx:alpine

RUN rm /etc/nginx/conf.d/*

COPY ./default.conf /etc/nginx/conf.d/

EXPOSE 80

CMD [ "nginx", "-g", "daemon off;" ]

This is mautic Dockerfile:

FROM mautic/mautic:v4

RUN rm /etc/apache2/ports.conf
RUN rm /etc/apache2/sites-available/000-default.conf

COPY ./ports.conf /etc/apache2/
COPY ./000-default.conf /etc/apache2/sites-available

EXPOSE 8081

Mautic image ports.conf file

Listen 8081

<IfModule ssl_module>
    Listen 443
</IfModule>

<IfModule mod_gnutls.c>
    Listen 443
</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Mautic image 000-default.conf file

<VirtualHost *:8081>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Score:2
vi flag

I believe this is a problem with my backend service Mautic and not NGINX. What's happening and some solutions can be gleaned from here: https://serverfault.com/a/797006

I went with a solution where I point a subdomain to my service instead of it being a subpath of a domain.

So instead of trying to access it via example.com/mautic/:

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

I create a separate server block with server_name set to mautic.example.com and my location block inside it is:

location / {
    proxy_pass http://mautic:8081/;
}
cn flag
with your experience with mautic on docker, do you recommend it for production use case?
Polynook avatar
vi flag
Yes, once I set it up right it has been running well for me.
cn flag
Thanks, Can you share more details of your setup somehow for mautic with nginx. And if possible share docker-compose and guideline on how to make it work in best way
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.