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.