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 VARIABLES
section inman distrobox-create
.DBX_CONTAINER_MANAGER=docker
-
Create distrobox - see [[#fedora41-dx]] below -
distrobox assemble create
- note the use of aContainerfile
to 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
docker
for 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
cron
job orsystemd
unit to periodically exec thecreate.sh
script to recreate the container
Also note that the
Ptyxis
container integration does not support thedocker
engine. 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:
HOME
andUSER
are defined incontainerEnv
andremoteUser: "klmcw"
- I mount my home directory as a convenience. This is not strictly necessary.
- In a
devcontainer
the 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-settings
https://code.visualstudio.com/api/advanced-topics/remote-extensions#debugging-in-a-custom-development-container
https://github.com/ublue-os/toolboxes
https://github.com/klmcwhirter/freethreading_python