DEV Community

Pavan K Jadda for This is Angular

Posted on

7 2

Multi Stage Docker builds with Angular and Nginx

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 .
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • 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 .
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode
  • 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/*
Enter fullscreen mode Exit fullscreen mode
  • 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;
    }
    
    
    
  • Then Copy dist folder from build stage to nginx public folder
COPY — from=builder /app/dist /usr/share/nginx/html
Enter fullscreen mode Exit fullscreen mode
  • 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 :)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay