nginxdockerfilenginx-reverse-proxynginx-confignginx-location

Dockerized NGINX with Reverse proxy doesn't listen on the default port


I have deployed my django backend api on Amazon Ec2 using docker successfully.

My first step is when I attempted to put in a dockerized Nginx to act as a reverse proxy. I then eventually intend to use for Static media files caching and a dedicated live media streaming server. I'm using the following repo https://github.com/tiangolo/nginx-rtmp-docker/tree/master which installs the necessary nginx modules including the rtmp module which i need later.

However , There is no response from the nginx side when it comes to Reverse proxy which is the 1st configuration I'm testing.

The following is what I have checked.

  • Added port 70 as listen port for EC2 in Security groups - custom tcp.
  • Both the containers are running by checking docker stats
  • The ports are mapped correctly by checking the port mappings using docker ps.
  • Used netstat to check if the the port is listed after I spun up the 2 containers and both 70 (nginx listen port) and 80 (api listen port) are listed.
  • The api server still works when I hit the public static IP of my EC2 server 34.XX.XX.XX:80/ but not when I hit 34.XX.XX.XX:70/ which should proxy requests to the port 80.

Here is my configuration. Kindly note I'm not attaching the configuration for postgresql-db and redis-db in the docker-compose.yml since I believe they are not relevant to the question but they are the other 2 containers listening on other ports.

docker-compose.yml

services:
  webserver:
    container_name: myapp-api
    build:
      dockerfile: Dockerfile
      context: ./.docker/api
    privileged: True
    extra_hosts:
      - db.myapp:172.16.16.4
      - redis.myapp:172.16.16.5
    volumes:
      - ./:/opt/myapp-api-core
    ports:
      - '80:8080' # External listen port 80 mapped to interal docker port 8080
    working_dir: /opt/myapp-api-core
    networks:
      myapp:
        ipv4_address: 172.16.16.1
    depends_on:
      - db
      - redis
    env_file:
      - .docker-compose.env
      
  nginx-media_server:
    container_name: myapp-nginx-media-server
    build: 
        dockerfile: Dockerfile
        context: ./.docker/nginx-media-server
    ports:
      - 70:1652 # External Caching server listen port mapped to internal docker container port 1652.
    volumes:
      - ./.docker-cache/static:/tmp/nginx
      - ./.docker/nginx-media-server/nginx.conf:/etc/nginx/nginx.conf
      - ./.docker/nginx-media-server/log:/var/log/nginx # Logs
    networks:
        myapp:
          ipv4_address: 172.16.16.6
    env_file:
        - .docker-compose.env

nginx.conf

    worker_processes auto;
    
    events {
        use epoll;
    }
    
    # HTTP block
    http {
        log_format main '$remote_addr - $remote_user [$time_local] "$request" '
        '$status $body_bytes_sent "$http_referer" '
        '"$http_user_agent" "$http_x_forwarded_for" $request_time';
    
        # Access & Error Logs
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
    
        default_type application/octet-stream;
    
        include /etc/nginx/mime.types;
    
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
    
        # Increase the maximum size of the hash table
        proxy_headers_hash_max_size 1024;
    
        # Increase the bucket size of the hash table
        proxy_headers_hash_bucket_size 128;
    
        #Note that these are defined outside of the server block altho they don't necessarily need to be
        proxy_cache_path /tmp/nginx levels=1:2 keys_zone=my_zone:10m inactive=60m max_size=20g;
        proxy_cache_key "$scheme$request_method$host$request_uri";
    
      
        server {
    
            listen 70 default_server;
            server_name _;
    
            access_log /var/log/nginx/access.log ;
            error_log /var/log/nginx/error.log;
    
            location / {
                proxy_cache my_zone;
                proxy_cache_bypass $http_cache_control;
                add_header X-Proxy-Cache $upstream_cache_status;
    
    
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
                include proxy_params;
    
                proxy_pass http://172.16.16.1:8080;
    
                # WebSocket support (nginx 1.4)
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
            }
           
        }
}     

Dockerfile (Nginx media server)

FROM buildpack-deps:bullseye

LABEL maintainer="Sebastian Ramirez <tiangolo@gmail.com>"

# Versions of Nginx and nginx-rtmp-module to use
ENV NGINX_VERSION nginx-1.23.2
ENV NGINX_RTMP_MODULE_VERSION 1.2.2

