how to fix 404 not found when accessing URL routes while deploying an app using nginx?

12/10/2020

I am trying to deploy an angular based webapp to kube, I am trying to deploy it as static content using nginx.
The problem is the URL's are not accessible; meaning if I try to access https://website.company.com/route1, I get a 404 not found error, I can access https://website.company.com and then click on route1 from homepage it takes me to https://website.company.com/route1

Any guidance on what am I missing here?

Following are my Dockerfile and nginx.conf.erb

Dockerfile:

FROM nginx
EXPOSE 80
COPY www/* /usr/share/nginx/html
COPY nginx.conf.erb /etc/nginx/nginx.conf.erb

nginx.conf.erb:

worker_processes 1;
error_log stderr;
pid /app/.nginx-tmp/pid;
daemon off;

events {
        worker_connections 768;
}

http {
        include mime.types;
        client_body_temp_path /app/.nginx-tmp/body    1 2;
        proxy_temp_path       /app/.nginx-tmp/cache   1 2;
        fastcgi_temp_path     /app/.nginx-tmp/fastcgi 1 2;
        uwsgi_temp_path       /app/.nginx-tmp/uwsgi   1 2;
        scgi_temp_path        /app/.nginx-tmp/scgi    1 2;
        access_log off;
        server {
                listen <%= ENV['PORT'] %>;
                server_name _;
                root /app/www;
                index index.html;
                location = /__health {
                        return 200 'OK';
                        add_header Content-Type text/plain;
                }

                location / {
                        try_files $uri $uri/ /index.html;
                }
        }
}

UPDATE:

Dockerfile:

FROM nginx
RUN mkdir -p /app/.nginx-tmp
COPY www/* /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf

nginx.conf

worker_processes 1;
error_log stderr;
pid /app/.nginx-tmp/pid;
events {
        worker_connections 768;
}
http {
        include mime.types;
        client_body_temp_path /app/.nginx-tmp/body    1 2;
        proxy_temp_path       /app/.nginx-tmp/cache   1 2;
        fastcgi_temp_path     /app/.nginx-tmp/fastcgi 1 2;
        uwsgi_temp_path       /app/.nginx-tmp/uwsgi   1 2;
        scgi_temp_path        /app/.nginx-tmp/scgi    1 2;
        access_log off;
        server {
                listen 80;
                server_name _;
                root /app/www;
                index index.html;
                location = /__health {
                        return 200 'OK';
                        add_header Content-Type text/plain;
                }
                location / {
                        try_files $uri $uri/ /index.html;
                }
        }
}

Error:

2020/12/18 01:43:53 [error] 31#31: *2 rewrite or internal redirection cycle while internally redirecting to "/index.html", client: 172.17.0.1, server: _, request: "GET / HTTP/1.1", host: "localhost:8080"
2020/12/18 01:43:53 [error] 31#31: *1 rewrite or internal redirection cycle while internally redirecting to "/index.html", client: 172.17.0.1, server: _, request: "GET /favicon.ico HTTP/1.1", host: "localhost:8080", referrer: "http://localhost:8080/"
-- carte blanche
docker
kubernetes
nginx

1 Answer

12/17/2020

Indeed, NGINX is not going to understand a nginx.conf.erb file.
It looks like <kbd>Passenger</kbd> would allow this type of file type but the "vanilla" NGINX image won't.

So you will want your file to be a simple .conf file and to be copied over the existing /etc/nginx/nginx.conf file.

FROM nginx
EXPOSE 80
COPY www/* /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf 
## off course, you'll have to rename your host file to nginx.conf too.

Note that for this, you will also have to fix this line in the configuration file:

listen <%= ENV['PORT'] %>;

Because this a ruby erb syntax and it won't be accepted nor interpreted by NGINX.

And, because your containerPort is explicitly specifying that it exposes the port 3000 of the container, I would expect you will be safe with:

listen 3000;

But if this is not the case, you can use the solution prompted in the docker image documentation

Out-of-the-box, nginx doesn't support environment variables inside most configuration blocks. But this image has a function, which will extract environment variables before nginx starts.

Here is an example using docker-compose.yml:

web:
  image: nginx
  volumes:
   - ./templates:/etc/nginx/templates
  ports:
   - "8080:80"
  environment:
   - NGINX_HOST=foobar.com
   - NGINX_PORT=80

By default, this function reads template files in /etc/nginx/templates/*.template and outputs the result of executing envsubst to /etc/nginx/conf.d.

So if you place templates/default.conf.template file, which contains variable references like this:

listen       ${NGINX_PORT};

outputs to /etc/nginx/conf.d/default.conf like this:

listen       80;

<sup>Source: https://hub.docker.com/_/nginx</sup>

-- β.εηοιτ.βε
Source: StackOverflow