bluefin - use docker distrobox container in vscode
To use a bluefin distrobox in vscode as a devcontainer, do the following to create a docker distrobox, and then use the same OCI image to create devcontainer(s) from vscode.
steps
-
Setup env vars to assure distrobox uses docker - see the
ENVIRONMENT VARIABLESsection inman distrobox-create.DBX_CONTAINER_MANAGER=docker -
Create distrobox - see [[#fedora41-dx]] below -
distrobox assemble create- note the use of aContainerfileto create the image to be shared with devcontainers. This is done to minimize creation time and disk utilization. -
Use Dev Containers: Open Folder in Container…
Note that when using
dockerfor distrobox containers the quadlet systemd feature cannot be used as documented to update containers. Do this instead.
- be disciplined to only modify files that exist in bind mounted volumes (e.g., the home dir in my example)
- setup a
cronjob orsystemdunit to periodically exec thecreate.shscript to recreate the container
Also note that the
Ptyxiscontainer integration does not support thedockerengine. Although, this makes container integration useless, in my opinion - as it is only a partial solution.
fedora41-dx
Please note the ublue-os/toolboxes repo. I am using the fedora-toolbox.
Here is the Containerfile I use. This is where I install all the software I need - as opposed to in distrobox.ini.
I do this to promote finer-grained OCI image layer sharing.
FROM ghcr.io/ublue-os/fedora-toolbox:latest
ARG USER # `create.sh` sets this to the value of the $USER env var
ARG NEW_UID=1000
ARG NEW_GID=1000
RUN if ! grep "${USER}" /etc/group >/dev/null 2>&1;then sudo groupadd -g ${NEW_GID} ${USER};fi
RUN if ! grep "${USER}" /etc/passwd >/dev/null 2>&1;then sudo useradd -g ${NEW_GID} -u ${NEW_UID} ${USER};fi
RUN dnf update -y
RUN dnf install -y emacs-nw info texinfo git vim tmux fastfetch fzf zoxide
RUN dnf install -y python3 python3-tkinter python3.14 python3.14-freethreading python3.14-tkinter tk gitk git-gui
# VS Code is installed in here for vscode-server primarily.
# But the `code` CLI utility can also be used from a terminal session connected to the container.
RUN rpm --import https://packages.microsoft.com/keys/microsoft.asc
RUN echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com/yumrepos/vscode\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" | tee /etc/yum.repos.d/vscode.repo > /dev/null
RUN dnf update -y
RUN dnf install -y code
USER ${NEW_UID}:${NEW_UID}
WORKDIR /var/home/${USER}
This is a snippet from the distrobox.ini I am using that focuses on the vscode prerequisites. With this approach I install the additional software I need via a Containerfile
[fedora41-dx]
image=klmcwhirter/fedora41-dx:latest
init=false
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/local/bin/starship;
nvidia=true
pull=0
root=false
start_now=true
home=/var/home/klmcw
exported_bins="/usr/bin/python3.14 /usr/bin/python3.14t /usr/bin/gitk"
exported_bins_path="/var/home/klmcw/.local/bin"
And this is the create.sh script I use to create the OCI image and the distrobox. Note that DBX_CONTAINER_ALWAYS_PULL=0 is used to prevent having to push the image to a registry; i.e., it only exists locally.
#!/bin/bash
# Create image
${DBX_CONTAINER_MANAGER} build -f Containerfile -t klmcwhirter/fedora41-dx:latest --build-arg USER=$USER .
# assemble
DBX_CONTAINER_ALWAYS_PULL=0 distrobox assemble create --replace
Then the devcontainer is defined like this in the project (.devcontainer/devcontainer.json).
Important details:
HOMEandUSERare defined incontainerEnvandremoteUser: "klmcw"- I mount my home directory as a convenience. This is not strictly necessary.
- In a
devcontainerthe extensions mentioned are installed automatically.
// For format details, see https://aka.ms/devcontainer.json.
{
"name": "explore_python",
"image": "klmcwhirter/fedora41-dx:latest", // also matches `create.sh`
"runArgs": [
"--name",
"explore-python"
],
"containerEnv": {
"HOME": "/var/home/klmcw",
"TZ": "PST8PDT",
"USER": "klmcw"
},
"mounts": [
{
"source": "/var/home/klmcw",
"target": "/var/home/klmcw",
"type": "bind"
}
],
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {},
// Use 'initializeCommand' to run commands on the host machine during initialization
"initializeCommand": {
"start time": "date"
},
// Use 'onCreateCommand' to run commands during the container creation process.
"onCreateCommand": ".devcontainer/vsc-install-pdm.sh",
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": {
"pwd": "pwd",
"uname": "uname -a",
"pdm version": "pdm --version",
"python version": "python --version",
// "build & run pytests": "ENABLE_TESTS=1 .devcontainer/vsc-run-pytests.sh",
},
// Use 'postStartCommand' to run commands after the container is created.
"postStartCommand": {
"end time": "date"
},
// Configure tool-specific properties.
"customizations": {
"vscode": {
"extensions": [
"charliermarsh.ruff",
"tamasfe.even-better-toml",
"streetsidesoftware.code-spell-checker",
"ms-python.isort"
],
"settings": {
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "charliermarsh.ruff"
},
"python.terminal.activateEnvironment": true,
"terminal.integrated.defaultProfile.linux": "bash"
}
}
},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
"remoteUser": "klmcw"
}
See my freethreading_python repo for the scripts that are referenced.
By reusing the OCI image, most of the layers will be shared between the distrobox and devcontainer.
References
https://code.visualstudio.com/docs/devcontainers/containers#_container-specific-settingshttps://code.visualstudio.com/api/advanced-topics/remote-extensions#debugging-in-a-custom-development-containerhttps://github.com/ublue-os/toolboxeshttps://github.com/klmcwhirter/freethreading_python