Search code examples
dockernginxdocker-composecontainersgunicorn

Nginx only shows index page of running server when accessed with HTTPS


I have two docker containers: one running nginx and another running my server app in flask. When sending requests with HTTP, all of server's endpoints are reachable both directly and through nginx. However, after adding certificate using mkcert(and allowing exception in browser) only the index page of my server is reachable.

Below are my nginx.conf and relevant part of docker-compose.yml

nginx.conf

server {
    listen 80;
    server_name example.com;

    # Redirect all HTTP traffic to HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/nginx/certs/server.crt;
    ssl_certificate_key /etc/nginx/certs/server.key;

    location / {
        proxy_pass http://server:5000;
        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;
    }
}

docker-compose.yml

services:
  server:
    build:
      context:  ./server
      dockerfile: Dockerfile.prod
    container_name: flask
    networks:
      backend:
    restart: always
    command: gunicorn --bind 0.0.0.0:5000 run:app
    volumes:
      - ./server/:/usr/src/server/
    expose:
      - 5000
    env_file:
      - ./server/.env.prod

  nginx:
    build: ./nginx
    container_name: nginx
    networks:
      backend:
      frontend:
    restart: always
    ports:
      - "8080:80"
      - "443:443"
    volumes:
      - ./server/certs:/etc/nginx/certs

Attempting to reach any of the endpoints results in nginx responding with 404 not found error. Using address http://example.com redirects me 'Welcome to nginx!' successful installation site, making me believe that the redirect part of nginx.conf is somehow faulty as well.

I have used port 8080 as port 80 was in use. lsof -i :80 returned nothing.


Solution

  • This config is working for me:

    events {
      worker_connections  4096;  ## Default: 1024
    }
    
    
    http {
      
      server {
          listen 80;
          server_name example.internal.test;
    
          # Redirect all HTTP traffic to HTTPS
          return 301 https://$host$request_uri;
      }
    
      server {
        listen 443 ssl;
        server_name example.internal.test;
    
        ssl_certificate /etc/nginx/certs/server.crt;
        ssl_certificate_key /etc/nginx/certs/server.key;
    
        location / {
            proxy_pass http://server: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;
        }
      }
    }
    

    and:

    services:
      server:
        image: adminer
        restart: always
        networks:
          - frontend
    
      nginx:
        image: nginx
        container_name: nginx
        depends_on:
          - server
        restart: always
        command: [nginx-debug, "-g", "daemon off;"] // add this for debugging
        networks:
          - frontend
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - ./server/certs:/etc/nginx/certs
          - ./nginx.conf:/etc/nginx/nginx.conf:ro
    
    networks:
      frontend:
        name: frontend
    
    

    I used an adminer server instead of a flask app but the concept remains the same. enter image description here

    You can probably try checking if your /etc/hosts is properly configured for example.com. Also make sure you flush cache dscacheutil -flushcache. Finally try using curl instead of the browser. curl https://example.com --insecure

    Make sure to add command: [nginx-debug, "-g", "daemon off;"] to your docker file so you can debug if requests are arriving to your nginx server and if they are being redirected properly.