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 1Added 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 } ];
NGINX can be used as a web server or reverse proxy to serve the static content. All the NGINX configuration can be placed in this file nginx. conf . We need to build the angular app and place all the static files in the root location of the NGINX to serve the web. Docker is used as the container runtime.
NGINX Configuration: Understanding Directives. Every NGINX configuration file will be found in the /etc/nginx/ directory, with the main configuration file located in /etc/nginx/nginx. conf .
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!
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With