It can be useful to run build steps inside a Docker container, to handle isolation between environments (prevent conflicts between dependency versions), enable development on different operating systems (macOS, Linux, Windows) and reliable builds (a stable build environment).
There are some obstacles you will encounter when trying to setup such an environment. I went through them, and created an example boilerplate project which shows some of the setup. (Note that I have set up a project which uses yarn instead of npm; it is perfectly possible to create a similar setup that uses npm.)
You can check out the full code example on GitHub:
https://github.com/eirslett/chrome-karma-docker
From the official node.js image, it’s possible to install Chrome from the official .deb package.
Also note that I add dumb-init; it saves you from a lot of pain and annoyance, like when you’re trying to use Ctrl+C to stop your container.
FROM node:8.2.1
_# OPTIONAL: Install dumb-init (Very handy for easier signal handling of SIGINT/SIGTERM/SIGKILL etc.)_RUN wget https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.debRUN dpkg -i dumb-init_*.debENTRYPOINT ["dumb-init"]
_# Install Google Chrome_RUN wget **-**q **-O - https://dl-ssl.google.com/linux/**linux_signing_key.pub | apt-key add -RUN sh **-**c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'RUN apt-get update && apt-get install **-**y google-chrome-stable
**WORKDIR /opt/**app
ADD package.json yarn.lock /opt/app/RUN yarn
It turns out there are some problems with running Chrome inside Docker. Unless you’re running the container in privileged mode, Chrome’s sandbox won’t work. We use the is-docker package to detect whether the process is running inside a Docker container or not. Based on that, we’ll have to tweak our build configuration:
const isDocker = require('is-docker')();
module.exports = config => config.set({customLaunchers: {ChromeCustom: {base: 'ChromeHeadless',// We must disable the Chrome sandbox when running Chrome inside Docker (Chrome's sandbox needs// more permissions than Docker allows by default) flags: isDocker ? ['--no-sandbox'] : []}}// more karma configuration here...}
Karma should be run with the ChromeCustom browser.
If you want to run Webpack or webpack-dev-server inside a container, you should use the is-docker detection and tweak a few configurations:
Instead of running docker run with an insane number of arguments, we can use docker-compose.yml to set configuration parameters:
**version: '3'
services:dev:build:context:** .dockerfile: docker/dev/Dockerfileworking_dir: /opt/appcontainer_name: "dev"volumes: - "./:/opt/app" - /opt/app/node_modules
This will let us run “docker-compose run dev XXX”, which will start the Docker container with “XXX” as a command, for example
If it’s possible to work on your project without running inside Docker, that might be preferable, since you can avoid the overhead of containerization. Then, you should be able to “yarn run [whatever-command]” directly.
If you prefer to work on the project within a container, you can use “docker-compose run dev yarn run [whatever-command]” to run inside a container.
Tip: add a helper script “container.sh” to your working directory:
**#!/bin/bash**docker-compose run dev $@
Then you can run “./container.sh yarn run [whatever-command]”, which is a bit shorter.
Make sure Docker is installed on the CI instance. (duh!)
You probably want to rebuild the container for every CI run:
docker-compose build
After that, you can run CI build scripts inside the container the same way;
docker-compose run dev yarn run build
That’s all. Good luck with your containerized builds!