Skip to content

Devcontainer setup

VS Code features don't work with Podman

In VS Code, I had to abandon working with VS Code features, such as adding Zsh or ChezMoi to my devcontainer.

In a cryptic summary: these features need a BuildKit way of creating container images, and this is not yet compatible with Podman.

As a result, I had to change some of my devcontainer setups, switching to a more classical ContainerFile setup.

In my VS Code user settings, I have added my GitHub dotfiles repository, and that contains an install script with the software I want in my container.

settings.json
...
    "dotfiles.repository": "rolfkleef/dotfiles",
    "dotfiles.installCommand": "./install.sh",
    "dotfiles.targetPath": "~/.local/share/chezmoi",
...

With VS Code's support for a dotfiles repository in my user settings, I then use the install script in my dotfiles repository to add for instance Zsh and OhMyZsh to the container.

install.sh
#!/bin/sh

# -e: exit on error
# -u: exit on unset variables
set -eu

# 1. Upgrade packages (for Debian/Ubuntu-based images)
export DEBIAN_FRONTEND=noninteractive
apt-get update && apt-get upgrade -y

# 2. Install helpers
apt-get install -y zsh curl git nano

# 3. Install Oh My Zsh
if [ ! -d "$HOME/.oh-my-zsh" ]; then
  sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
fi

# 4. Set Zsh as the default shell for the container user
chsh -s $(which zsh) "$(whoami)"

# 5. Install and init chezmoi
sh -c "$(curl -fsLS get.chezmoi.io)" -- -b /usr/local/bin
chezmoi init --apply

I do have to run zsh by hand the first time a fresh container starts.

My conventions

  • At the moment, all my devcontainer setups are Debian/Ubuntu-based, so the install script above works everywhere.
  • I always use a bind mount to make my host directory available inside my container, and always in the directory /workspace. In both Docker Desktop and Podman, the user root within the container is mapped to the local user on the host system, and file permissions should work ok.
  • It also allows me to configure Zsh in my dotfiles to store its history in /workspace/.zsh_history, so it is stored in the host directory, to have a persistent shell history across container rebuilds.
  • The host directory typically contains a .env file. At a minimum, I specify a Compose project name and my timezone. When additional services like a database are included, this is a good place to include usernames and passwords for that.

    .env
    COMPOSE_PROJECT_NAME=drostan-notes
    TZ=Europe/Amsterdam
    

    and that file is added to the service for the devcontainer:

    compose.yml
    services:
      mkdocs:
        image: python:3.12
        command: sleep infinity
        volumes:
          - ..:/workspace
        env_file:
          - ../.env
    

Tip

To let a container also reach other services via localhost, add the following to its definition in compose.yml:

extra_hosts:

- localhost:host-gateway

Of course, this requires them to run on unique ports.