I am trying to host an Angular 2 seed on an NGINX server.
I am able to clone the seed, npm install
it and npm start
it and it works just fine off of the embedded web server.
I then try to move the content of the same src
directory of the seed (with the index.html
file and all the other Angular components in it under the default root of my nginx server ( /usr/share/nginx/html
).
My Angular index.html looks like this:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Clarity Seed App</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico?v=2">
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>
The structure of inside the src
directory (which is copied over to /usr/share/nginx/html
) is this:
drwxr-xr-x 14 root root 476 May 26 11:47 .
drwxr-xr-x 3 root root 4096 Nov 8 2016 ..
drwxr-xr-x 11 root root 374 May 26 10:40 app
drwxr-xr-x 4 root root 136 May 26 10:40 environments
-rw-r--r-- 1 root root 15086 May 26 10:40 favicon.ico
drwxr-xr-x 3 root root 102 May 26 10:40 images
-rw-r--r-- 1 root root 310 May 26 10:40 index.html
-rw-r--r-- 1 root root 351 May 26 10:40 main.ts
drwxr-xr-x 2 root root 68 May 26 11:47 node_modules
-rw-r--r-- 1 root root 604 May 26 10:40 polyfills.ts
-rw-r--r-- 1 root root 80 May 26 10:40 styles.css
-rw-r--r-- 1 root root 1005 May 26 10:40 test.ts
-rw-r--r-- 1 root root 702 May 26 10:40 tsconfig.json
-rw-r--r-- 1 root root 147 May 26 10:40 typings.d.ts
Inside the app
directory there is my actual Angular application.
When I try to connect to the nginx server the index.html
file is loaded properly but then, instead of loading the angular application, it just stays there (forever) at the "Loading" message per the <my-app>Loading...</my-app>
code.
I have not changed the default nginx configuration (given that I am dropping my angular app right into the default root for the web server). The configuration files for the nginx server are as follows.
Main nginx config file:
cat /etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
Nginx config file imported into the main config:
cat /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
I can't figure out whether this problem is due to some nginx configurations missing, whether this is due to some runtime components that are required to run the angular app or whether this problem is due to some compilation problems (but again if I take the same directory and I npm start
it the app renders just fine).
Thanks.
UPDATE: I did not mention this before as I thought that it would confuse stuff even more but when I said I moved the files from src
to /usr/share/nginx/html
what I have really done was to start nginx as a container and mapping my src
directory to the /usr/share/nginx/html
inside the container. So when I am working on my local host I npm install
and npm start
in the src
directory and it's working fine. Then I start the container mapping to the exact same directory (under /usr/share/nginx/html
) and I see the problem as described above. I want to assume that when you do the npm install
the first time you are actually compiling the app and downloading all dependencies and when you then use the same app (in src
) in the context of the nginx container the app is ready to be run?
UPDATE #2: I think this was getting a bit fluffy on my side so I decided to codify what I am trying to do. I think discussing around an actual piece of code is better than assuming. You can recreate my problem using this Dockerfile:
FROM nginx:1.11.5
RUN apt-get update
RUN apt-get -y install git
RUN git clone https://github.com/vmware/clarity-seed.git
RUN apt-get -y install build-essential
RUN apt-get -y install curl
RUN curl -sL https://deb.nodesource.com/setup_7.x | bash -
RUN apt-get -y install nodejs
RUN npm install -g @angular/cli
RUN sed -i -- 's#/usr/share/nginx/html#/clarity-seed/src#g' /etc/nginx/conf.d/default.conf
WORKDIR /clarity-seed/src
RUN npm install
RUN ng build --prod
You can build and run it as follows:
docker build -t mreferre/nginxangular .
docker run -d -p 8080:80 mreferre/nginxangular
if you point your browser to the docker host (port 8080) where the container is running ... you will see the Loading page I was referring to and the Angular app will never start.
Sure thing there is a mistake in the Dockerfile somewhere (or on the NGINX config?).
UPDATE #3: kind of getting closer now.. but not quite there yet. If you try to get inside the container above you can do a curl localhost:80
and you get your static html page served by nginx (which is running on port 80 of the container). Interesting to note this part of the response:
<body>
<my-app>Loading...</my-app>
</body>
If I then try to bring up the ng web server ( ng serve
) this comes up and start listening on port 4200. Now you can do curl localhost:4200
. The response is almost identical except for ...
<body>
<my-app>Loading...</my-app>
<script type="text/javascript" src="inline.bundle.js"></script><script type="text/javascript" src="scripts.bundle.js"></script><script type="text/javascript" src="styles.bundle.js"></script><script type="text/javascript" src="vendor.bundle.js"></script><script type="text/javascript" src="main.bundle.js"></script></body>
Unfortunately I don't have a real browser to test it but I 'd bet this is working (as I see the Javascript code being returned).
The problem seems to be due to the fact that, for some reasons, the nginx server doesn't provide the Javascript app content in the response.
Mh...
I eventually figured what I was doing wrong. I am not very familiar with Angular and I wasn't sure where the artifacts of the build were being built. I kept pointing my NGINX instance to the src
directory and I was missing that the production artifacts were being created in the dist
directory.
As soon as I pointed the nginx web server root to the dist
directory the application start working.
This is a sample (and definitely not optimized) working Dockerfile for reference:
FROM nginx:1.11.5
RUN apt-get update
RUN apt-get -y install git
RUN git clone https://github.com/vmware/clarity-seed.git
RUN apt-get -y install build-essential
RUN apt-get -y install curl
RUN curl -sL https://deb.nodesource.com/setup_7.x | bash -
RUN apt-get -y install nodejs
RUN npm install -g @angular/cli
RUN sed -i -- 's#/usr/share/nginx/html#/clarity-seed/dist#g' /etc/nginx/conf.d/default.conf
WORKDIR /clarity-seed/src
RUN npm install
RUN ng build --prod
For future reference I would like to add my production nginx-angular builder Dockerfile in response to your file. Since docker added a feature called multi-stage builds, it's possible to create really small images very easily without the use of a container builder pipeline.
FROM node:alpine as builder
COPY frontend /app
# build the app
RUN npm install
RUN npm run build
# now the fun part
FROM nginx:stable-alpine
# copy nginx configs
COPY nginx.conf /etc/nginx/nginx.conf
COPY dhparams.pem /etc/nginx/dhparams.pem
COPY example.com.crt /etc/nginx/example.com.crt
COPY example.com.key /etc/nginx/example.com.key
# copy the prebuild frontend from the previous build stage
COPY --from=builder /app/dist /app/dist
# expose both http and https port that nginx listens on
EXPOSE 80
EXPOSE 443
# because the nginx:stable-alpine image already has an CMD, nginx automatically starts up
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.