DougM
DougM

Reputation: 940

How can I connect the Nginx container to my React container?

I have tried reading through the other stackoverflow questions here but I am either missing something or none of them are working for me.

Context

I have two docker containers setup on a DigitalOcean server running Ubuntu.

root_frontend_1 running on ports 0.0.0.0:3000->3000/tcp root_nginxcustom_1 running on ports 0.0.0.0:80->80/tcp

If I connect to http://127.0.0.1, I get the default Nginx index.html homepage. If I http://127.0.0.1:3000 I am getting my react app.

What I am trying to accomplish is to get my react app when I visit http://127.0.0.1. Following the documentation and suggestions here on StackOverflow, I have the following:

docker-compose.yml in root of my DigitalOcean server.

version: "3"
services:
  nginxcustom:
    image: nginx
    hostname: nginxcustom
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/root/nginxcustom/conf/custom.conf
    tty: true

  backend:
    build: https://github.com/Twitter-Clone/twitter-clone-api.git
    ports:
      - "8000:8000"
    tty: true

  frontend:
    build: https://github.com/dougmellon/react-api.git
    ports:
      - "3000:3000"
    stdin_open: true
    tty: true

nginxcustom/conf/custom.conf :

server {
 listen 80;
 server_name http://127.0.0.1;

  location / {
    proxy_pass http://root_frontend_1:3000; # this one here
    proxy_redirect off;
  }
}

When I run docker-compose up, it builds but when I visit the ip of my server, it's still showing the default nginx html file.

Question

What am I doing wrong here and how can I get it so the main URL points to my react container?

Thank you for your time, and if there is anything I can add for clarity, please don't hesitate to ask.

Upvotes: 1

Views: 1082

Answers (2)

masseyb
masseyb

Reputation: 4150

TL;DR;

The nginx service should proxy_pass to the service name (customnginx), not the container name (root_frontend_1) and the nginx config should be mounted to the correct location inside the container.

Tip: the container name can be set in the docker-compose.yml for services setting the container_name however beware you can not --scale services with a fixed container_name.

Tip: the container name (root_frontend_1) is generated using the compose project name which defaults to using the current directory name if not set.

Tip: the nginx images are packaged with a default /etc/nginx/nginx.conf that will include the default server config from /etc/nginx/conf.d/default.conf. You can docker cp the default configuration files out of a container if you'd like to inspect them or use them as a base for your own configuration:

docker create --name nginx nginx
docker cp nginx:/etc/nginx/conf.d/default.conf default.conf
docker cp nginx:/etc/nginx/nginx.conf nginx.conf
docker container rm nginx

With nginx proxying connections for the frontend service we don't need to bind the hosts port to the container, the services ports definition can be replaced with an expose definition to prevent direct connections to http://159.89.135.61:3000 (depending on the backend you might want prevent direct connections as well):

version: "3"
services:
  ...
  frontend:
    build: https://github.com/dougmellon/react-api.git
    expose:
      - "3000"
    stdin_open: true
    tty: true

Taking it a step further we can configure an upstream for the frontend service then configure the proxy_pass for the upstream:

upstream frontend {
  server frontend:3000 max_fails=3;
}
server {
  listen 80;
  server_name http://159.89.135.61;

  location / {
    proxy_pass http://frontend/;
  }
}

... then bind-mount the custom default.conf on top of the default.conf inside the container:

version: "3"
services:
  nginxcustom:
    image: nginx
    hostname: nginxcustom
    ports:
      - "80:80"
    volumes:
      - ./default.conf:/etc/nginx/conf.d/default.conf
    tty: true

... and finally --scale our frontend service (bounce the services removing the containers to make sure changes to the config take effect):

docker-compose stop nginxcustom \
&& docker-compose rm -f \
&& docker-compose up -d --scale frontend=3

docker will resolve the service name to the IP's of the 3 frontend containers which nginx will proxy the connections for in a (by default) round robin manner.

Tip: you can not --scale a service that has ports mappings, only a single container can bind to the port.

Tip: if you've updated the config and can connect to your load balanced service then you're all set to create a DNS record to resolve a hostname to your public IP address then update your default.conf's server_name.

Tip: for security I maintain specs for building a nginx docker image with Modsecurity and Modsecurity-nginx pre-baked with the OWASP Core Rule Set.

Upvotes: 2

Adrien De Peretti
Adrien De Peretti

Reputation: 3672

In Docker when multiple services needs to communicate with each other, you can use the service name in the url (set in the docker-composer.yml instead of the ip (which is attributed from the available pool of the network, default by default), it will automatically be resolve to the right container ip due to network management by docker.

For you it would be http://frontend:3000

Upvotes: 0

Related Questions