Docker Nginx Angular2/Angular routes
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.
Steve Fitzsimons
Updated on July 09, 2022Comments
-
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 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 } ];