Home > Enterprise >  How to point Nginx docker container to the correct container for my web app?
How to point Nginx docker container to the correct container for my web app?

Time:07-07

I am setting up my Ruby on Rails application on AWS ECS and would like to redirect my website, example.com, to www.example.com. I am running into an issue with redirecting my Nginx upstream server to my Rails app. Everything seems to work fine locally. My Docker container crashes with the following error message:

[emerg] 8#8: host not found in upstream "web:3000" in /etc/nginx/conf.d/default.conf:3
nginx: [emerg] host not found in upstream "web:3000" in /etc/nginx/conf.d/default.conf:3

Here's my docker-compose.yml:

version: '3'

services:
  web:
    build:
      args:
        DEPLOY_ENV_ARG: ${DEPLOY_ENV:-development}
        SERVER_ENV_ARG: ${SERVER_ENV:-development}
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"

  nginx:
    build:
      dockerfile: Dockerfile.nginx
    links:
      - web
    ports:
      - "80:80"

Dockerfile.nginx

FROM nginx:1.23-alpine

COPY ./nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

nginx.conf

upstream rails_app {
  server web:3000;
}

server {
  server_name example.com;

  # Redirect all http://example.com requests to http://www.example.com
  return 301 $scheme://www.$server_name$request_uri;
}

server {
  listen 80;
  listen [::]:80;
  # server_name www.example.com;
  server_name xxxxx-xxxxx-xxxx-xxxx.us-west-2.elb.amazonaws.com; # My ALB address hostname

  # Specify the public application root
  root   /example/public;

  # Specify where Nginx should write its logs
  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  # Deny requests for files that should never be accessed such as .rb or .log files
  location ~ /\. {
    deny all;
  }

  location ~* ^. \.(rb|log)$ {
    deny all;
  }

  # Serve static (compiled) assets directly
  location ~ ^/(assets|images|javascripts|stylesheets|swfs|system)/   {
    try_files $uri @rails;
    access_log off;
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    add_header Last-Modified "";
    add_header ETag "";
    break;
  }

  # Send non-static file requests to the app server
  location / {
    try_files $uri @rails;
  }

  # Reverse proxy redirecting the request to the rails app, port 3000.
  location @rails {
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://rails_app;
    proxy_read_timeout 900;
  }
}

If it's helpful, here's the output of docker ps:

CONTAINER ID   IMAGE                                                                             COMMAND
  CREATED          STATUS                  PORTS                                       NAMES
4634eafd0ac1   xxxxxxxxxx.xxx.xxx.us-west-2.amazonaws.com/example_web_production:latest      "./docker/web-entryp…"   3 seconds ago    Up 2 seconds            0.0.0.0:3000->3000/tcp, :::3000->3000/tcp   ecs-example_web_production-10-web-aad0d39b88a584e02800
3385ac3e9bcd   amazon/amazon-ecs-agent:latest                                                    "/agent"
  37 hours ago     Up 37 hours (healthy)                                               ecs-agent

How can I get the Nginx config to recognize the web container running on the same instance?

CodePudding user response:

I fixed it! Nginx could not find the web container because the links between the nginx and web containers were not set in the AWS ECS task definition. This is what my task definition looked like before:

{
  ...
  "containerDefinitions": [
    {
      "name": "nginx",
      "image": "xxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/nginx:latest",
      "cpu": 0,
      "links": [],
      "portMappings": [
        {
          "containerPort": 80,
          "hostPort": 0,
          "protocol": "tcp"
        }
      ],
      "essential": true,
      ...
    },
    {
      "name": "web",
      "image": "xxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/web:latest",
      "cpu": 0,
      "links": [],
      "portMappings": [
        {
          "containerPort": 3000,
          "hostPort": 3000,
          "protocol": "tcp"
        }
      ],
      "essential": true,
      ...
    }
  ]

  ...
}

Now it looks like the following (note the links):

{
  ...
  "containerDefinitions": [
    {
      "name": "nginx",
      "image": "xxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/nginx:latest",
      "cpu": 0,
      "links": [
        "web"
      ],
      "portMappings": [
        {
          "containerPort": 80,
          "hostPort": 0,
          "protocol": "tcp"
        }
      ],
      "essential": true,
      ...
    },
    {
      "name": "web",
      "image": "xxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/web:latest",
      "cpu": 0,
      "links": [],
      "portMappings": [
        {
          "containerPort": 3000,
          "hostPort": 3000,
          "protocol": "tcp"
        }
      ],
      "essential": true,
      ...
    }
  ]

  ...
}

I had to use the old ECS console in order to add the web container as link; the new console doesn't have that option yet. See this SO answer for a screenshot.

  • Related