Prog blog

Dockerfile for Angular production build

Dockerfile for Angular production build

Hey, I usually learn new things about IT after work. Last time I said I'd learn how to make dockers in my spare time. Below is a recipe for a well-built image of the production version for any angular project.

Since the Angular 9 and Ivy versions, the Angular compatibility compiler (ngcc) has been added. It is designed to pre-compile libraries for further use of Angular. Usually ngcc is run during the ng build but for the dock image to reduce the build time we will call the pre-compilation right after the package installation. For this, we will need to make this command available from the scripts in package.json. In addition, we also need to access the ng cli Angular.

package.json

{
  "scripts": {
    "ngcc": "ngcc",
    "ng": "ng"
  }
}

The docker file has two stages. First there is the building stage. Where all modules are downloaded and the Angular project is built to the production version. The second stage is to create an nginx server on port 80 to share the previously built project.

Dockerfile

FROM node AS build

WORKDIR /opt/ng
COPY package.json ./
COPY package-lock.json ./
RUN npm ci
RUN npm run ngcc
ENV PATH="./node_modules/.bin:$PATH" 

COPY . ./

RUN npm run ng build <project> --prod 

FROM nginx
COPY --from=build /opt/ng/dist/<project> /usr/share/nginx/html

An important file here is also .dockerignore.

.dockerignore

node_modules
dist

This allows the docker to ignore the locally created node_modules and dist directory during COPY operations.

docker-compose.yml

---
version: "2.1"
services:
  frontend:
    build:
      context: .
      dockerfile: ./Dockerfile
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    restart: always

There's also the docker-compose.yml where we overwrite the nginx configuration.

nginx.conf

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}


http {
    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;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied expired no-cache no-store private auth;
    gzip_types text/plain text/css text/xml text/javascript application/javascript;

    include /etc/nginx/conf.d/*.conf;
}

I've extended the configuration to make gzip active in response server. This will allow us to send smaller files.

We're testing the image with a command:

docker-compose up

If we don't get any bugs in the console and we have our project at http://localhost:80/ it means that we have set everything right. And we can enjoy a ready-made production image of the project.

Example angular project on docker

Additionally, I'm publishing a repository on github with a working example: https://github.com/studioLaCosaNostra/docker-for-angular