I've been having fun playing with GitHub codespaces. One of the things that has seemed odd to me is the language-specific
development environments. Most projects—even small side projects—have multiple languages. Composing these images feels
messy. I've always enjoyed asdf
for managing language versions in a unified fashion.
This project builds a devcontainer image (for use with GitHub Codespace) setup with asdf support. It also includes a nice
utility script for installing all asdf plugins, finding all .tool-versions
files, installing the versions specified,
and starting up a docker-compose.yml
if one exists.
Here's my blog post which walks through this in detail.
Main design goals:
- Include all relevant packages that most popular languages require for install. The
Dockerfile
is very aggressive with including many packages so the container can install asdf packages in many languages. I am no sysadmin so there may be negative side effects with this approach. - Fix homebrew not working due to out of date image. This means
apt-get update
in the build, combined with a monthly gh actions cron, fixes this. - Easily install all asdf plugins used in a project.
/asdf-post-create.sh
finds all.tool-versions
included in the repo and installs the relevant asdf plugins. - Easily start
docker-compose
services. For instance, if your project requires postgres + redis, you can include adocker-compose.yml
file in.devcontainer/
and it will be started when you run/asdf-post-create.sh
.
Here are the languages I've confirmed compile and run via asdf on this image:
- Elixir + Erlang
- Python
- Ruby
- NodeJS
- Deno
- Bun
- PHP
Check out devcontainer-example
folder for how to use this in your application.
Here's how to easily copy the example into your project:
mkdir .devcontainer && cd .devcontainer && curl https://codeload.github.com/iloveitaly/asdf-devcontainer/tar.gz/main | tar -xz --strip=2 asdf-devcontainer-main/devcontainer-example
If you clone the repo locally, here's a quick script to copy:
cp -R ~/Projects/asdf-devcontainer/devcontainer-example your-new-project/.devcontainer
Here's what your devcontainer.json
should look like:
{
"image": "iloveitaly/asdf-devcontainer:0-ubuntu-22.04",
"postCreateCommand": "/asdf-post-create.sh && bin/setup",
"remoteUser": "vscode",
"features": {
"homebrew": "latest",
"ghcr.io/devcontainers/features/sshd:1": {
"version": "latest"
},
"ghcr.io/devcontainers/features/docker-in-docker:1": {
"version": "latest",
"dockerDashComposeVersion":"v2"
}
}
}
Easiest way to iterate on this image is to setup a codespace and rebuild the Dockerfile. Some tips:
- What base variants exist?
http https://mcr.microsoft.com/v2/vscode/devcontainers/base/tags/list | fzf
- Build on a different base variant
docker build -t asdf-devcontainer . --build-arg VARIANT=dev-ubuntu
- Run a shell inside the image
docker run --rm -it asdf-devcontainer bash -lc
- Get github webhook structure for github actions development
gh api repos/iloveitaly/asdf-devcontainer/events
- View all available devcontainer features
- Devcontainers open source spec