A Dev Container for Bot Zero

For our bot-zero project, we've decided to go all in on dev containers. What's not to love? You can basically ship a development environment complete with node 22 and all the Visual Studio Code extensions we need. And if you don't want to use a dev container? That's also fine!

In a previous version of this article, I also described how to do the installation and configuration of Git and GPG signing on Windows, but let's adhere to the principle of single responsibility and focus on the dev container alone.

Dockerfile

Let's bring our own Dockerfile. Why? Docker uses layers. Installing global packages as layers will help to prevent doing installs over and over again:

FROM mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm

# Upgrade NPM
RUN npm install -g npm@10.9.0 --no-audit --no-fund

# Install global packages
RUN npm install --no-audit --no-fund --global \
    npm-check-updates

COPY ./startup.sh /
RUN chmod +x /startup.sh

# Append the pofile to the current .bashrc and .zshrc files
# this makes sure we keep the current behaviour like colors and aliases
COPY ./.profile /tmp/.profile
RUN cat /tmp/.profile >> /home/vscode/.bashrc && \
    cat /tmp/.profile >> /home/vscode/.zshrc && \
    rm /tmp/.profile

So what's in here? We update NPM, to get rid of the update nags and we install npm-check-updates globally, so we can use

Dev container config

Let's check our devcontainer.json:

{
  "name": "Bot Zero",
  "dockerFile": "Dockerfile",
  "customizations": {
    "vscode": {
      "extensions": [
	  "ms-azuretools.vscode-docker",
	  "esbenp.prettier-vscode",
	  "streetsidesoftware.code-spell-checker",
	  "mikestead.dotenv",
	  "herrmannplatz.npm-dependency-links",
	  "wayou.vscode-todo-highlight",
	  "nsoult.typescript-imports-sort"
      ]
    }
  },
  "postStartCommand": "/startup.sh"
}

Not much to see here. Of course we install a bunch of extensions into Visual Studio Code, which will make it easier to code. Whenever the container is started, we'll run /startup.sh. After the startup is done, we'll open up a bash shell in which our developers can start interacting with the container.

Startup script

Startup scripts are ran whenever we start the container. This is a great place to correct some problems with git, install our dependencies and to copy the example environments file.

#!/bin/sh

set -e

# trust the repo
# fixes:
# - fatal:   detected dubious ownership in repository at '/workspaces/bot-zero'.
# - warning: safe.directory 'C:/{...}/blaze-platform-provisioning' not absolute
git config --global --unset-all safe.directory > /dev/null 2>&1
git config --global --add safe.directory "$PWD"

# install NPM packages
echo ""
echo "Installing packages..."
npm install --no-audit --no-fund

# copy example.env to .env
if [ ! -f .env ]; then
    echo ""
    echo "Copying .example.env to .env..."
    cp .example.env .env
fi

You can execute these commands by hand, but you'll need to redo this every time you rebuild your container, which isn't very user friendly.

To make this work under Windows, I needed to make sure that the line endings were setup correctly. Otherwise you'll get some weird \r exceptions when executing the script in Docker.

.profile

Our first time users might not know what to do, so let's echo a user friendly message on how to start the project when they open up the terminal in Visual Studio Code:

NC='\033[0m' # no color
YELLOW='\033[1;33m'

# echo start instructions
echo -e "To start your bot-zero instance, please enter: ${YELLOW}npm run dev${NC}"
echo ""

The .profile is written in POSIX shell and should run on both ZSH and Bash.

Visual Studio Code Dev Container Extension Problems: Wayland socket

If you run into bind problems, like this:

docker: Error response from daemon: invalid mount config for type 
"bind": bind source path does not exist: 
\\wsl.localhost\Ubuntu\mnt\wslg\runtime-dir\wayland-0

Do the following:

  1. Navigate to \\wsl.localhost\Ubuntu\mnt\wslg\runtime-dir\
  2. Remove the file wayland-0
  3. Remove the file wayland-0.lock
  4. Reopen and rebuild your dev container in VSCode.

Thanks Nathan Crum. In a previous discussion I reverted to version 0.266.1 of the dev container extension, but with this fix, you can just upgrade to the latest and greatest. Not 100% sure, but I think it has something to do with running Racher Desktop.

Further reading

While researching how to set this up, I've use the following sources:

Changelog

  • rewritten the entire article and split off the notes Git and GPG.
  • initial article.
expand_less brightness_auto