Dockerizing BigCommerce’s Stencil CLI

Aglensmith
BigCommerce Developer Blog
4 min readMay 28, 2020

--

I won’t be going over what Stencil CLI, Docker, or containers are in this post — I’ll assume you’re already familiar with the basic concepts. However, if this is something you’re approaching for the first time, I’ve included some primers to get you started in the Wrapping Up section section at the end.

Also included towards the bottom is a TL;DR with just the commands necessary to build and run the image if you’d prefer to skip my ramblings.

But Why?

Stencil CLI is a pretty sweet tool; however, like many other npm packages, the smallest misconfiguration in your node environment can make it a PITA to install. I know. I’ve been there.

I recently experienced package hell attempting to install Stencil CLI on a personal machine. I could have cleaned up my node environment (it was messed up like a soup sandwich) and resolved the issue; however I just wanted to tinker around a bit, and I was ready to show npm who’s boss once and for all. That’s when I remembered step one of the Efficiency Algorithm I mentioned in Tips for Optimizing Your Workflow: there’s a solution to your annoyance.

Luckily, in this case, I already knew the solution: containers. This is exactly the type of problem containers are meant to solve. So, why containerize Stencil CLI? I’ll get to the point:

  1. It’s fun and easy to setup
  2. It’s cross-platform
  3. It makes Stencil CLI easier to install
  4. It makes Stencil CLI easier to install
  5. ???
  6. Profit

Okay, now that you’re convinced, let’s dockerize this bad boy.

Installing Docker

First, if you don’t have docker installed, install it (docker.com) — GL HF DD (urbandictionary.com).

Creating the Dockerfile

Docker runs images. In order to run an image, the image must be built. A convenient way to build images is using a dockerfile. According to docs.docker.com:

A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession.

Here’s the dockerfile I use to build a basic Node.js and Stencil CLI image:

# use official node parent image
FROM node:10
# set container working directory
WORKDIR /theme
# install the cli
RUN npm -g config set user root
RUN npm install -g @bigcommerce/stencil-cli
# publish cli default port
EXPOSE 3000

I’ve pushed this dockerfile to a repo on my GitHub — feel free to clone, fork, or copy/paste to customize to your taste.

Building the Docker Image

Conveniently, docker build accepts URLs to dockerfiles. So, the image can be built on any machine with docker and access to the internet:

# build docker image
docker build -t docker-stencil https://github.com/aglensmith/docker-stencil-cli.git

Explanation

  • -t: name and optionally a tag in the ‘name:tag’ format

Running the Image Interactively

The basic command for running a docker image is as follows:

docker run [<IMAGE>][<COMMAND>]

However, if you execute docker run docker-stencil stencil start not much will happen. This is because, by default, docker runs the command passed in and immediately exits. To interact with Stencil, we’ll need to do a few things:

  • Run the image interactively and start a shell session so that we can run stencil init and other CLI commands.
  • Mount the current working directory to the/theme dir in the container’s file system so that stencil can access the theme files on the host machine.
  • Expose the default port used by stencil start and attach it to a port on the host machine so that we can browse to the theme preview.

Here’s the complete command:

user@host$: docker run -it -v $(pwd):/theme -p3000:3000 docker-stencil /bin/bash

Or, for bash on Windows:

user@host$: docker run -it -v /$(PWD):/theme -p3000:3000 docker-stencil //bin/bash

Run it to start a containerized bash shell:

root@54a89154e06c:/theme# ls -all
total 1398
drwxrwxrwx 2 root root 12288 Mar 10 23:28 .
drwxr-xr-x 1 root root 4096 Apr 23 15:07 ..
-rwxr-xr-x 1 root root 66 Mar 5 19:52 .eslintignore
...

exit to go back to the host machine’s CLI:

root@54a89154e06c:/theme# exit

Explanation:

  • -it : keep STDIN open and allocate a pseudo-TTY.
  • -v $(pwd):/theme: mount host’s current working directory (your theme dir) to container’s working directory (/theme — specified in dockerfile).
  • -p3000:3000 : expose stencil’s default port to localhost.

Initializing Stencil

If there’s not a .stencil configuration file in your theme directory, you’ll need to generate one. Also, don’t forget to install theme dependencies.

To do so, run the following commands:

# move into theme dir
user@host$: cd ~/path/to/theme/dir
# install theme dependencies
user@host$: npm install
# Run container and start bash
user@host$: sudo docker run -it -v $(pwd):/theme -p3000:3000 docker-stencil /bin/bash
# initialize stencil config
root@54a89154e06c:/theme#: stencil init

# exit back to host CLI
root@54a89154e06c:/theme#: exit

Starting Stencil

Once everything is configured, use docker run to start stencil:

user@host$: cd ~/path/to/theme/diruser@host$: docker run -it -v $(pwd):/theme -p3000:3000 docker-stencil stencil start

Pro-Tip:

  • Add an alias for the above command to your ~/.bash_profile or ~/.bashrc .

TL;DR

# build image
user@host$: docker build -t docker-stencil https://github.com/aglensmith/docker-stencil-cli.git
# move into theme dir
user@host$: cd ~/path/to/theme/dir
# install dependencies
user@host$: npm install
# run interactively
user@host$: sudo docker run -it -v $(pwd):/theme -p3000:3000 docker-stencil /bin/bash
# init stencil
root@54a89154e06c:/theme#: stencil init
# exit
root@54a89154e06c:/theme#: exit
# start stencil
user@host$:docker run -it -v $(pwd):/theme -p3000:3000 docker-stencil stencil start

Wrapping Up

What is this, a Christmas present? I’ve got nothing. Go dockerize Stencil CLI already. Oh yeah, below are the resources I promised.

Docker Primers

Docker Docs

Stencil Docs

--

--