How to Serve an Angular App with nginx in Docker
Nick Scialli
February 09, 2021
Let’s create a website using the Angular framework and learn how to serve it in a Docker container using nginx. We are going to use the Angular CLI to generate a starter Angular app.
We will name this app angular-nginx-docker
. Note that I’m using npx
here because I’m too lazy to install the Angular CLI directly, but if you have it installed locally you would use ng
instead of npx @angular/cli
.
npx @angular/cli new angular-nginx-docker
Once the app is set up, navigate to the new app folder:
cd angular-nginx-docker
Now we know we’ll need a couple files to use with Docker: a Dockerfile
and a .dockerignore
file. Let’s make them now.
touch Dockerfile
For our .dockerignore
file, let’s make sure to ignore our dependency files in node_modules
like we would with git.
echo "node_modules" > .dockerignore
Building Out the Dockerfile
Time to build out the Dockerfile! There are a lot of ways we could do this, but today we’ll use a multi-stage process:
- Stage 1: Node image for building frontend assets
- Stage 2: nginx stage to serve frontend assets
Stage 1: Building the front-end assets
Our first stage will:
- Use a node image
- Copy all our Angular files into a working directory
- Install the project dependencies with npm
- Build the app with npm
Here’s how this looks in Docker!
# Name the node stage "builder"
FROM node:10 AS builder
# Set working directory
WORKDIR /app
# Copy all files from current directory to working dir in image
COPY . .
# install node modules and build assets
RUN npm i && npm run build
Next up, we actually serve the content we just built!
Stage 2: Our nginx server
Our second stage will:
- Use an nginx image
- Remove any default static assets from the nginx image
- Copy our static assets from the
builder
image we created in the first stage - Specify the entrypoint for our container to run nginx
Here’s what this stage looks like in the Dockerfile:
# nginx state for serving content
FROM nginx:alpine
# Set working directory to nginx asset directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static assets
RUN rm -rf ./*
# Copy static assets from builder stage
COPY --from=builder /app/dist/angular-nginx-docker .
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]
Importantly, Angular builds the static assets into the dist/[project name]
folder by default, so we copy our files from there. If your app builds the files into another folder for some reason, adjust accordingly.
Putting it All Together
Okay! Let’s put this all together and run our app.
Our multi-stage Dockerfile should now look like this:
# Multi-stage
# 1) Node image for building frontend assets
# 2) nginx stage to serve frontend assets
# Name the node stage "builder"
FROM node:10 AS builder
# Set working directory
WORKDIR /app
# Copy all files from current directory to working dir in image
COPY . .
# install node modules and build assets
RUN npm i && npm run build
# nginx state for serving content
FROM nginx:alpine
# Set working directory to nginx asset directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static assets
RUN rm -rf ./*
# Copy static assets from builder stage
COPY --from=builder /app/dist/angular-nginx-docker .
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]
Now that we have assembled our Dockerfile, let’s build an image called angular-nginx
:
docker build -t angular-nginx .
Now that our image is built, we can start a container with the following command, which will serve our app on port 8080.
docker run --rm -it -p 8080:80 angular-nginx
Navigate to http://localhost:8080, and you should now see our default Angular app!
Nick Scialli is a senior UI engineer at Microsoft.