Help: Nginx on VPS proxy to docker container timeout

Hi, I’m new to using docker on servers, I have only used it for local development. I am working on a project that the server has nginx installed on it, and also some containers running with docker-compose.

I have created a container for running a laravel application and mapped it to port 8000. When setting up nginx, I have set the domain as a frontend, and the port 8000 will be a backend API. Whenever I access the frontend it works correctly. The problem is when I try to access the docker container, it always returns an error ERR_CONNECTION_TIMED_OUT. I have added a subdomain for this container.

this is the nginx configuration:

server {
    listen 80;
    listen [::]:80;
    
    server_name api.site; # ommited the real site.

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

this is how I created the docker-compose.prod.yml file. There is a compose for production and another one for local dev. The local dev has a nginx service inside of it and it is working fine. The production I didn’t add it because I think it doesn’t need because of the already running nginx on the vps. I don’t know if this thinking is right or not.

volumes:
  db-laravel: ~

networks:
  laravel:
    driver: bridge

services:

  # Application service
  app.laravel:
    container_name: app.laravel
    build:
      context: .
      dockerfile: ./docker/Dockerfile.prod
      args:
        - PHP_VERSION=8.3.9-fpm
    restart: unless-stopped
    tty: true
    environment:
      - SERVICE_NAME=app.laravel
      - SERVICE_TAGS=dev
    volumes:
      - .:/var/www/app
      - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
    working_dir: /var/www/app
    depends_on:
      - db.laravel
    networks:
      - laravel
    ports:
      - "${APP_PORT:-8000}:80"

  # Database service
  db.laravel:
    container_name: db.laravel
    image: mysql:9.0
    restart: unless-stopped
    tty: true
    ports:
      - '${FORWARD_DB_PORT:-3306}:3306'
    environment:
      - MYSQL_DATABASE=${DB_DATABASE}
      - MYSQL_USER=${DB_USERNAME}
      - MYSQL_PASSWORD=${DB_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
      - MYSQL_ROOT_HOST=%
      - SERVICE_NAME=db.laravel
      - SERVICE_TAGS=dev
    volumes:
      - db-laravel:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/my.cnf
    networks:
      - laravel

This is the Dockerfile for the app.laravel service:

# Versão da imagem Docker PHP
ARG PHP_VERSION

FROM php:${PHP_VERSION} as php

# Seta o Working dir
WORKDIR /var/www/app

# apt-utils é um extensão de recursos do gerenciador de pacotes APT
RUN apt-get update -y && apt-get install -y --no-install-recommends \
    apt-utils \
    supervisor

# Dependências recomendadas de desenvolvido para ambiente linux
RUN apt-get update && apt-get install -y \
    zlib1g-dev \
    libzip-dev \
    unzip \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    libpq-dev \
    libxml2-dev \
    curl \
    libcurl4 \
    libcurl4-openssl-dev \
    nano \
    git \
    build-essential \
    locales \
    libicu-dev \
    libonig-dev

# Instala dependências PHP
RUN docker-php-ext-configure gd --with-freetype --with-jpeg
RUN docker-php-ext-install -j$(nproc) \
    gettext \
    gd \
    zip \
    iconv \
    pcntl \
    fileinfo \
    simplexml \
    mysqli \
    pdo \
    pdo_mysql \
    bcmath \
    xml \
    session

# Copia configs do php.ini
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini

# Instala Composer
RUN cd /tmp \
    && curl -sS https://getcomposer.org/installer -o composer-setup.php \
    && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
    && rm composer-setup.php

# Configura arquivos do supervisor
# COPY ./supervisord/supervisord.conf /etc/supervisor
# COPY ./supervisord/conf /etc/supervisord.d/

# Limpa instalação
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Adiciona novo usuário
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

# Copia o diretório
COPY . /var/www/app

# Seta permissões
COPY --chown=www:www . /var/www/app

# Muda usuário atual
USER www

# Expõe a porta
EXPOSE 9000

# Executa comandos no supervisor
# CMD["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisor.conf"]

# Executa servidor php-fpm
CMD ["php-fpm"]

# Outros comandos teste
# COPY --from=composer:2.3.5 /usr/bin/composer /usr/bin/composer
# ENTRYPOINT ["docker/entrypoint.sh"]

I haven’t added the variables APP_URL and FORWARD_DB_PORT inside the .env file, so it is using the default values.

When I run the command docker ps it shows the containers running:

CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
c2e011dbef7b   laravel-app.laravel   "docker-php-entrypoi…"   26 minutes ago   Up 26 minutes   9000/tcp, 0.0.0.0:8000->80/tcp, :::8000->80/tcp        app.laravel
3a59d462dcd0   mysql:9.0             "docker-entrypoint.s…"   26 minutes ago   Up 26 minutes   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   db.laravel

When I run docker network ls it shows:

NETWORK ID     NAME                     DRIVER    SCOPE
d45cea03d35b   bridge                   bridge    local
333c46cd7f8e   host                     host      local
dc1dd81e2b46   laravel_laravel          bridge    local
7bc7a1539992   none                     null      local

currently the project is inside the vps at /var/www/laravel

Then when I run curl 127.0.0.1 or curl 0.0.0.0 it returns the standard page for the frontend.

But when I run curl 127.0.0.1:8000 or curl 0.0.0.0:8000 it shows an error:
curl: (56) Recv failure: Connection reset by peer

I don’t know if I need to open any ports, I’ve read that current docker compose already opens the ports.

When I run the commnand netstat -tulnit shows these active connections:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:33329         0.0.0.0:*               LISTEN     
tcp6       0      0 :::22                   :::*                    LISTEN     
tcp6       0      0 :::8000                 :::*                    LISTEN     
tcp6       0      0 :::3306                 :::*                    LISTEN     
tcp6       0      0 :::80                   :::*                    LISTEN     
udp        0      0 127.0.0.1:323           0.0.0.0:*                          
udp6       0      0 ::1:323                 :::*                          

And lastly, inside the container the permissions and group is root root with the standard permissions for writing, reading, etc. I don’t know if the group needs to change.

When inside the container if I try the command curl 127.0.0.1 it shows an error:
curl: (7) Failed to connect to 127.0.0.1 port 80 after 0 ms: Couldn't connect to server

I am looking for a solution on the internet and also using chat-gpt but there are many conflicting responses, and also many of them are about how to use nginx inside a container. I don’t know what could change from my setup.

Can someone help me?

It is unclear where nginx is running. I assume it’s running on the host, as neither your Dockerfile has any indication that you install nginx, copy the nginx.conf into the image, or bind it into the running container.

If the laravel container indeed just uses php-fpm, does php-fpm realy listen on port 80? Isn’t the default port 9000?

Shouldn’t php-fpm require a location block with fastcgi_pass to point the php-fpm container?

I am not a php guy, so I can not really here. I can only give pointers for your own follow up research.

I don’t know either, I was following a guide on how to setup the php container for laravel. The nginx is installed in the host machine.

When I run sudo netstat -pln it seems the connections exists. I also disabled the firewall entirely to rule out the possibility of being it. Still getting the timeout.

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      1435/docker-proxy   
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1277/nginx: master  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      595/sshd: /usr/sbin 
tcp        0      0 127.0.0.1:40155         0.0.0.0:*               LISTEN      884/code-f1e16e1e62 
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      1539/docker-proxy   
tcp6       0      0 :::3306                 :::*                    LISTEN      1441/docker-proxy   
tcp6       0      0 :::80                   :::*                    LISTEN      1277/nginx: master  
tcp6       0      0 :::22                   :::*                    LISTEN      595/sshd: /usr/sbin 
tcp6       0      0 :::8000                 :::*                    LISTEN      1546/docker-proxy   
udp        0      0 127.0.0.1:323           0.0.0.0:*                           601/chronyd         
udp6       0      0 ::1:323                 :::*                                601/chronyd

It is very strange because I’m on the second day of trying to discover a solution and I can’t find this problem anywhere.

1 Like