# Install dependencies
RUN apt-get update && \
    apt-get install -y ca-certificates openssl libssl-dev && \
    rm -rf /var/lib/apt/lists/*

# Download and decompress Nginx
RUN mkdir -p /tmp/build/nginx && \
    cd /tmp/build/nginx && \
    wget -O ${NGINX_VERSION}.tar.gz https://nginx.org/download/${NGINX_VERSION}.tar.gz && \
    tar -zxf ${NGINX_VERSION}.tar.gz

# Download and decompress RTMP module
RUN mkdir -p /tmp/build/nginx-rtmp-module && \
    cd /tmp/build/nginx-rtmp-module && \
    wget -O nginx-rtmp-module-${NGINX_RTMP_MODULE_VERSION}.tar.gz https://github.com/arut/nginx-rtmp-module/archive/v${NGINX_RTMP_MODULE_VERSION}.tar.gz && \
    tar -zxf nginx-rtmp-module-${NGINX_RTMP_MODULE_VERSION}.tar.gz && \
    cd nginx-rtmp-module-${NGINX_RTMP_MODULE_VERSION}

# Build and install Nginx
# The default puts everything under /usr/local/nginx, so it's needed to change
# it explicitly. Not just for order but to have it in the PATH
RUN cd /tmp/build/nginx/${NGINX_VERSION} && \
    ./configure \
        --sbin-path=/usr/local/sbin/nginx \
        --conf-path=/etc/nginx/nginx.conf \
        --error-log-path=/var/log/nginx/error.log \
        --pid-path=/var/run/nginx/nginx.pid \
        --lock-path=/var/lock/nginx/nginx.lock \
        --http-log-path=/var/log/nginx/access.log \
        --http-client-body-temp-path=/tmp/nginx-client-body \
        --with-http_ssl_module \
        --with-threads \
        --with-ipv6 \
        --add-module=/tmp/build/nginx-rtmp-module/nginx-rtmp-module-${NGINX_RTMP_MODULE_VERSION} --with-debug && \
    make -j $(getconf _NPROCESSORS_ONLN) && \
    make install && \
    mkdir /var/lock/nginx && \
    rm -rf /tmp/build

# Forward logs to Docker
RUN ln -sf /dev/stdout /var/log/nginx/access.log && \
    ln -sf /dev/stderr /var/log/nginx/error.log

# Set up config file
COPY nginx.conf /etc/nginx/nginx.conf

# Install ffmpeg
RUN apt-get -y update
RUN apt-get -y upgrade
RUN apt-get install -y ffmpeg

VOLUME ["/tmp/nginx","/etc/nginx/nginx.conf","/var/log/nginx"]

# Expose internal docker ports attached to external receiver ports.
EXPOSE 1652 

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

EDIT :

Based on the questions posted by @0xn0b174 -->

can you check the inbound rule for port 70 in you ec2 Security group what have you addded ??

Port          Source         Protocol            Description                      
 70          0.0.0.0/0          TCP           NGINX Caching server

you have mapped 1652 docker port to port 70 can you confrim your service is running in 1652 inside docker container.

can you share the ouput of docker exec -it myapp-nginx-media-server ping 172.16.16.1

OCI runtime exec failed: exec failed: unable to start container process: exec: "ping": executable file not found in $PATH: unknown

lastly can you tail and share /var/log/nginx/error.log and docker logs docker logs myapp-nginx-media-server

Shows logs from a few hourse before, the errors of which have been already corrected. Used the docker copy command

2024/09/07 04:16:46 [emerg] 1#1: invalid log level "main" in /etc/nginx/nginx.conf:16
2024/09/07 04:18:21 [emerg] 1#1: invalid log level "main" in /etc/nginx/nginx.conf:16
2024/09/07 06:22:32 [emerg] 1#1: host not found in upstream "api:8080" in /etc/nginx/nginx.conf:187
2024/09/07 06:24:37 [emerg] 1#1: invalid host in upstream "http://172.16.16.1:8080/" in /etc/nginx/nginx.conf:187
2024/09/07 06:27:15 [emerg] 1#1: invalid host in upstream "http://172.16.16.1:8080/" in /etc/nginx/nginx.conf:187
2024/09/07 07:27:28 [notice] 11#11: signal process started
2024/09/07 07:27:31 [notice] 20#20: signal process started
2024/09/07 07:29:01 [emerg] 1#1: unexpected end of file, expecting "}" in /etc/nginx/nginx.conf:444

docker.logs

docker logs --since=1h cc1274f259d4 > /home/ubuntu/docker_logs.txt 
Above log is empty

EDIT 2:

I did a clean install. The nginx error.log and access.log is empty. The ports are correctly mapped after check docker ps.

I entered the nginx container and did a nginx -t

I got this:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful


Solution

  • your setup should be pretty easy, not sure why are you complicating binding diffrent ports but here is nginx and docker conatiner simple setup to run in ec2:

    docker-compose.yml

    services:
      web:
        container_name: django-api
        build:
          context: ./django
          dockerfile: Dockerfile
        volumes:
          - ./django/app:/app
        expose:
          - "8000"  # Expose internal Django port
        networks:
          - myapp-network
    
      nginx:
        container_name: nginx
        build:
          context: ./nginx
          dockerfile: Dockerfile
        ports:
          - "80:80"  # Expose port 80 for the public to access
        volumes:
          - ./nginx/nginx.conf:/etc/nginx/nginx.conf
        depends_on:
          - web
        networks:
          - myapp-network
    
    networks:
      myapp-network:
        driver: bridge
    

    ./django/Dockerfile

    # Use official Python image from the dockerhub
    FROM python:3.9-slim
    
    # Set work directory
    WORKDIR /app
    
    # Install dependencies
    COPY ./app /app
    RUN pip install --upgrade pip && \
        pip install -r /app/requirements.txt
    
    # Expose port
    EXPOSE 8000
    
    # Command to run the app
    CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
    

    ./nginx/Dockerfile

    FROM nginx:alpine
    
    # Copy the custom nginx.conf to the container
    COPY nginx.conf /etc/nginx/nginx.conf
    
    EXPOSE 80
    CMD ["nginx", "-g", "daemon off;"]
    

    ./nginx/nginx.conf

    worker_processes auto;
    events { worker_connections 1024; }
    
    http {
        upstream django {
            server web:8000;  # The internal Django API service
        }
    
        server {
            listen 80;
    
            location / {
                proxy_pass http://django;
                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;
            }
        }
    }
    

    If you can imitate this setup you should be good to go.