Add rootless podman image - #339
Conversation
Ports the podman image from the archived community-templates repo so it has a maintained home. Installs podman from Ubuntu's own repositories instead of the kubic unstable repo, and grants subuid/subgid ranges to the standard coder user instead of a separate podman user.
apt-key was removed from the resolute base image, which has failed every build since Aug 10 (including scheduled rebuilds on main). Trust the Yarn repository via a signed-by keyring instead. Verified locally: node v24.19.0, yarn 1.22.22.
nickvigilante
left a comment
There was a problem hiding this comment.
Approving. The design is sound and consistent with the repo's conventions, and CI is green (images/ubuntu + quick). Everything below is non-blocking.
Looks good
- Wrapping
enterprise-baseso the standard uid-1000coderuser gets the subuid/subgid ranges is the right call, andbuild_images.sh/push_images.shwill publishcodercom/example-podman(primary) +codercom/enterprise-podman(alias) with the dated/version tags like every other image. - Installing podman/crun/fuse-overlayfs from Ubuntu's own repos instead of the kubic unstable repo is a real maintainability win.
/var/lib/sharedread-only stores and the fuse-overlayfsmount_programare set up correctly.
Non-blocking follow-ups
- Document the writable-storage expectation for
graphroot/runroot(inline onstorage.conf) so the image is usable outside the paired coder/coder#28100 template. - The node Yarn fix is unrelated scope — consider splitting or noting it (inline).
_CONTAINERS_USERNS_CONFIGURED=""looks like a no-op — drop or comment (inline).
Minor nits
- README badge differs from the sibling READMEs (
DockerPullsvsDocker Pulls, missing?label=); since Podman is brand new you could point it atexample-podmanper the top-level README's recommendation. slirp4netnsisn't exercised withnetns="host"(resolute defaults to pasta) — harmless fallback.cgroups="disabled"means no per-container resource limits orpodman stats— worth a README line.
Note: PR CI builds but doesn't run or push the image, so green means "builds on resolute," not "rootless run verified" — that rests on the EKS test, which is good enough here.
Review drafted with AI assistance (Coder Agents).
|
|
||
| ## How To Use | ||
|
|
||
| See |
| runroot = "/run/containers/storage" | ||
|
|
||
| # Primary read/write location of container storage | ||
| graphroot = "/var/lib/containers/storage" |
There was a problem hiding this comment.
Non-blocking question: runroot (/run/containers/storage) and graphroot (/var/lib/containers/storage) sit under root-owned paths, and the image ends as USER coder (uid 1000) without creating/chowning them. Does rootless Podman here rely on the workspace mounting writable volumes at those paths (as the coder/coder#28100 template does)? If so, a one-line note in the README would help anyone using the image on its own. The /var/lib/shared read-only stores look correctly handled.
From Coder Agents 🤖
There was a problem hiding this comment.
Good question — neither, actually: rootless Podman ignores runroot/graphroot (those are rootful paths) and stores under ~/.local/share/containers/storage, which lands on the workspace home volume. That's why the verified runs worked with no extra mounts. Added a note to both storage.conf and the README.
(posted via Coder Agents on my behalf)
| # Install Yarn. apt-key was removed from modern Ubuntu releases, so trust | ||
| # the Yarn repository via a signed-by keyring instead. | ||
| RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor -o /usr/share/keyrings/yarnkey.gpg && \ | ||
| echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ | ||
| DEBIAN_FRONTEND="noninteractive" apt-get update && apt-get install -y yarn |
There was a problem hiding this comment.
Unrelated to the Podman image (Yarn keyring fix). It's correct and probably necessary now that apt-key is gone on resolute — but it's invisible in the PR title/body. Worth splitting into its own small PR (would unblock main on its own) or at least calling it out in the description.
From Coder Agents 🤖
There was a problem hiding this comment.
Called it out in the description instead of splitting — main is red either way and this unblocks it in one go.
(posted via Coder Agents on my behalf)
| /var/lib/shared/vfs-images/images.lock \ | ||
| /var/lib/shared/vfs-layers/layers.lock | ||
|
|
||
| ENV _CONTAINERS_USERNS_CONFIGURED="" |
There was a problem hiding this comment.
ENV _CONTAINERS_USERNS_CONFIGURED="" looks like a no-op — Podman sets this internally after it re-execs into a user namespace and gates on a non-empty value, so an empty string reads the same as unset (and ENV foo="" doesn't unset an inherited value either). Fine to drop it, or add a comment if it's intentionally mirroring the archived image.
From Coder Agents 🤖
There was a problem hiding this comment.
Agreed, it's a no-op carried over from the archived image — dropped.
(posted via Coder Agents on my behalf)
nickvigilante
left a comment
There was a problem hiding this comment.
LGTM! Coder Agents found a few things, and I'm refactoring my PR based on this.
…recation and EKS Auto Mode (DOCS-645) Addresses review feedback on #28100: - Swap ghcr.io/coder/podman for the maintained codercom/example-podman image and link its source (coder/images#339). - Note that the AppArmor annotation is deprecated on Kubernetes 1.30+. - Add an EKS Auto Mode caveat to the Bottlerocket section.
…CS-645) The tree/main/images/podman path 404s until coder/images#339 merges, which fails the docs linkspector (check-docs) job. Link the repo root, which stays valid regardless of merge order.
- Drop the no-op _CONTAINERS_USERNS_CONFIGURED env (Podman sets it internally after re-exec; an empty value reads the same as unset) - Document that runroot/graphroot are rootful-only and rootless storage lands on the home volume - README wording: See -> Visit
…cker-in-workspaces) (#28100) ## Summary Fixes broken examples on the `extending-templates` pages surfaced by the DOCS-637 runtime drift sweep, and completes the dangling `external-auth` reference. Verified against `main` and the CLI source (`coder templates init --id`, `coder templates push`). ## Changes | Page | Fix | |------|-----| | `dynamic-parameters.md` | The **Dynamic Validation** snippet referenced an undefined `show_cpu_cores` through a stray `count = data.coder_parameter.show_cpu_cores.value ? 1 : 0` line copied from the earlier Hide/Show Options example. Standalone copy failed `terraform validate`. Removed the `count` line (and its misleading "Only show this parameter" comment) so the snippet is self-contained. The valid occurrence in the Hide/Show example (where `show_cpu_cores` is defined) is untouched. | | `docker-in-workspaces.md` | The rootless Podman step used `echo "kubernetes-with-podman" \| coder templates init`, but `kubernetes-with-podman` isn't a built-in starter id, so the command scaffolds nothing. Step 4 now starts from the built-in `kubernetes` starter (`coder templates init --id kubernetes`) and shows the minimal Podman delta inline: the maintained `codercom/example-podman:ubuntu` base image, the `container.apparmor.security.beta.kubernetes.io/dev = unconfined` pod annotation, and a `github.com/fuse` device limit. The starter already runs as UID/GID 1000 with `run_as_non_root`, which rootless Podman needs. Also switches the deprecated `coder templates create` to `coder templates push`. Follow-up from review: swapped `ghcr.io/coder/podman` for the maintained `codercom/example-podman:ubuntu` image and linked its source, added a note that the AppArmor annotation is deprecated on Kubernetes 1.30+ (`securityContext.appArmorProfile`), and added an EKS Auto Mode caveat to the Bottlerocket section. | | `external-auth.md` | The **External Auth Providers** sentence dead-ended at "...in the Coder Control Plane. See" with no link. Completed it with a link to the admin External Authentication page (`../../external-auth/index.md`), the target chosen in review. | ## Dependency The `docker-in-workspaces.md` example now references `codercom/example-podman:ubuntu`, published by coder/images#339. That PR is approved but should merge (and publish the image to Docker Hub) before this PR merges, so the docs don't point at an image that doesn't exist yet. Linear: https://linear.app/codercom/issue/DOCS-645 > This PR was created with AI assistance (Coder Agents). --------- Co-authored-by: Ben Potter <me@bpmct.net> Co-authored-by: Ben Potter <ben@coder.com>
…cker-in-workspaces) (#28100) ## Summary Fixes broken examples on the `extending-templates` pages surfaced by the DOCS-637 runtime drift sweep, and completes the dangling `external-auth` reference. Verified against `main` and the CLI source (`coder templates init --id`, `coder templates push`). ## Changes | Page | Fix | |------|-----| | `dynamic-parameters.md` | The **Dynamic Validation** snippet referenced an undefined `show_cpu_cores` through a stray `count = data.coder_parameter.show_cpu_cores.value ? 1 : 0` line copied from the earlier Hide/Show Options example. Standalone copy failed `terraform validate`. Removed the `count` line (and its misleading "Only show this parameter" comment) so the snippet is self-contained. The valid occurrence in the Hide/Show example (where `show_cpu_cores` is defined) is untouched. | | `docker-in-workspaces.md` | The rootless Podman step used `echo "kubernetes-with-podman" \| coder templates init`, but `kubernetes-with-podman` isn't a built-in starter id, so the command scaffolds nothing. Step 4 now starts from the built-in `kubernetes` starter (`coder templates init --id kubernetes`) and shows the minimal Podman delta inline: the maintained `codercom/example-podman:ubuntu` base image, the `container.apparmor.security.beta.kubernetes.io/dev = unconfined` pod annotation, and a `github.com/fuse` device limit. The starter already runs as UID/GID 1000 with `run_as_non_root`, which rootless Podman needs. Also switches the deprecated `coder templates create` to `coder templates push`. Follow-up from review: swapped `ghcr.io/coder/podman` for the maintained `codercom/example-podman:ubuntu` image and linked its source, added a note that the AppArmor annotation is deprecated on Kubernetes 1.30+ (`securityContext.appArmorProfile`), and added an EKS Auto Mode caveat to the Bottlerocket section. | | `external-auth.md` | The **External Auth Providers** sentence dead-ended at "...in the Coder Control Plane. See" with no link. Completed it with a link to the admin External Authentication page (`../../external-auth/index.md`), the target chosen in review. | ## Dependency The `docker-in-workspaces.md` example now references `codercom/example-podman:ubuntu`, published by coder/images#339. That PR is approved but should merge (and publish the image to Docker Hub) before this PR merges, so the docs don't point at an image that doesn't exist yet. Linear: https://linear.app/codercom/issue/DOCS-645 > This PR was created with AI assistance (Coder Agents). --------- Co-authored-by: Ben Potter <me@bpmct.net> Co-authored-by: Ben Potter <ben@coder.com>
The rootless Podman docs (and a bunch of templates in the wild) reference
ghcr.io/coder/podman, but its Dockerfile lives in the now-archived community-templates repo, so the image is published-but-orphaned. This gives it a maintained home here, published ascodercom/example-podman:ubuntu(+enterprise-alias) like the rest.Changes from the archived version:
enterprise-baselike our other images instead of rawubuntu:22.04, so the standardcoderuser (uid 1000) gets the subuid/subgid ranges rather than a separatepodmanuserstorage.confto the settings we actually overrideAlso includes an unrelated CI fix:
images/nodewas broken byapt-keybeing removed from theresolutebase image, which has failed every build onmainsince Aug 10 (including scheduled rebuilds). The Yarn repo is now trusted via asigned-bykeyring instead. Bundled here since CI can't pass without it.Verified the setup end-to-end on an EKS cluster with the recipe from coder/coder#28100: rootless
podman run hello-worldworks as uid 1000, unprivileged, fuse-overlayfs driver. Follow-up: point the docker-in-workspaces docs at this image once it publishes.