Docker Nginx Angular2/Angular routes

24,770

Solution 1

Here is my nginx sites-available/myapp

server {
    listen 80;
    listen 80 [::]:80;
    root /my/root/path;
    server_name www.mysite.com mysite.com;

    location /app1/ {
        alias /my/root/path/app1/;
        try_files $uri$args $uri$args/ $uri/ /app1/index.html;
    }

    location /app2/ {
         ...
    }    
}

After setting up the config you want to make your site enabled, run:

sudo ln -s /pathtonginx/sites-available/myapp /pathtonginx/sites-enabled/myapp

The basehref on my index.html

<base href="./">

Hope this helps!

Solution 2

The nginx Docker image includes a base configuration file, /etc/nginx/nginx.conf. This configuration file sets up various items to values that the image maintainers (presumably) know to be good values for a Docker container, so it is tempting to make use of that configuration file as much as possible when serving Angular. Anticipating that users might want to do that, the base configuration file includes the directive

http {
...
    include /etc/nginx/conf.d/*.conf;
}

so, you can put your Angular specific configuration in a file /etc/nginx/conf.d/ng.conf, and get the benefit of using the base configuration file.

That file can be nice and simple. As recommended by the Angular documentation and the Nginx documentation, it just uses the try_files directive to serve your index.html for all deep-link paths:

  server {
    location / {
      root /usr/share/nginx/html;
      try_files $uri $uri/ /index.html;
    }
  }

and your Dockerfile just needs to copy that file from the build context into the Docker image:

COPY src/etc/nginx/conf.d/ng.conf /etc/nginx/conf.d/

I did that, but it didn't work, because there is also one snag. The nginx Docker image also includes a file /etc/nginx/conf.d/default.conf. That file is suitable for serving static content (from /usr/share/nginx/html), and if Nginx uses that configuration in preference to your configuration (which can happen), your try_files will be useless. Your Dockerfile should therefore also remove that default configuration:

RUN rm /etc/nginx/conf.d/default.conf

Solution 3

You need to configure your docker file like the following;

FROM nginx:1.17.8-alpine

COPY nginx.conf /etc/nginx/conf.d/nginx.conf
WORKDIR /usr/share/nginx/html/
COPY dist/mooveinn .
RUN rm /etc/nginx/conf.d/default.conf

One important thing is to remove the default nginx conf file.

Then your nginx file will be similar to this one;

server {
    listen 80;
    server_name localhost;
    #sending logs to console(standard out) in a predefined json fromat
    #access_log / dev / stdout json_combined;
    #error_log / dev / stdout info json_combined;
    root / usr / share / nginx / html;
    index index.html index.htm;
    include / etc / nginx / mime.types;
    # compression
    gzip on;
    gzip_min_length 1000;
    gzip_proxied expired no - cache no - store private auth;
    gzip_types text / plain text / css application / json application / javascript application / x - javascript text / xml application / xml application / xml + rss text / javascript;

    # angular index.html location
    location / {
        try_files $uri $uri / /index.html;
    }
    # potential reverse proxy
    for sending api calls
    location / reverse - proxy / {
        proxy_set_header Host $host;
        proxy_set_header Content - Type application / json;
        proxy_set_header X - Real - IP $remote_addr;
        # proxy_pass http: //pointer-api:8080/;
    }
}

Build the docker image again, and run the application.

Share:
24,770
Steve Fitzsimons
Author by

Steve Fitzsimons

Updated on July 09, 2022

Comments

  • Steve Fitzsimons
    Steve Fitzsimons almost 2 years

    I have an Angular2/Angular app running inside a docker container and using nginx to serve it. So my app base = /myapp/. Everything works correctly when hitting the app using the base url i.e. www.server.com/myapp or www.server.com/myapp/

    events {
      worker_connections  4096;  ## Default: 1024
    }
    
    http {
      include /etc/nginx/conf/*.conf;
    
      server {
        listen       80 default_server;
    
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        include /etc/nginx/mime.types;
        underscores_in_headers on;
    
        location /myapp {
          # If you want to enable html5Mode(true) in your angularjs app for pretty URL
          # then all request for your angularJS app will be through index.html
          try_files $uri /myapp/index.html;
    
        }
    
        #Static File Caching. All static files with the following extension will be cached for 1 day
        location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
          expires 1d;
        }
    
        ## PROXIES ##
        # location matcher for get requests. Any query params will be proxied using this location block
        location = /myapp/api {
    
          proxy_pass http://$hostname/api$is_args$query_string;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection 'upgrade';
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_connect_timeout       120;
          proxy_send_timeout          120;
          proxy_read_timeout          120;
          send_timeout                120;
        }
    
        # location matcher for post requests i.e. updateAsset. Any request with additional path params will be proxied using this location block
        location ~ ^/myapp/api/(?<section>.*) {
    
          proxy_pass http://$hostname/api/$section;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection 'upgrade';
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_connect_timeout       120;
          proxy_send_timeout          120;
          proxy_read_timeout          120;
          send_timeout                120;
        }
      }
    }
    

    My app has several other routes e.g. /myapp/page1 or /myapp/page2. These routes can be hit when serving the app in dev mode using nodejs. However once i containerize it (containerization isn't the issue) and serve using nginx then i get a 404 not found when trying to access /myapp/page1 or /myapp/page2. The error log outputs

    2017/02/27 12:15:01 [error] 5#5: *3 open() "/usr/share/nginx/html/myapp/page1" failed (2: No such file or directory), client: 172.17.0.1, server: , request: "GET /myapp/page1 HTTP/1.1", host: "localhost"

    I have tried mapping all my app urls in the nginx conf file but nothing seems to work. How do I get this to work?

    Update 1

    Added angular routes

    Main app route:

    import { Route } from '@angular/router';
    import { MyAppComponent } from './index';
    
    export const MyAppRoutes: Route[] = [
      {
        path: '',
        component: MyAppComponent
      }
    ];
    

    Page 1 route:

    import { Route } from '@angular/router';
    import { Page1Component } from './index';
    
    export const Page1Routes: Route[] = [
      {
        path:'page1',
        component: Page1Component
      }
    ];