Dockerize an Angular 17 app with nginx and deploy on Kubernetes


There serveral ways to host an Angular app using nginx, a nodejs server, IIS, Apache on a Windows or Lunix with registered as a service.

In this blog post, we will go through step-by-step guide to build an Angular app using Docker and host the production-ready in nginx container and then deploy on Kubernetes.

Normally, the result of the build is outputted in the dist/<app-name> for an Angular 16, but Angular 17 is outputting the build result in a folder called browser. Yet, this is the configuration in the angular.js, it’s showing dist/<app-name>. but it still adds folder called browser.

Asume that we already have an Angular 17 app, with the outputted in the dist/<app-name>/browser.

1. Create Dockerfile, .dockerignore and nginx.conf.template

We shall be using Nginx to host the angular build inside the container. Create a nginx.conf.template file in the project root folder with the folloing content:

server{
    listen 80;
    sendfile on;
    default_type application/octet-stream;

    gzip on;
    gzip_http_version 1.1;
    gzip_disable      "MSIE [1-6]\.";
    gzip_min_length   256;
    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   9;

    root /usr/share/nginx/html;

    location / {
      try_files $uri $uri/ /index.html =404;
    }
}

Dockerfile will consist of commands which needs to execute when we are building docker image. With Angular 17, we need to use node:18 or later to support Angular 17.

# Stage 1: Build Angular app
FROM node:18-alpine as builder
# Automatically create the directory if it doesn't exist.
WORKDIR /app
# Copy the rest of the application code
COPY . .
# Install dependencies
RUN npm install
# Build the Angular app
RUN npm run build

# Stage 2: Serve Angular app using NGINX
FROM nginx:1.20 as ngx
# Copy built Angular app from Stage 1
COPY --from=builder /app/dist/<app-name>/browser /usr/share/nginx/html
COPY /nginx.conf.template  /etc/nginx/conf.d/default.conf
# Create NGINX cache directory
RUN mkdir -p /var/cache/nginx/client_temp
# Set ownership of NGINX cache directory
RUN chown -R nginx:nginx /var/cache/nginx

# Expose port 80
EXPOSE 80

# Start NGINX
CMD ["nginx", "-g", "daemon off;"]

.dockerignore contains which file/folder we need to ignore while docker build takes place.

.git
.firebase
.editorconfig
/node_modules
/e2e
/docs
.gitignore
*.zip
*.md

Build and run the Container

Now that we have assembled our Dockerfile, let’s build an image called

docker build --no-cache=true . -t angular-nginx:v0.0.1

If Docker getting stuck at RUN npm run build, Change the parameter cli in angular.json to:

"cli": {
  "analytics": false,
},

After the image is built successfully, we can start a container with the following command, which will serve our app on port 8080:80 (<host-port>:<docker-port>). We had exposed port 80 in Dockerfile and assigned nginx to listen to port 80.

docker run --rm -it -p 8080:80 angular-nginx:v0.0.1

Navigate to http://localhost:8080, and we now can see our Angular app.

Deploy on Kubernetes

Create the Deployment:

kubectl apply -f - <<EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: dev
  name: fe-app
  labels:
    app: fe-app
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 0
  minReadySeconds: 30
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: fe-app
  template:
    metadata:
      labels:
        app: fe-app
    spec:
      containers:
      - name: fe-app
        image: 'angular-nginx:v0.0.1'
        ports:
        - containerPort: 80
EOF

We have to continue on creating the Service and Ingress for the deployment.

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Service
metadata:
  namespace: dev
  name: fe-app
  labels:
    app: fe-app
    service: fe-app
spec:
  type: NodePort
  ports:
    - name: fe-app
      port: 80
      targetPort: 80
      protocol: TCP
  selector:
    app: fe-app
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: fe-ingress
  namespace: dev
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /

spec:
  rules:
    - host: angular.app.local
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: fe-app
                port:
                  number: 80
EOF

Now, the Angula app is live on http://angular.app.local in web browser.


Nam Le, [email protected]
@nready.net


Leave a Reply