This repository builds an Ubuntu development image for Apple's container
runtime and provides shell helpers for opening project-scoped dev environments.
The default workflow is a named, long-running container:
devshell-start /path/to/projectThat command creates a container named devshell if it does not already exist,
bind-mounts only the chosen directory at /workspace, keeps the container
running in the background, and opens a shell into it. Later shells attach to the
same named container:
devshell-shellcontainer buildcreates an image. The image is the reusable Ubuntu template.devshell-start <dir>creates or enters a named ordinary container from that image. This is the default workflow.- The named container keeps running until it is stopped or deleted.
- The named container has exactly the host directory passed at creation time
mounted at
/workspace. - A container's mounts are fixed when the container is created. To use a different host directory with the same name, delete and recreate the devshell.
- Ubuntu 24.04
- Python 3,
venv,pip, anduv - Go from the current stable upstream tarball
- Rust stable through
rustup - Node.js LTS,
npm, Corepack, and Yarn - Git, Git LFS, and GitHub CLI
make,clang,clangd,lld,cmake,ninja- Neovim,
ripgrep,fd,fzf,jq,tmux,zsh,tree - PostgreSQL client and SQLite CLI
- Docker CLI, Buildx, and Compose plugin
Source the helper file from zsh or bash:
cd /path/to/container-devshell
source ./devshell.shTo load the helpers in every new terminal, add the source line to ~/.zshrc:
source /path/to/container-devshell/devshell.shThe helper defaults are:
DEVSHELL_NAME=devshell
DEVSHELL_IMAGE=local/devshell-ubuntu:latest
DEVSHELL_CPUS=8
DEVSHELL_MEMORY=16G
DEVSHELL_WORKDIR=/workspaceDEVSHELL_NAME controls the default named container.
Build the Ubuntu image:
devshell-buildOr run the underlying Apple commands from this repository:
container builder start --cpus 6 --memory 12G
container build --cpus 6 --memory 12G -t local/devshell-ubuntu:latest -f Containerfile .container builder start starts Apple's build service. container build reads
Containerfile, installs the tools, and stores the result as
local/devshell-ubuntu:latest.
Create or enter the default devshell:
devshell-start /path/to/projectInside the shell:
pwd # /workspace
whoami # your macOS username
lsFiles under /workspace are files from the host directory passed to
devshell-start. Files written there persist on macOS. Files written elsewhere
live in the named container until it is deleted.
Open another shell into the same running devshell:
devshell-shellStop the devshell:
devshell-stopStart it again and enter a shell:
devshell-shellDelete the devshell and its container-local filesystem:
devshell-deleteDeleting the devshell does not delete files in the mounted host directory.
Pass a name as the second argument to create a separate long-running devshell for another project:
devshell-start /path/to/project-a project-a
devshell-start /path/to/project-b project-bEnter one by name:
devshell-shell project-a
devshell-shell project-bStop or delete one by name:
devshell-stop project-a
devshell-delete project-aThe mount for a named devshell is set at creation time. To point project-a at
a different host directory:
devshell-delete project-a
devshell-start /new/path/to/project-a project-adevshell-build
Builds DEVSHELL_IMAGE from this repository's Containerfile.
devshell-builddevshell-create <host-dir> [name]
Creates a named, detached container with <host-dir> mounted at
DEVSHELL_WORKDIR, which defaults to /workspace. If [name] is omitted,
DEVSHELL_NAME is used.
devshell-create /path/to/project
devshell-create /path/to/project my-projectdevshell-start <host-dir> [name]
Creates the named devshell if needed, then opens a shell into it. If the devshell already exists, its existing mount is used.
devshell-start /path/to/projectdevshell-shell [name]
Opens a shell into an existing named devshell. If it was stopped,
container start is run first.
devshell-shell
devshell-shell my-projectdevshell-status [name]
Lists devshell containers in a compact table with source and destination mount columns. With a name, only that container is shown.
devshell-status
devshell-status my-projectdevshell-stop [name]
Stops a named devshell. The container and its filesystem remain available.
devshell-stop
devshell-stop my-projectdevshell-delete [name]
Deletes a named devshell. This removes the container-local filesystem, but not the mounted host directory.
devshell-delete
devshell-delete my-projectCheck the named-container workflow:
devshell-start /path/to/project
pwd
whoami
touch .devshell-write-test
exit
ls -l /path/to/project/.devshell-write-test
rm /path/to/project/.devshell-write-testCheck the mounted directory from macOS:
container list --all
devshell-statusList containers:
container list --allEnter a named devshell without the helper:
container start devshell
container exec -i -t --user "$(id -un)" -w /workspace devshell /bin/bashStop or delete a named devshell without the helper:
container stop devshell
container delete --force devshell