I have a Docker environment containing numerous containers for web, api, mongodb, mongo express and nginx. My goal is to use Nginx to forward traffic onto the correct services. At the moment I have things working so that if i navigate to localhost/api the api appears with a message, same works for web. But if i navigate to localhost/mongo-express the service loads but the resources that mongo-express try to retrieve are all 404 not found:
I’m fairly new to Docker and completely new to Nginx and learning how it works. Here is my docker-compose file:
version: ‘3’
services:
# Web App Container
web:
build:
context: web
container_name: web
networks:
- mynetwork
# API Container
api:
build:
context: api
container_name: api
networks:
- mynetwork
# Nginx Container
nginx:
image: nginx:1.21-alpine
container_name: nginx
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
ports:
- "80:80"
- "403:403"
depends_on:
- web
- api
- mongodb
- mongo-express
networks:
- mynetwork
# Mongodb Container
mongodb:
image: mongo
container_name: mongodb
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
volumes:
- mongodb_data:/data/db
networks:
- mynetwork
# Mongo Express Container
mongo-express:
image: mongo-express
container_name: mongo-express
restart: always
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: admin
ME_CONFIG_MONGODB_ADMINPASSWORD: admin
ME_CONFIG_MONGODB_URL: mongodb://root:root@mongodb:27017/
depends_on:
- mongodb
networks:
- mynetwork
volumes:
mongodb_data:
networks:
mynetwork:
And here is my Nginx config file:
# nginx.conf
user nginx;
worker_processes auto;
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"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://web:8080/;
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;
}
location /api/ {
rewrite ^/api(/.*)$ $1 break;
proxy_pass http://api:3000/;
# Additional proxy settings for the API if needed
}
location /mongo-express/ {
rewrite ^/mongo-express(/.*)$ $1 break;
proxy_pass http://mongo-express:8081/;
# Additional proxy settings for Mongo Express if needed
}
location /mongodb/ {
rewrite ^/mongodb(/.*)$ $1 break;
proxy_pass http://mongodb:27017/;
# Additional proxy settings for MongoDB if needed
}
error_page 404 /404.html/;
location = /40x.html/ {
}
error_page 500 502 503 504 /50x.html/;
location = /50x.html/ {
}
}
}
I was expecting the files being retrieved with mongo-express to resolve no problem due to the reverse proxy. I’ve tried tweaking the nginx config and docker-compose file by altering the location, setting ME_CONFIG_SITE_BASEURL: mongo-express
in the docker-compose file, but nothing has worked for me.
I’m after not just a solution but for information to really help me understand why this is happening.
2
Answers
I've managed to fix this. Firstly my location urls and BASE url had trailing slashes. I had added trailing slashes due to many online guides stating that i must, even Mongo express documentation states it. Alongside this, removing rewrite ^/mongo-express(/.*)$ $1 break; from my nginx config also helped.
In your Nginx configuration, any URL that starts with
/mongo-express/
is forwarded to the mongo-express container. That container constructs its own URLs, using absolute URL paths, and it isn’t immediately aware of that path prefix, so it’s generating URLs that start with just e.g./public/...
, without that prefix.The Docker Hub
mongo-express
image has a specific configuration setting for thisSo you need to make sure to include this in that container’s
environment:
settings.The specific setting for this winds up being application- and framework-specific; there is not a universal answer that works for all containers. For your own application code, if it’s possible to use only a relative URL
<img src="assets/test.png">
this avoids the problem entirely, but with standard packaging tools like Webpack this can wind up being a little bit out of your control.