This blog post shows multi stage Dockerfile that builds and deploys Angular app in Nginx container
Dockerfile:
###### Install dependencies only when needed ######
FROM node:16-alpine AS builder
ARG CONFIGURATION='dev'
# Make /app as working directory
WORKDIR /app
# Copy package.json file
COPY package.json .
# Install dependencies
RUN npm install --legacy-peer-deps
# Copy the source code to the /app directory
COPY . .
# Build the application
RUN npm run build -- --output-path=dist --configuration=$CONFIGURATION --output-hashing=all
###### Use NgInx alpine image ######
FROM nginx:stable-alpine
# Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*
# Copy nginx config file
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
# Copy dist folder fro build stage to nginx public folder
COPY --from=builder /app/dist /usr/share/nginx/html
# Start NgInx service
CMD ["nginx", "-g", "daemon off;"]
The above Dockerfile has 2 stages
Stage 1 – install NPM dependencies and builds Angular project
Stage 2 – Builds docker image from dist
directory generated by previous stage
Stage 1: Install dependencies and Build Angular project
- We use Node 16 alpine image to build the project and it accepts
CONFIGURATION
build argument. You can override this during build based on your environment
docker build --build-arg CONFIGURATION=dev .
and you can also define as many arguments as you like
2. Then make/app
as working directory. All of the source code and files will be copies to /app
directory inside Node container
WORKDIR /app
3. Copy the package.json file to /app directory. This will enable Docker to cache the node_modules
rather than building from scratch and sub sequent builds use these when package.json file is unchanged.
COPY package.json .
4. Install dependencies using npm install
command and specify flag — legacy-peer-deps
to prevent build errors in NPM 7+
RUN npm install --legacy-peer-deps
5. Then copy the source code and build the project using npm run build
COPY . .RUN npm run build -- --output-path=dist --configuration=$CONFIGURATION --output-hashing=all
6. The built code will be present in /app/dist
directory in Node container
Stage 2: Build Docker image
- We use
NgInx
alpine stable image to serve Angular application in production - Remove existing HTML content using the command
RUN rm -rf /usr/share/nginx/html/*
3. Copy the Nginx config file from source to /etc/nginx/nginx.conf
directory. If you don’t have one, you can use the below one
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events
{
worker_connections 1024;
}
http
{
upstream springbootapp
{
server pres_springboot:8080;
}
server
{
location /
{
#### Gzip Settings ####
gzip on;
gzip_min_length 1100;
gzip_vary on;
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;
gzip_comp_level 5;
#### Serve Angular Application ####
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-store, no-cache, must-revalidate";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
}
location /api
{
proxy_pass http://springbootapp;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
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;
keepalive_timeout 30m;
include /etc/nginx/conf.d/*.conf;
}
4. Then Copy dist
folder from build stage to nginx public folder
COPY — from=builder /app/dist /usr/share/nginx/html
5. At the end specify the NgInx start command. That’s it.
You can also split Stage 1 into two separate stages. One to install dependencies and second one to build the Angular app 🙂