Nginx Docker Gunicorn – How to Remove Port Number from URL

djangodockergunicornnginxreverse-proxy

I have a django app that's also using gunicorn and nginx. I'm able to access my site using http://url:8000, but I don't know how to correctly configure it so I don't have to use the port number in the url at all, ie http://url would by the same as http://url:8000 .

Here's my docker-compose.yml:

version: '3.2'

services:
  immweb:
    restart: always
    build: .
    expose:
      - "8000"
    command: gunicorn smn_imm.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - type: volume
        source: smnvol
        target: /etc/smn_imm/smnvol
    ports:
      - "8000:8000"

  nginx:
    build: nginx
    depends_on:
      - immweb

nginx.conf:

upstream smn_imm {
    server web:8000;
}

server {

    listen 80;
    server_name smn-imm;

    location / {
        proxy_pass http://smn_imm;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        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_redirect off;
    }

}

Best Answer

You haven't opened any ports for the nginx service. It sounds like when you're hitting http://url:8000 you're actually hitting the gunicorn container directly.

In your nginx config I would remove the upstream block completely, and just specify the gunicorn port in your proxy_pass line. However this should point to the DNS name of the gunicorn container (immweb as specified). See this guide for more info on why.

server {
    listen 80;
    server_name smn-imm;
    location / {
        proxy_pass http://immweb:8000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        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_redirect off;
    }
}

You then need to update the compose file:

version: '3.2'

services:
  immweb:
    restart: always
    build: .
    command: gunicorn smn_imm.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - type: volume
        source: smnvol
        target: /etc/smn_imm/smnvol

  nginx:
    build: nginx
    depends_on:
      - immweb
    ports:
     - "80:80"

Notice I've added an external port mapping for nginx but removed the ports and expose lines for immweb. See the section in the doc I linked on the difference between HOST_PORT and CONTAINER_PORT:

Networked service-to-service communication use the CONTAINER_PORT. When HOST_PORT is defined, the service is accessible outside the swarm as well.

Now connect to http://smn-imm/ in your browser and it should work. If this isn't the hostname you intend to use for the service, then update the server_name in the nginx config, and/or configure your DNS.

Obviously don't make this available to the internet though, another reverse proxy should terminate SSL, or alternatively configure your nginx container with SSL certs, and expose port 443.