This blog post shows multi stage Dockerfile that builds and deploys Angular app in Nginx container
###### 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
- Then make
/app
as working directory. All of the source code and files will be copies to /app directory inside Node container
WORKDIR /app
- 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 .
- 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
- 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
- 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/*
- Copy the Nginx config file from source to
/etc/nginx/nginx.conf
directory. If you don’t have one, you can use the below oneuser 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; }
- Then Copy dist folder from build stage to nginx public folder
COPY — from=builder /app/dist /usr/share/nginx/html
- 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 the second one to build the Angular app :)
Top comments (0)