Setting up my Exercism development environment
Using the Exercism development environment.
Organizing our development environment in a simple, practical and efficient way lets us focus on solving problems and therefore increases our productivity.
I find Exercism's organization practical. It has tracks associated with programming languages. Each track contains core and optional exercises with different difficulty levels, covering different aspects of the language.
The Exercism command-line interface
Exercism has a command-line interface for downloading exercises and uploading solutions. Since last year I have been trying to use Docker on every project. When I started practicing on Exercism, I did the same. Initially, I tried to install the Exercism CLI inside the image I was creating. After several attempts and errors, I realized that was not really necessary. It is better simply to install it on the operating system we use. This useful guide explains installation on different operating systems: CLI Walkthrough.
Docker image
Once the CLI was installed, the second step was creating an image for my containers. Here is my Dockerfile:
FROM node:10
# Install Global npm dependencies
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
# optionally if you want to run npm global bin without specifying path
ENV PATH=/home/node/.npm-global/bin:$PATH
It creates an image from the latest stable version of Node and configures npm for easy access inside my containers. The problem was that I was creating a container for every exercise, and each one was also building an image. I decided to publish the image to DockerHub so I would not need to build it for every container. Initially, I tried the push command, but received an error when logging into DockerHub. The problem was that I use WSL Ubuntu, which does not use X11. This solves it: https://github.com/docker/compose/issues/6023#issuecomment-419792269
After experimenting with DockerHub, I realized it was much more efficient to create a repository there and connect it to one on GitHub, as explained in this guide. Each change to our Dockerfile on GitHub then automatically generates a new image version on DockerHub. There are many configuration options, and we need to evaluate what is practical for each project. If you do not want to publish your image on DockerHub or your Dockerfile on GitHub, you can configure your own Docker image registry, as this article explains. Here are the image and repository I created:
Container
This is the docker-compose.yaml file I use to create the containers:
version: '3'
services:
node:
image: webcu/exercism-js:latest
volumes:
- .:/src
- node_modules:/src/node_modules
working_dir: /src
command: tail -f /dev/null
volumes:
node_modules:
external: true
Before using docker-compose, we must create the node_modules volume. This lets us reuse already-installed modules without running npm install again, saving time and avoiding symlink problems on Windows.
Initially, I downloaded a new exercise, copied docker-compose.yaml, navigated to the exercise folder from WSL and ran:
- docker-compose up -d
- docker-compose exec node bash
Inside the container I ran tests using:
- npm test
This worked, but I was still creating a container for each exercise even though they all used the same dependencies. I made a small change to create just one container for the JS track. I copied docker-compose.yaml and package.json to the track's root instead of each exercise folder. The container worked: it installed every dependency and could access all downloaded exercises. The tests, however, did not work. I am not very familiar with Jest configuration, but fortunately the solution was much simpler than expected. All I needed to do was copy babel.config.js to the JS track's root. Voilà, problem solved! Now I can run the tests for all exercises or just one specific exercise.