This is the fist time I am writing a Dockerfile. I have an application in Angular that connects to different backends (Spring Boot Rest services). I mean to say the spring boot application has been deployed in many different sites/locations. They all have different URLs. These Rest services are already there (I didn’t write these rest services). I was getting CORS error when I tried to call these Rest services. So I had to us the below xyx.proxy.conf.json
Below is the configurations I have:
package.json
"scripts": {
"ng": "ng",
"start:localhost": "ng serve --proxy-config localhost.proxy.conf.json",
"start:site1qa": "ng serve --proxy-config site1qa.proxy.conf.json",
"start:site2qa": "ng serve --proxy-config site2qa.proxy.conf.json",
"start:site1prod": "ng serve --proxy-config site1qa.proxy.conf.json",
"start:site2prod": "ng serve --proxy-config site2prod.proxy.conf.json",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e --proxy-config site1qa.proxy.conf.json"
},
site1qa.proxy.conf.json Note: I must have to use proxy as I am getting CORS error
{
"/RestWeb/*": {
"target": "http://site1qa:8005",
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
}
}
Angular Service.ts
findAllByModelYear(): Observable<string[]> {
return this.httpClient.get<string[]>('/RestWeb/model/findAllModelYearCodes');
}
I tested the application using below commands in my local pointing to different backends like this:
npm run start:localhost
OR
npm run start:site1qa
OR
npm run start:site2prod
My current Dockerfile is like this:
# Stage 1: Compile and Build angular codebase
# Use official node image as the base image
FROM node:latest as build
# Set the working directory
WORKDIR /usr/local/app
# Add the source code to app
COPY ./ /usr/local/app/
# Install all the dependencies
RUN npm install
# Generate the build of the application
RUN npm run build
# Stage 2: Serve app with nginx server
# Use official nginx image as the base image
FROM nginx:latest
# Copy the build output to replace the default nginx contents.
COPY --from=build /usr/local/app/dist/my-projectt /usr/share/nginx/html
# Expose port 80
EXPOSE 80
Currently am I build like this:
docker build -t dockerangular .
And run like this:
docker run -it -p 8000:80 --name angulardocker1 my-first-app
Question:
How do I pass argument (while building and/or running the application), so I can connect to different sites (as mentioned in package.json i.e. using xyx.proxy.conf.json)
2
Answers
Since you seem to use NGINX as HTTP server, you can use the proxy_pass directive for the proxy purpose.
Also, you can create your own NGINX template configuration files, i.e. during bootstrap NGINX looks in the
/etc/nginx/templates/
folder, and if any.template
files are present, NGINX outputs the result of executing envsubst to/etc/nginx/conf.d
, for example:If you place a file in
/etc/templates/default.conf.template
, that contains variable references like this:the output would go to
/etc/nginx/conf.d/default.conf
and look like this (let’s sayMY_NGINX_PORT
is 8080):Ref: https://hub.docker.com/_/nginx
The solution:
Since NGINX’s default configuration file, located in
/etc/nginx/conf.d/default.conf
, contains a very simple setup, you can create a template file and let NGINX use it to override the default conf file during bootstrap:/etc/templates/default.conf.template
–(would become afterenvsubst
)–>/etc/nginx/conf.d/default.conf
nginx-default.conf.template
and fill it with this content and then put it in your project root folder:Note the
/RestWeb/
path and the${REMOTE_API_URL}
custom environment variable, i.e. any request starting with the/RestWeb/
path will be seamlessly proxied to the${REMOTE_API_URL}
, just like ng cli / webpack’s proxy dev server does.REMOTE_API_URL
todocker run
, its value will be used automatically when the NGINX server starts up, e.g.or for a secure API:
A few tips
You don’t need
EXPOSE 80
. It is only for documentation purposes, and does actually nothing.Avoid using the latest version of Docker images, like
nginx:latest
ornode:latest
. Thelatest
, as the name suggests, always points to the latest version.docker build
instruction the respective image with the latest version will be pulled from the Docker Hub, which, however, may not be what you actually want/need. Imagine, today the current version of node is 12 and after a few days/weeks version 13 comes out and with the tagnode:latest
you would pull it and use it under the hood. And that would be risky, because it could possibly break somethingnode:14-alpine
andnginx:1.19.9-alpine
. See the Docker Hub for more tags)These are equivalent:
See: https://docs.docker.com/engine/reference/builder/#workdir
See: Why COPY package*.json ./ precedes COPY . .?
Did you try to add the site1qa.proxy.conf.json to angular.json file like this?: