# A Dev Container for Bot Zero

**Date:** 2023-06-07  
**Author:** Kees C. Bakker  
**Categories:** PowerShell  
**Tags:** dev containers, Docker  
**Original:** https://keestalkstech.com/a-devcontainer-for-bot-zero/

![A Dev Container for Bot Zero](https://keestalkstech.com/wp-content/uploads/2023/06/robert-anasch-McX3XuJRsUM-unsplash.jpg)

---

For our [bot-zero project](https://github.com/wehkamp/bot-zero), 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](https://web.archive.org/web/20241104183652/https://keestalkstech.com/2023/06/github-windows-ssh-gpg-devcontainer/), I also described how to do the [installation and configuration of Git](https://keestalkstech.com/2024/10/notes-on-git-setup-with-ssh-for-windows-github/) and [GPG signing](https://keestalkstech.com/2024/03/setup-gpg-signing-on-windows/) 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:

```docker
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](https://www.npmjs.com/package/npm-check-updates) globally, so we can use

## Dev container config

Let's check our devcontainer.json:

```js
{
  "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.

```sh
#!/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:

```sh
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](https://stackoverflow.com/a/764972) 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:

```txt
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](https://dev.to/crumdev/vscode-dev-container-failing-to-build-ap4). 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](https://github.com/microsoft/vscode-remote-release/issues/8306).

## Further reading

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

- [Ken Muse: Avoiding Dubious Ownership in Dev Containers](https://www.kenmuse.com/blog/avoiding-dubious-ownership-in-dev-containers/)
- [Notes on Git Setup with SSH for Windows (GitHub)](https://keestalkstech.com/2024/10/notes-on-git-setup-with-ssh-for-windows-github/)
- [Setup GPG signing on Windows](https://keestalkstech.com/2024/03/setup-gpg-signing-on-windows/)

## Changelog

- 2024-11-04: rewritten the entire article and split off the notes Git and GPG.
- 2023-07-07: [initial article](https://web.archive.org/web/20241104183652/https://keestalkstech.com/2023/06/github-windows-ssh-gpg-devcontainer/).
