From 9f8d502a940363f8f33fa55f9d0c413663393e68 Mon Sep 17 00:00:00 2001 From: Ben Potter Date: Mon, 6 Jul 2026 18:40:47 +0000 Subject: [PATCH 01/10] docs(coderd/templatebuilder): add workspace image guidance to docker and kubernetes prerequisites --- coderd/templatebuilder/bases/docker/README.md | 11 +++++++++++ coderd/templatebuilder/bases/docker/base.json | 2 +- coderd/templatebuilder/bases/kubernetes/README.md | 11 ++++++++++- coderd/templatebuilder/bases/kubernetes/base.json | 2 +- coderd/templatebuilder/bases_test.go | 4 ++-- coderd/templatebuilder/testdata/docker.tf.golden | 2 +- coderd/templatebuilder/testdata/kubernetes.tf.golden | 2 +- 7 files changed, 27 insertions(+), 7 deletions(-) diff --git a/coderd/templatebuilder/bases/docker/README.md b/coderd/templatebuilder/bases/docker/README.md index 6398547ef5f..bc9085ae3dc 100644 --- a/coderd/templatebuilder/bases/docker/README.md +++ b/coderd/templatebuilder/bases/docker/README.md @@ -17,6 +17,17 @@ Provision Docker containers as [Coder workspaces](https://coder.com/docs/user-gu ## Prerequisites +### Workspace image + +The container image determines what tools, languages, and runtimes are available in the workspace out of the box, so it has a major impact on the developer experience. + +Some options to consider: + +- [`codercom/example-base:ubuntu`](https://github.com/coder/images/tree/main/images/base) (default): minimal and lightweight, but may not include many tools developers expect by default +- [`codercom/example-universal:ubuntu`](https://github.com/coder/images/tree/main/images/universal): catch-all image with many languages and tools available, but larger and slower to pull + +More language-specific images (Go, Java, Node.js, and more) are available in [coder/images](https://github.com/coder/images), and the [devcontainers/images](https://github.com/devcontainers/images) collection is another good source of ready-made development images. You can also build your own image to pre-bake the exact tools your team needs. See [Coder's image management docs](https://coder.com/docs/admin/templates/managing-templates/image-management) for additional guidance. + ### Infrastructure The VM you run Coder on must have a running Docker socket and the `coder` user must be added to the Docker group: diff --git a/coderd/templatebuilder/bases/docker/base.json b/coderd/templatebuilder/bases/docker/base.json index 09b8224c014..e2feddc8d5e 100644 --- a/coderd/templatebuilder/bases/docker/base.json +++ b/coderd/templatebuilder/bases/docker/base.json @@ -3,6 +3,6 @@ "display_name": "Docker", "os": "linux", "default_context": { - "container_image": "codercom/enterprise-base:ubuntu" + "container_image": "codercom/example-base:ubuntu" } } diff --git a/coderd/templatebuilder/bases/kubernetes/README.md b/coderd/templatebuilder/bases/kubernetes/README.md index 26e7e07e381..b1fceb7e219 100644 --- a/coderd/templatebuilder/bases/kubernetes/README.md +++ b/coderd/templatebuilder/bases/kubernetes/README.md @@ -21,7 +21,16 @@ Provision Kubernetes Pods as [Coder workspaces](https://coder.com/docs/user-guid **Cluster**: This template requires an existing Kubernetes cluster -**Container Image**: This template uses the [codercom/enterprise-base:ubuntu image](https://github.com/coder/enterprise-images/tree/main/images/base) with some dev tools preinstalled. To add additional tools, extend this image or build it yourself. +### Workspace image + +The container image determines what tools, languages, and runtimes are available in the workspace out of the box, so it has a major impact on the developer experience. + +Some options to consider: + +- [`codercom/example-base:ubuntu`](https://github.com/coder/images/tree/main/images/base) (default): minimal and lightweight, but may not include many tools developers expect by default +- [`codercom/example-universal:ubuntu`](https://github.com/coder/images/tree/main/images/universal): catch-all image with many languages and tools available, but larger and slower to pull + +More language-specific images (Go, Java, Node.js, and more) are available in [coder/images](https://github.com/coder/images), and the [devcontainers/images](https://github.com/devcontainers/images) collection is another good source of ready-made development images. You can also build your own image to pre-bake the exact tools your team needs. See [Coder's image management docs](https://coder.com/docs/admin/templates/managing-templates/image-management) for additional guidance. ### Authentication diff --git a/coderd/templatebuilder/bases/kubernetes/base.json b/coderd/templatebuilder/bases/kubernetes/base.json index a3b04acbaa9..89dcd59dc7e 100644 --- a/coderd/templatebuilder/bases/kubernetes/base.json +++ b/coderd/templatebuilder/bases/kubernetes/base.json @@ -3,7 +3,7 @@ "display_name": "Kubernetes", "os": "linux", "default_context": { - "container_image": "codercom/enterprise-base:ubuntu" + "container_image": "codercom/example-base:ubuntu" }, "variables": [ { diff --git a/coderd/templatebuilder/bases_test.go b/coderd/templatebuilder/bases_test.go index cb2109331c1..f01f6f48a04 100644 --- a/coderd/templatebuilder/bases_test.go +++ b/coderd/templatebuilder/bases_test.go @@ -65,14 +65,14 @@ func TestDefaultBaseRenderContext(t *testing.T) { t.Run("Docker", func(t *testing.T) { t.Parallel() rc := templatebuilder.DefaultBaseRenderContext("docker") - require.Equal(t, "codercom/enterprise-base:ubuntu", rc.ContainerImage) + require.Equal(t, "codercom/example-base:ubuntu", rc.ContainerImage) require.Nil(t, rc.ImageOptions) }) t.Run("Kubernetes", func(t *testing.T) { t.Parallel() rc := templatebuilder.DefaultBaseRenderContext("kubernetes") - require.Equal(t, "codercom/enterprise-base:ubuntu", rc.ContainerImage) + require.Equal(t, "codercom/example-base:ubuntu", rc.ContainerImage) require.Nil(t, rc.ImageOptions) }) diff --git a/coderd/templatebuilder/testdata/docker.tf.golden b/coderd/templatebuilder/testdata/docker.tf.golden index 11d9ded4f64..9efa2ee27a7 100644 --- a/coderd/templatebuilder/testdata/docker.tf.golden +++ b/coderd/templatebuilder/testdata/docker.tf.golden @@ -150,7 +150,7 @@ resource "docker_volume" "home_volume" { resource "docker_container" "workspace" { count = data.coder_workspace.me.start_count - image = "codercom/enterprise-base:ubuntu" + image = "codercom/example-base:ubuntu" # Uses lower() to avoid Docker restriction on container names. name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" # Hostname makes the shell more user friendly: coder@my-workspace:~$ diff --git a/coderd/templatebuilder/testdata/kubernetes.tf.golden b/coderd/templatebuilder/testdata/kubernetes.tf.golden index 876f3c1dfc2..7bcb33e298a 100644 --- a/coderd/templatebuilder/testdata/kubernetes.tf.golden +++ b/coderd/templatebuilder/testdata/kubernetes.tf.golden @@ -244,7 +244,7 @@ resource "kubernetes_deployment_v1" "main" { container { name = "dev" - image = "codercom/enterprise-base:ubuntu" + image = "codercom/example-base:ubuntu" image_pull_policy = "Always" command = ["sh", "-c", coder_agent.main.init_script] security_context { From 1c82dc99e22d5768cdfc582406cf11ff3b6724c0 Mon Sep 17 00:00:00 2001 From: Ben Potter Date: Mon, 6 Jul 2026 18:51:26 +0000 Subject: [PATCH 02/10] docs(docs/admin/templates/managing-templates): link Coder example images in image management guide --- docs/admin/templates/managing-templates/image-management.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/admin/templates/managing-templates/image-management.md b/docs/admin/templates/managing-templates/image-management.md index 0a7cca2d623..7afdd0fe6bb 100644 --- a/docs/admin/templates/managing-templates/image-management.md +++ b/docs/admin/templates/managing-templates/image-management.md @@ -1,7 +1,7 @@ # Image Management While Coder provides example -[base container images](https://github.com/coder/enterprise-images) for +[base container images](https://github.com/coder/images) for workspaces, it's often best to create custom images that matches the needs of your users. This document serves a guide to operational maturity with some best practices around managing workspaces images for Coder. @@ -32,7 +32,7 @@ to consider: - Consider creating (and starting the container with) a non-root user See Coder's -[example base image](https://github.com/coder/enterprise-images/tree/main/images/minimal) +[example base image](https://github.com/coder/images/tree/main/images/minimal) for reference. ## Create general-purpose golden image(s) with standard tooling @@ -61,6 +61,7 @@ most cases) with a well-defined scope. Examples: +- [Coder's Universal Image](https://github.com/coder/images/tree/main/images/universal): a catch-all image with many languages and tools preinstalled. Runs as the `coder` user, so it works with Coder templates out of the box. See [coder/images](https://github.com/coder/images) for more example images, including language-specific ones. - [Universal Dev Containers Image](https://github.com/devcontainers/images/tree/main/src/universal) ## Allow developers to bring their own images and customizations with Dev Containers From eefd7c4eba33a327518b149c234c6ecca04e4740 Mon Sep 17 00:00:00 2001 From: Ben Potter Date: Mon, 6 Jul 2026 18:52:10 +0000 Subject: [PATCH 03/10] docs(docs/admin/templates/managing-templates): add project-specific images section --- .../managing-templates/image-management.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/admin/templates/managing-templates/image-management.md b/docs/admin/templates/managing-templates/image-management.md index 7afdd0fe6bb..06c7fd177bc 100644 --- a/docs/admin/templates/managing-templates/image-management.md +++ b/docs/admin/templates/managing-templates/image-management.md @@ -8,7 +8,8 @@ practices around managing workspaces images for Coder. 1. Create a minimal base image 2. Create golden image(s) with standard tooling -3. Allow developers to bring their own images and customizations with Dev +3. Create project-specific images for common use cases +4. Allow developers to bring their own images and customizations with Dev Containers An image is just one of the many properties defined within the template. @@ -64,6 +65,22 @@ Examples: - [Coder's Universal Image](https://github.com/coder/images/tree/main/images/universal): a catch-all image with many languages and tools preinstalled. Runs as the `coder` user, so it works with Coder templates out of the box. See [coder/images](https://github.com/coder/images) for more example images, including language-specific ones. - [Universal Dev Containers Image](https://github.com/devcontainers/images/tree/main/src/universal) +## Create project-specific images for common use cases + +Beyond golden images, create images scoped to a specific project, language, or +use case (e.g. a Go backend, a Node.js frontend, or a data science stack). +These images stay smaller and faster to pull than a kitchen-sink image, and +give each team exactly the tooling they need. + +Examples: + +- [coder/images](https://github.com/coder/images): Coder's example + language-specific images (Go, Java, Node.js, and more), all running as the + `coder` user +- [Dev Containers image catalog](https://hub.docker.com/r/microsoft/devcontainers): + browsable catalog of language and framework-specific images maintained in + [devcontainers/images](https://github.com/devcontainers/images) + ## Allow developers to bring their own images and customizations with Dev Containers While golden images are great for general use cases, developers will often need From 401f45a83f574857cd202441dd0030734de6a845 Mon Sep 17 00:00:00 2001 From: Ben Potter Date: Mon, 6 Jul 2026 18:53:39 +0000 Subject: [PATCH 04/10] docs(docs/admin/templates/managing-templates): link mise guide and drop envbuilder mention --- .../templates/managing-templates/image-management.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/admin/templates/managing-templates/image-management.md b/docs/admin/templates/managing-templates/image-management.md index 06c7fd177bc..62701a1fad2 100644 --- a/docs/admin/templates/managing-templates/image-management.md +++ b/docs/admin/templates/managing-templates/image-management.md @@ -77,9 +77,9 @@ Examples: - [coder/images](https://github.com/coder/images): Coder's example language-specific images (Go, Java, Node.js, and more), all running as the `coder` user -- [Dev Containers image catalog](https://hub.docker.com/r/microsoft/devcontainers): - browsable catalog of language and framework-specific images maintained in - [devcontainers/images](https://github.com/devcontainers/images) +- Rather than baking every tool into the image, you can also layer tools onto + a smaller image with [mise](https://mise.jdx.dev/). See the + [install command-line tools guide](../../../get-started/customize-your-template/install-command-line-tools.md) ## Allow developers to bring their own images and customizations with Dev Containers @@ -88,5 +88,4 @@ specific tooling for their projects. The [Dev Container](https://containers.dev) specification allows developers to define their projects dependencies within a `devcontainer.json` in their Git repository. -- [Configure a template for Dev Containers](../../integrations/devcontainers/integration.md) (recommended) -- [Learn about Envbuilder](../../integrations/devcontainers/envbuilder/index.md) (alternative for environments without Docker) +- [Configure a template for Dev Containers](../../integrations/devcontainers/integration.md) From 3ae8f936903bfc69a481e78af76c504844d06e8c Mon Sep 17 00:00:00 2001 From: Ben Potter Date: Mon, 6 Jul 2026 18:56:30 +0000 Subject: [PATCH 05/10] docs(docs/admin/templates/managing-templates): link minimal and base images, add dogfood example --- .../templates/managing-templates/image-management.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/admin/templates/managing-templates/image-management.md b/docs/admin/templates/managing-templates/image-management.md index 62701a1fad2..3206aec390b 100644 --- a/docs/admin/templates/managing-templates/image-management.md +++ b/docs/admin/templates/managing-templates/image-management.md @@ -33,8 +33,10 @@ to consider: - Consider creating (and starting the container with) a non-root user See Coder's -[example base image](https://github.com/coder/images/tree/main/images/minimal) -for reference. +[example minimal image](https://github.com/coder/images/tree/main/images/minimal) +for reference, or the +[example base image](https://github.com/coder/images/tree/main/images/base) +for a slightly more padded starting point with common utilities preinstalled. ## Create general-purpose golden image(s) with standard tooling @@ -77,6 +79,9 @@ Examples: - [coder/images](https://github.com/coder/images): Coder's example language-specific images (Go, Java, Node.js, and more), all running as the `coder` user +- [Coder's dogfood image](https://github.com/coder/coder/tree/main/dogfood): + the image Coder's own engineers use to develop Coder. A good reference for a + project-specific image tailored to a specific team or monorepo setup - Rather than baking every tool into the image, you can also layer tools onto a smaller image with [mise](https://mise.jdx.dev/). See the [install command-line tools guide](../../../get-started/customize-your-template/install-command-line-tools.md) From a9c9a684ca16c650a48d7ee55e622499f9a1b780 Mon Sep 17 00:00:00 2001 From: Ben Potter Date: Mon, 6 Jul 2026 19:04:41 +0000 Subject: [PATCH 06/10] docs(docs/admin/templates/managing-templates): use consistent example lists, move mise to dev containers section --- .../managing-templates/image-management.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/admin/templates/managing-templates/image-management.md b/docs/admin/templates/managing-templates/image-management.md index 3206aec390b..0e6527fba0f 100644 --- a/docs/admin/templates/managing-templates/image-management.md +++ b/docs/admin/templates/managing-templates/image-management.md @@ -32,11 +32,10 @@ to consider: `docker`, `bash`, `jq`, and/or internal tooling - Consider creating (and starting the container with) a non-root user -See Coder's -[example minimal image](https://github.com/coder/images/tree/main/images/minimal) -for reference, or the -[example base image](https://github.com/coder/images/tree/main/images/base) -for a slightly more padded starting point with common utilities preinstalled. +Examples: + +- [Coder's minimal image](https://github.com/coder/images/tree/main/images/minimal): only the necessary dependencies for a Coder workspace to bootstrap +- [Coder's base image](https://github.com/coder/images/tree/main/images/base): a slightly more padded starting point with common utilities preinstalled ## Create general-purpose golden image(s) with standard tooling @@ -82,9 +81,6 @@ Examples: - [Coder's dogfood image](https://github.com/coder/coder/tree/main/dogfood): the image Coder's own engineers use to develop Coder. A good reference for a project-specific image tailored to a specific team or monorepo setup -- Rather than baking every tool into the image, you can also layer tools onto - a smaller image with [mise](https://mise.jdx.dev/). See the - [install command-line tools guide](../../../get-started/customize-your-template/install-command-line-tools.md) ## Allow developers to bring their own images and customizations with Dev Containers @@ -94,3 +90,7 @@ specification allows developers to define their projects dependencies within a `devcontainer.json` in their Git repository. - [Configure a template for Dev Containers](../../integrations/devcontainers/integration.md) + +Alternatively, rather than baking every tool into the image, developers can +layer tools onto a smaller image with [mise](https://mise.jdx.dev/). See the +[install command-line tools guide](../../../get-started/customize-your-template/install-command-line-tools.md). From c5518a9de4020acb8f2ed9f616c75d29e3d6ac66 Mon Sep 17 00:00:00 2001 From: Ben Potter Date: Mon, 6 Jul 2026 19:06:04 +0000 Subject: [PATCH 07/10] docs(docs/admin/templates/managing-templates): rework developer customization section --- .../managing-templates/image-management.md | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/admin/templates/managing-templates/image-management.md b/docs/admin/templates/managing-templates/image-management.md index 0e6527fba0f..84141e9554e 100644 --- a/docs/admin/templates/managing-templates/image-management.md +++ b/docs/admin/templates/managing-templates/image-management.md @@ -9,8 +9,7 @@ practices around managing workspaces images for Coder. 1. Create a minimal base image 2. Create golden image(s) with standard tooling 3. Create project-specific images for common use cases -4. Allow developers to bring their own images and customizations with Dev - Containers +4. Let developers customize their own environment An image is just one of the many properties defined within the template. Templates can pull images from a public image registry (e.g. Docker Hub) or an @@ -82,15 +81,17 @@ Examples: the image Coder's own engineers use to develop Coder. A good reference for a project-specific image tailored to a specific team or monorepo setup -## Allow developers to bring their own images and customizations with Dev Containers +## Let developers customize their own environment -While golden images are great for general use cases, developers will often need -specific tooling for their projects. The [Dev Container](https://containers.dev) -specification allows developers to define their projects dependencies within a -`devcontainer.json` in their Git repository. +Even with well-scoped images, developers will often need tooling that is +specific to their project or personal workflow. Instead of maintaining an +image for every combination, let developers layer their own customizations +on top of a smaller image: -- [Configure a template for Dev Containers](../../integrations/devcontainers/integration.md) - -Alternatively, rather than baking every tool into the image, developers can -layer tools onto a smaller image with [mise](https://mise.jdx.dev/). See the -[install command-line tools guide](../../../get-started/customize-your-template/install-command-line-tools.md). +- [Dev Containers](https://containers.dev): developers define their project's + dependencies in a `devcontainer.json` in their Git repository, and Coder + builds the environment on top of your base image. See + [configure a template for Dev Containers](../../integrations/devcontainers/integration.md). +- [mise](https://mise.jdx.dev/): developers install and pin language runtimes + and CLI tools at workspace startup without rebuilding the image. See the + [install command-line tools guide](../../../get-started/customize-your-template/install-command-line-tools.md). From d861d1b2d8a3d768e2419c0f0cc6ccd6ba917bea Mon Sep 17 00:00:00 2001 From: Ben Potter Date: Mon, 6 Jul 2026 19:07:32 +0000 Subject: [PATCH 08/10] docs(docs/admin/templates/managing-templates): use pullable image references and tighten prose --- .../managing-templates/image-management.md | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/docs/admin/templates/managing-templates/image-management.md b/docs/admin/templates/managing-templates/image-management.md index 84141e9554e..99cb29c672b 100644 --- a/docs/admin/templates/managing-templates/image-management.md +++ b/docs/admin/templates/managing-templates/image-management.md @@ -1,10 +1,10 @@ # Image Management While Coder provides example -[base container images](https://github.com/coder/images) for -workspaces, it's often best to create custom images that matches the needs of -your users. This document serves a guide to operational maturity with some best -practices around managing workspaces images for Coder. +[container images](https://github.com/coder/images) for +workspaces, it's often best to create custom images that match the needs of +your users. This document serves as a guide to operational maturity with some +best practices around managing workspace images for Coder. 1. Create a minimal base image 2. Create golden image(s) with standard tooling @@ -13,12 +13,13 @@ practices around managing workspaces images for Coder. An image is just one of the many properties defined within the template. Templates can pull images from a public image registry (e.g. Docker Hub) or an -internal one, thanks to Terraform. +internal one, thanks to Terraform. Each image reference below can be dropped +directly into a template's image variable or parameter. ## Create a minimal base image While you may not use this directly in Coder templates, it's useful to have a -minimal base image is a small image that contains only the necessary +minimal base image: a small image that contains only the necessary dependencies to work in your network and work with Coder. Here are some things to consider: @@ -33,16 +34,16 @@ to consider: Examples: -- [Coder's minimal image](https://github.com/coder/images/tree/main/images/minimal): only the necessary dependencies for a Coder workspace to bootstrap -- [Coder's base image](https://github.com/coder/images/tree/main/images/base): a slightly more padded starting point with common utilities preinstalled +- [`codercom/example-minimal:ubuntu`](https://github.com/coder/images/tree/main/images/minimal): only the necessary dependencies for a Coder workspace to bootstrap +- [`codercom/example-base:ubuntu`](https://github.com/coder/images/tree/main/images/base): a slightly more padded starting point with common utilities preinstalled -## Create general-purpose golden image(s) with standard tooling +## Create golden image(s) with standard tooling -It's often practical to have a few golden images that contain standard tooling -for developers. These images should contain a number of languages (e.g. Python, -Java, TypeScript), IDEs (VS Code, JetBrains, PyCharm), and other tools (e.g. -`docker`). Unlike project-specific images (which are also important), general -purpose images are great for: +Building on the base image, it's often practical to have a few golden images +that contain standard tooling for developers. These images should contain a +number of languages (e.g. Python, Java, TypeScript), IDEs (VS Code, JetBrains, +PyCharm), and other tools (e.g. `docker`). Unlike project-specific images +(which are also important), general purpose images are great for: - **Scripting:** Developers may just want to hop in a Coder workspace to run basic scripts or queries. @@ -62,8 +63,8 @@ most cases) with a well-defined scope. Examples: -- [Coder's Universal Image](https://github.com/coder/images/tree/main/images/universal): a catch-all image with many languages and tools preinstalled. Runs as the `coder` user, so it works with Coder templates out of the box. See [coder/images](https://github.com/coder/images) for more example images, including language-specific ones. -- [Universal Dev Containers Image](https://github.com/devcontainers/images/tree/main/src/universal) +- [`codercom/example-universal:ubuntu`](https://github.com/coder/images/tree/main/images/universal): a catch-all image with many languages and tools preinstalled. Runs as the `coder` user, so it works with Coder templates out of the box. +- [`mcr.microsoft.com/devcontainers/universal`](https://github.com/devcontainers/images/tree/main/src/universal): the Universal Dev Containers image ## Create project-specific images for common use cases @@ -74,12 +75,14 @@ give each team exactly the tooling they need. Examples: -- [coder/images](https://github.com/coder/images): Coder's example - language-specific images (Go, Java, Node.js, and more), all running as the - `coder` user -- [Coder's dogfood image](https://github.com/coder/coder/tree/main/dogfood): +- [`codercom/example-golang:ubuntu`](https://github.com/coder/images/tree/main/images/golang), + [`codercom/example-java:ubuntu`](https://github.com/coder/images/tree/main/images/java), + [`codercom/example-node:ubuntu`](https://github.com/coder/images/tree/main/images/node): + Coder's example language-specific images, all running as the `coder` user. + See [coder/images](https://github.com/coder/images) for the full list. +- [`codercom/oss-dogfood:latest`](https://github.com/coder/coder/tree/main/dogfood): the image Coder's own engineers use to develop Coder. A good reference for a - project-specific image tailored to a specific team or monorepo setup + project-specific image tailored to a specific team or monorepo setup. ## Let developers customize their own environment From 6b44538ba8c7f6523555896fe83ead9f0a93eaf6 Mon Sep 17 00:00:00 2001 From: Ben Potter Date: Mon, 6 Jul 2026 19:37:20 +0000 Subject: [PATCH 09/10] docs: apply review suggestions from nickvigilante --- coderd/templatebuilder/bases/docker/README.md | 4 ++- .../bases/kubernetes/README.md | 4 ++- .../managing-templates/image-management.md | 27 ++++++++++--------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/coderd/templatebuilder/bases/docker/README.md b/coderd/templatebuilder/bases/docker/README.md index bc9085ae3dc..60b95bfbbf9 100644 --- a/coderd/templatebuilder/bases/docker/README.md +++ b/coderd/templatebuilder/bases/docker/README.md @@ -26,7 +26,9 @@ Some options to consider: - [`codercom/example-base:ubuntu`](https://github.com/coder/images/tree/main/images/base) (default): minimal and lightweight, but may not include many tools developers expect by default - [`codercom/example-universal:ubuntu`](https://github.com/coder/images/tree/main/images/universal): catch-all image with many languages and tools available, but larger and slower to pull -More language-specific images (Go, Java, Node.js, and more) are available in [coder/images](https://github.com/coder/images), and the [devcontainers/images](https://github.com/devcontainers/images) collection is another good source of ready-made development images. You can also build your own image to pre-bake the exact tools your team needs. See [Coder's image management docs](https://coder.com/docs/admin/templates/managing-templates/image-management) for additional guidance. +More language-specific images (Go, Java, Node.js, and more) are available in [coder/images](https://github.com/coder/images), and the [devcontainers/images](https://github.com/devcontainers/images) collection is another good source of ready-made development images. +You can also build your own image to pre-bake the exact tools your team needs. +Visit [Coder's image management docs](https://coder.com/docs/admin/templates/managing-templates/image-management) for additional guidance. ### Infrastructure diff --git a/coderd/templatebuilder/bases/kubernetes/README.md b/coderd/templatebuilder/bases/kubernetes/README.md index b1fceb7e219..f97f78c7d43 100644 --- a/coderd/templatebuilder/bases/kubernetes/README.md +++ b/coderd/templatebuilder/bases/kubernetes/README.md @@ -30,7 +30,9 @@ Some options to consider: - [`codercom/example-base:ubuntu`](https://github.com/coder/images/tree/main/images/base) (default): minimal and lightweight, but may not include many tools developers expect by default - [`codercom/example-universal:ubuntu`](https://github.com/coder/images/tree/main/images/universal): catch-all image with many languages and tools available, but larger and slower to pull -More language-specific images (Go, Java, Node.js, and more) are available in [coder/images](https://github.com/coder/images), and the [devcontainers/images](https://github.com/devcontainers/images) collection is another good source of ready-made development images. You can also build your own image to pre-bake the exact tools your team needs. See [Coder's image management docs](https://coder.com/docs/admin/templates/managing-templates/image-management) for additional guidance. +More language-specific images (Go, Java, Node.js, and more) are available in [coder/images](https://github.com/coder/images), and the [devcontainers/images](https://github.com/devcontainers/images) collection is another good source of ready-made development images. +You can also build your own image to pre-bake the exact tools your team needs. +Visit [Coder's image management docs](https://coder.com/docs/admin/templates/managing-templates/image-management) for additional guidance. ### Authentication diff --git a/docs/admin/templates/managing-templates/image-management.md b/docs/admin/templates/managing-templates/image-management.md index 99cb29c672b..ac7b1e2dcae 100644 --- a/docs/admin/templates/managing-templates/image-management.md +++ b/docs/admin/templates/managing-templates/image-management.md @@ -6,10 +6,12 @@ workspaces, it's often best to create custom images that match the needs of your users. This document serves as a guide to operational maturity with some best practices around managing workspace images for Coder. -1. Create a minimal base image -2. Create golden image(s) with standard tooling -3. Create project-specific images for common use cases -4. Let developers customize their own environment +After following this tutorial, you'll accomplish the following: + +1. Create a minimal base image. +2. Create golden images with standard tooling. +3. Create project-specific images for common use cases. +4. Let developers customize their own environment. An image is just one of the many properties defined within the template. Templates can pull images from a public image registry (e.g. Docker Hub) or an @@ -19,7 +21,7 @@ directly into a template's image variable or parameter. ## Create a minimal base image While you may not use this directly in Coder templates, it's useful to have a -minimal base image: a small image that contains only the necessary +minimal base image as a small image that contains only the necessary dependencies to work in your network and work with Coder. Here are some things to consider: @@ -37,7 +39,7 @@ Examples: - [`codercom/example-minimal:ubuntu`](https://github.com/coder/images/tree/main/images/minimal): only the necessary dependencies for a Coder workspace to bootstrap - [`codercom/example-base:ubuntu`](https://github.com/coder/images/tree/main/images/base): a slightly more padded starting point with common utilities preinstalled -## Create golden image(s) with standard tooling +## Create golden images with standard tooling Building on the base image, it's often practical to have a few golden images that contain standard tooling for developers. These images should contain a @@ -69,9 +71,8 @@ Examples: ## Create project-specific images for common use cases Beyond golden images, create images scoped to a specific project, language, or -use case (e.g. a Go backend, a Node.js frontend, or a data science stack). -These images stay smaller and faster to pull than a kitchen-sink image, and -give each team exactly the tooling they need. +use case (e.g., a Go backend, a Node.js frontend, or a data science stack). +These images stay smaller and faster to pull than one larger image that tries to install all dependencies. Examples: @@ -79,7 +80,7 @@ Examples: [`codercom/example-java:ubuntu`](https://github.com/coder/images/tree/main/images/java), [`codercom/example-node:ubuntu`](https://github.com/coder/images/tree/main/images/node): Coder's example language-specific images, all running as the `coder` user. - See [coder/images](https://github.com/coder/images) for the full list. + Refer to [coder/images](https://github.com/coder/images) for the full list. - [`codercom/oss-dogfood:latest`](https://github.com/coder/coder/tree/main/dogfood): the image Coder's own engineers use to develop Coder. A good reference for a project-specific image tailored to a specific team or monorepo setup. @@ -88,13 +89,13 @@ Examples: Even with well-scoped images, developers will often need tooling that is specific to their project or personal workflow. Instead of maintaining an -image for every combination, let developers layer their own customizations +image for every combination, developers can layer their own customizations on top of a smaller image: - [Dev Containers](https://containers.dev): developers define their project's dependencies in a `devcontainer.json` in their Git repository, and Coder - builds the environment on top of your base image. See + builds the environment on top of your base image. Visit [configure a template for Dev Containers](../../integrations/devcontainers/integration.md). - [mise](https://mise.jdx.dev/): developers install and pin language runtimes - and CLI tools at workspace startup without rebuilding the image. See the + and CLI tools at workspace startup without rebuilding the image. Visit the [install command-line tools guide](../../../get-started/customize-your-template/install-command-line-tools.md). From 37b99112396112f1f990a78ee00454750ebc0229 Mon Sep 17 00:00:00 2001 From: Jeremy Ruppel Date: Mon, 6 Jul 2026 16:20:09 -0400 Subject: [PATCH 10/10] feat: make docker and kubernetes base template image configurable (#27024) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a `container_image` variable to the Docker and Kubernetes base templates so admins can override the default container image via the Template Builder wizard. The field appears as a freeform text input with `codercom/enterprise-base:ubuntu` as the default placeholder. The templates reference the variable via `{{ .Variables.container_image }}`, the same pattern kubernetes already uses for `namespace` and `use_kubeconfig`. No special-case logic in the compose pipeline; the variable flows through `mergeBaseVariables` like any other base variable. No frontend, API, or SDK changes are needed. The existing `variableToField()` in `BaseTemplateParametersStep.tsx` automatically renders non-sensitive string variables as text fields, and Docker now shows the base parameters step (previously skipped because it had no variables). > [!NOTE] > This PR was authored by Coder Agents on behalf of @jeremyruppel. Screenshot 2026-07-06 at 4 14 46 PM
Implementation plan ## Approach Use the variable the same way the kubernetes template already uses `namespace` and `use_kubeconfig`: declare it in `base.json`, and reference it in the `.tf.tmpl` via `{{ .Variables.container_image }}`. The variable flows through `mergeBaseVariables` which HCL-quotes string values, so the template just emits the value directly (no manual quoting). No special handling in `compose.go` or `renderBase()`. ### Why this works `mergeBaseVariables` converts string variable defaults and caller-supplied values into HCL-quoted strings (e.g. `"codercom/enterprise-base:ubuntu"`). The kubernetes template already relies on this for `namespace`: ```hcl namespace = {{ .Variables.namespace }} ``` The same pattern works for `container_image`: ```hcl image = {{ .Variables.container_image }} ``` No variable has special meaning. No Go-side override logic. ### RFC context: ImageOptions The RFC describes `ImageOptions` as a curated list that renders into a `coder_parameter` dropdown for developers at workspace creation time. This task is complementary: it makes the static image configurable by the admin at template creation time. When `ImageOptions` is eventually wired up, the admin's chosen image would become the `default` of that `coder_parameter` dropdown.
--- coderd/templatebuilder/bases/docker/base.json | 13 ++++- .../templatebuilder/bases/docker/main.tf.tmpl | 2 +- .../bases/kubernetes/base.json | 9 ++++ .../bases/kubernetes/main.tf.tmpl | 2 +- coderd/templatebuilder/compose_test.go | 54 +++++++++++++++++++ coderd/templatebuilder_handler_test.go | 5 +- 6 files changed, 80 insertions(+), 5 deletions(-) diff --git a/coderd/templatebuilder/bases/docker/base.json b/coderd/templatebuilder/bases/docker/base.json index e2feddc8d5e..1ded9b022ae 100644 --- a/coderd/templatebuilder/bases/docker/base.json +++ b/coderd/templatebuilder/bases/docker/base.json @@ -4,5 +4,16 @@ "os": "linux", "default_context": { "container_image": "codercom/example-base:ubuntu" - } + }, + "variables": [ + { + "name": "container_image", + "type": "string", + "description": "Container image for workspaces. The image determines which tools and languages are available in the workspace by default. See the template README for guidance on choosing an image.", + "default": "codercom/example-base:ubuntu", + "required": false, + "sensitive": false, + "computed": false + } + ] } diff --git a/coderd/templatebuilder/bases/docker/main.tf.tmpl b/coderd/templatebuilder/bases/docker/main.tf.tmpl index b044974892c..c462ef9094d 100644 --- a/coderd/templatebuilder/bases/docker/main.tf.tmpl +++ b/coderd/templatebuilder/bases/docker/main.tf.tmpl @@ -166,7 +166,7 @@ resource "docker_container" "workspace" { {{- if .ImageOptions }} image = data.coder_parameter.container_image.value {{- else }} - image = "{{ .ContainerImage }}" + image = {{ .Variables.container_image }} {{- end }} # Uses lower() to avoid Docker restriction on container names. name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" diff --git a/coderd/templatebuilder/bases/kubernetes/base.json b/coderd/templatebuilder/bases/kubernetes/base.json index 89dcd59dc7e..d6c4583b26f 100644 --- a/coderd/templatebuilder/bases/kubernetes/base.json +++ b/coderd/templatebuilder/bases/kubernetes/base.json @@ -6,6 +6,15 @@ "container_image": "codercom/example-base:ubuntu" }, "variables": [ + { + "name": "container_image", + "type": "string", + "description": "Container image for workspaces. The image determines which tools and languages are available in the workspace by default. See the template README for guidance on choosing an image.", + "default": "codercom/example-base:ubuntu", + "required": false, + "sensitive": false, + "computed": false + }, { "name": "use_kubeconfig", "type": "bool", diff --git a/coderd/templatebuilder/bases/kubernetes/main.tf.tmpl b/coderd/templatebuilder/bases/kubernetes/main.tf.tmpl index b50495ffb35..d32c8e0bd90 100644 --- a/coderd/templatebuilder/bases/kubernetes/main.tf.tmpl +++ b/coderd/templatebuilder/bases/kubernetes/main.tf.tmpl @@ -260,7 +260,7 @@ resource "kubernetes_deployment_v1" "main" { {{- if .ImageOptions }} image = data.coder_parameter.container_image.value {{- else }} - image = "{{ .ContainerImage }}" + image = {{ .Variables.container_image }} {{- end }} image_pull_policy = "Always" command = ["sh", "-c", coder_agent.main.init_script] diff --git a/coderd/templatebuilder/compose_test.go b/coderd/templatebuilder/compose_test.go index b15692036fd..dca7877f826 100644 --- a/coderd/templatebuilder/compose_test.go +++ b/coderd/templatebuilder/compose_test.go @@ -290,6 +290,60 @@ func TestCompose(t *testing.T) { require.Contains(t, err.Error(), "interpolation") }) + t.Run("DockerDefaultContainerImage", func(t *testing.T) { + t.Parallel() + result, err := templatebuilder.Compose(templatebuilder.ComposeRequest{ + BaseTemplateID: "docker", + RegistryURL: "https://registry.coder.com", + }) + require.NoError(t, err) + require.Contains(t, string(result.MainTF), `"codercom/example-base:ubuntu"`) + }) + + t.Run("DockerCustomContainerImage", func(t *testing.T) { + t.Parallel() + result, err := templatebuilder.Compose(templatebuilder.ComposeRequest{ + BaseTemplateID: "docker", + RegistryURL: "https://registry.coder.com", + BaseVariableValues: map[string]string{ + "container_image": "myregistry/myimage:v2", + }, + }) + require.NoError(t, err) + mainTF := string(result.MainTF) + require.Contains(t, mainTF, `"myregistry/myimage:v2"`) + require.NotContains(t, mainTF, `codercom/example-base:ubuntu`) + }) + + t.Run("KubernetesDefaultContainerImage", func(t *testing.T) { + t.Parallel() + result, err := templatebuilder.Compose(templatebuilder.ComposeRequest{ + BaseTemplateID: "kubernetes", + RegistryURL: "https://registry.coder.com", + BaseVariableValues: map[string]string{ + "namespace": "default", + }, + }) + require.NoError(t, err) + require.Contains(t, string(result.MainTF), `"codercom/example-base:ubuntu"`) + }) + + t.Run("KubernetesCustomContainerImage", func(t *testing.T) { + t.Parallel() + result, err := templatebuilder.Compose(templatebuilder.ComposeRequest{ + BaseTemplateID: "kubernetes", + RegistryURL: "https://registry.coder.com", + BaseVariableValues: map[string]string{ + "namespace": "default", + "container_image": "custom/workspace:latest", + }, + }) + require.NoError(t, err) + mainTF := string(result.MainTF) + require.Contains(t, mainTF, `"custom/workspace:latest"`) + require.NotContains(t, mainTF, `codercom/example-base:ubuntu`) + }) + t.Run("MissingRequiredVariable", func(t *testing.T) { t.Parallel() // git-clone has a required "url" variable with no default. diff --git a/coderd/templatebuilder_handler_test.go b/coderd/templatebuilder_handler_test.go index baa89e80aeb..3629bb2d27b 100644 --- a/coderd/templatebuilder_handler_test.go +++ b/coderd/templatebuilder_handler_test.go @@ -45,13 +45,14 @@ func TestTemplateBuilderBases(t *testing.T) { { id: "docker", expectedOS: "linux", - hasVariables: false, + hasVariables: true, + expectedVars: []string{"container_image"}, }, { id: "kubernetes", expectedOS: "linux", hasVariables: true, - expectedVars: []string{"namespace", "use_kubeconfig"}, + expectedVars: []string{"container_image", "namespace", "use_kubeconfig"}, }, { id: "aws-linux",