Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions coderd/templatebuilder/bases/docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ 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.
Visit [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:
Expand Down
15 changes: 13 additions & 2 deletions coderd/templatebuilder/bases/docker/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
"display_name": "Docker",
"os": "linux",
"default_context": {
"container_image": "codercom/enterprise-base:ubuntu"
}
"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
}
]
}
2 changes: 1 addition & 1 deletion coderd/templatebuilder/bases/docker/main.tf.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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)}"
Expand Down
13 changes: 12 additions & 1 deletion coderd/templatebuilder/bases/kubernetes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,18 @@ 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.
Visit [Coder's image management docs](https://coder.com/docs/admin/templates/managing-templates/image-management) for additional guidance.

### Authentication

Expand Down
11 changes: 10 additions & 1 deletion coderd/templatebuilder/bases/kubernetes/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@
"display_name": "Kubernetes",
"os": "linux",
"default_context": {
"container_image": "codercom/enterprise-base:ubuntu"
"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",
Expand Down
2 changes: 1 addition & 1 deletion coderd/templatebuilder/bases/kubernetes/main.tf.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
4 changes: 2 additions & 2 deletions coderd/templatebuilder/bases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})

Expand Down
54 changes: 54 additions & 0 deletions coderd/templatebuilder/compose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion coderd/templatebuilder/testdata/docker.tf.golden
Original file line number Diff line number Diff line change
Expand Up @@ -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:~$
Expand Down
2 changes: 1 addition & 1 deletion coderd/templatebuilder/testdata/kubernetes.tf.golden
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 3 additions & 2 deletions coderd/templatebuilder_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
81 changes: 54 additions & 27 deletions docs/admin/templates/managing-templates/image-management.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
# Image Management

While Coder provides example
[base container images](https://github.com/coder/enterprise-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
3. Allow developers to bring their own images and customizations with Dev
Containers
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
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 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:

Expand All @@ -31,17 +34,18 @@ to consider:
`docker`, `bash`, `jq`, and/or internal tooling
- 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)
for reference.
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 general-purpose golden image(s) with standard tooling
## Create golden images 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.
Expand All @@ -61,14 +65,37 @@ most cases) with a well-defined scope.

Examples:

- [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

## Allow developers to bring their own images and customizations with Dev Containers
## Create project-specific images for common use cases

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.
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 one larger image that tries to install all dependencies.

Examples:

- [Configure a template for Dev Containers](../../integrations/devcontainers/integration.md) (recommended)
- [Learn about Envbuilder](../../integrations/devcontainers/envbuilder/index.md) (alternative for environments without Docker)
- [`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.
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.

## Let developers customize their own environment

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, 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. 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. Visit the
[install command-line tools guide](../../../get-started/customize-your-template/install-command-line-tools.md).
Loading