Getting Angular building inside Docker was actually pretty straightforward. Let’s jump straight in with a basic Angular build and release to nginx:
FROM nginx:alpine as envfetch dependencies
RUN apk add --no-cache nodejs nodejs-npm &&
apk upgrade --no-cache --available &&
npm config set unsafe-perm true &&
npm install -g @angular/cli npm-snapshot &&
npm cache clean --forcebuild step
FROM env as dev
COPY . src
WORKDIR src
RUN npm install &&
npm rebuild node-sass &&
ng buildrelease stage
FROM nginx:latest AS release
COPY --from=dev src/dist/ /usr/share/nginx/html/
OK, now let’s break this down:
FROM nginx:alpine as envfetch dependencies
RUN apk add --no-cache nodejs nodejs-npm &&
apk upgrade --no-cache --available &&
npm config set unsafe-perm true &&
npm install -g @angular/cli npm-snapshot &&
npm cache clean --force
Here I am using the nginx:alpine
base image — our Angular application is to be eventually served via a nginx server.
We are trying to standardise containers across all our microservices hence we are using alpine (linux) base image.
You could switch ngnix:alpine
out for node:latest
then you wouldn’t need the RUN apk add
steps, which brings me on nicely to fetching our dependencies…
Since we are base-ing from alpine we don’t have npm or nodejs installed inside the container, so we must fetch and install them before installing the Angular CLI.
Note: if you’re basing from node you won’t need to fetch nodejs or npm, something like this should work:
FROM node:latest as envRUN npm config set unsafe-perm true &&
npm install -g @angular/cli npm-snapshot &&
npm cache clean --force
Once we have got our dependencies installed, now let’s build our Angular application inside our container:
# build stepFROM env as dev
COPY . src
WORKDIR src
RUN npm install &&
npm rebuild node-sass &&
ng build
Here we are copying all our files inside a /src folder, then install our project dependencies from npm using npm install
.
Note: I have included a npm rebuild node-sass
step here, as node-sass is generally bound to your OS so unless you you’re developing locally inside alpine, you might run into diffs without it as your package-lock.json will be locking to the version of your local OS.
Finally we can run our build step using ng build
which should build our project into a /src/dist folder.
Now we are ready to release our built files to a ngnix server by copying them to the root of the ngnix as below.
# release stageFROM nginx:latest AS releaseCOPY --from=dev src/dist/<project>/ /usr/share/nginx/html/
Note: dependant on the build setup of your Angular application, you may need to specify which folder your files are built to.
Now, wouldn’t it be nice to be able to run our lint and unit tests inside Docker?
To do this, we first need to fetch chrome drivers required for alpine, change the RUN apk add line to the following:
RUN apk add --no-cache nodejs nodejs-npm bash chromium nss chromium-chromedriver &&
Getting the unit tests to run in Chrome headless was a little tricky. In short, Docker doesn’t like Chrome headless too much unless you’re running your container in privileged mode. Assuming you’re not, we need to tell Karma (Angular’s unit test runner) to run ChromeHeadless with the–no-sandbox
flag.
The easiest way I found was to add a customLauncher to your src/karma.conf.js as below:
customLaunchers: {
ChromeHeadless_without_sandox: {
base: ‘ChromeHeadless’,
flags: [‘–no-sandbox’]
}
},
browsers: [‘ChromeHeadless_without_sandox’]
Now can add lint and unit test step, as below:
# lint and unit testFROM dev as test
RUN ng lint &&
ng test --watch=false
That’s it! Now you should be able to build, test and release inside Docker.
Here’s a full working example with unit testing:
module.exports = function(config) {
config.set({
customLaunchers: {
Chrome_without_sandox: {
base: ‘ChromeHeadless’,
flags: [‘–no-sandbox’]
}
},
browsers: [‘Chrome’]
});
};
Add custom launcher to karma.config.js
FROM nginx:alpine as envRUN apk add --no-cache nodejs nodejs-npm bash chromium nss chromium-chromedriver && \ apk upgrade --no-cache --available && \ npm config set unsafe-perm true && \ npm install -g @angular/cli npm-snapshot && \ npm cache clean --force ENV CHROME_BIN=/usr/bin/chromium-browser ENV CHROME_DRIVER=/usr/bin/chromedriver # build step FROM env as dev COPY . src WORKDIR src RUN npm install && \ npm rebuild node-sass && \ ng build # lint and unit test FROM dev as test RUN ng lint && \ ng test --watch=false --browsers=Chrome_without_sandox # release stage FROM nginx:latest AS release COPY --from=dev src/dist/ /usr/share/nginx/html/
Thank you for taking the time to read my article. If you liked this post, share it with all of your programming buddies!
#angular #angular-js #docker #javascript #web-development