Skip to content

Commit e978d4d

Browse files
authored
chore(examples): update devcontainer-docker template with envbuilder provider (#14199)
Updates the devcontainer-docker template with optional caching via the envbuilder provider
1 parent c90e6d7 commit e978d4d

File tree

2 files changed

+69
-16
lines changed

2 files changed

+69
-16
lines changed

examples/templates/devcontainer-docker/README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ Coder supports Devcontainers via [envbuilder](https://github.com/coder/envbuilde
3434

3535
This template provisions the following resources:
3636

37+
- Envbuilder cached image (conditional, persistent)
3738
- Docker image (persistent)
3839
- Docker container (ephemeral)
3940
- Docker volume (persistent on `/workspaces`)
4041

41-
with [`envbuilder`](https://github.com/coder/envbuilder).
42+
with [`envbuilder`](https://github.com/coder/envbuilder) and [`terraform-provider-envbuilder`](https://github.com/coder/terraform-provider-envbuilder).
4243
The Git repository is cloned inside the `/workspaces` volume if not present.
4344
Any local changes to the Devcontainer files inside the volume will be applied when you restart the workspace.
4445
Keep in mind that any tools or files outside of `/workspaces` or not added as part of the Devcontainer specification are not persisted.
@@ -54,7 +55,7 @@ See the [Envbuilder documentation](https://github.com/coder/envbuilder/blob/main
5455
## Caching
5556

5657
To speed up your builds, you can use a container registry as a cache.
57-
When creating the template, set the parameter `cache_repo`.
58+
When creating the template, set the parameter `cache_repo` to a valid Docker repository.
5859

5960
For example, you can run a local registry:
6061

@@ -69,6 +70,8 @@ docker run --detach \
6970

7071
Then, when creating the template, enter `localhost:5000/devcontainer-cache` for the parameter `cache_repo`.
7172

73+
See the [Envbuilder Terraform Provider Examples](https://github.com/coder/terraform-provider-envbuilder/blob/main/examples/resources/envbuilder_cached_image/envbuilder_cached_image_resource.tf/) for a more complete example of how the provider works.
74+
7275
> [!NOTE] We recommend using a registry cache with authentication enabled.
7376
> To allow Envbuilder to authenticate with the registry cache, specify the variable `cache_repo_docker_config_path`
7477
> with the path to a Docker config `.json` on disk containing valid credentials for the registry.

examples/templates/devcontainer-docker/main.tf

+64-14
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@ terraform {
77
docker = {
88
source = "kreuzwerker/docker"
99
}
10+
envbuilder = {
11+
source = "coder/envbuilder"
12+
}
1013
}
1114
}
1215

1316
provider "coder" {}
1417
provider "docker" {}
18+
provider "envbuilder" {}
1519
data "coder_provisioner" "me" {}
1620
data "coder_workspace" "me" {}
1721
data "coder_workspace_owner" "me" {}
@@ -89,14 +93,19 @@ EOF
8993

9094
variable "cache_repo" {
9195
default = ""
92-
description = "Use a container registry as a cache to speed up builds."
93-
sensitive = true
96+
description = "(Optional) Use a container registry as a cache to speed up builds."
9497
type = string
9598
}
9699

100+
variable "insecure_cache_repo" {
101+
default = false
102+
description = "Enable this option if your cache registry does not serve HTTPS."
103+
type = bool
104+
}
105+
97106
variable "cache_repo_docker_config_path" {
98107
default = ""
99-
description = "Path to a docker config.json containing credentials to the provided cache repo, if required."
108+
description = "(Optional) Path to a docker config.json containing credentials to the provided cache repo, if required."
100109
sensitive = true
101110
type = string
102111
}
@@ -107,6 +116,24 @@ locals {
107116
git_author_name = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
108117
git_author_email = data.coder_workspace_owner.me.email
109118
repo_url = data.coder_parameter.repo.value == "custom" ? data.coder_parameter.custom_repo_url.value : data.coder_parameter.repo.value
119+
# The envbuilder provider requires a key-value map of environment variables.
120+
envbuilder_env = {
121+
"CODER_AGENT_TOKEN" : coder_agent.main.token,
122+
# Use the docker gateway if the access URL is 127.0.0.1
123+
"CODER_AGENT_URL" : replace(data.coder_workspace.me.access_url, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal"),
124+
"ENVBUILDER_GIT_URL" : local.repo_url,
125+
# Use the docker gateway if the access URL is 127.0.0.1
126+
"ENVBUILDER_INIT_SCRIPT" : replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal"),
127+
"ENVBUILDER_FALLBACK_IMAGE" : data.coder_parameter.fallback_image.value,
128+
"ENVBUILDER_CACHE_REPO" : var.cache_repo,
129+
"ENVBUILDER_DOCKER_CONFIG_BASE64" : try(data.local_sensitive_file.cache_repo_dockerconfigjson[0].content_base64, ""),
130+
"ENVBUILDER_PUSH_IMAGE" : var.cache_repo == "" ? "" : "true",
131+
"ENVBUILDER_INSECURE" : "${var.insecure_cache_repo}",
132+
}
133+
# Convert the above map to the format expected by the docker provider.
134+
docker_env = [
135+
for k, v in local.envbuilder_env : "${k}=${v}"
136+
]
110137
}
111138

112139
data "local_sensitive_file" "cache_repo_dockerconfigjson" {
@@ -145,23 +172,29 @@ resource "docker_volume" "workspaces" {
145172
}
146173
}
147174

175+
# Check for the presence of a prebuilt image in the cache repo
176+
# that we can use instead.
177+
resource "envbuilder_cached_image" "cached" {
178+
count = var.cache_repo == "" ? 0 : data.coder_workspace.me.start_count
179+
builder_image = local.devcontainer_builder_image
180+
git_url = local.repo_url
181+
cache_repo = var.cache_repo
182+
extra_env = local.envbuilder_env
183+
insecure = var.insecure_cache_repo
184+
}
185+
148186
resource "docker_container" "workspace" {
149187
count = data.coder_workspace.me.start_count
150-
image = local.devcontainer_builder_image
188+
image = var.cache_repo == "" ? local.devcontainer_builder_image : envbuilder_cached_image.cached.0.image
151189
# Uses lower() to avoid Docker restriction on container names.
152190
name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
153191
# Hostname makes the shell more user friendly: coder@my-workspace:~$
154192
hostname = data.coder_workspace.me.name
155-
# Use the docker gateway if the access URL is 127.0.0.1
156-
env = [
157-
"CODER_AGENT_TOKEN=${coder_agent.main.token}",
158-
"CODER_AGENT_URL=${replace(data.coder_workspace.me.access_url, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")}",
159-
"ENVBUILDER_GIT_URL=${local.repo_url}",
160-
"ENVBUILDER_INIT_SCRIPT=${replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")}",
161-
"ENVBUILDER_FALLBACK_IMAGE=${data.coder_parameter.fallback_image.value}",
162-
"ENVBUILDER_CACHE_REPO=${var.cache_repo}",
163-
"ENVBUILDER_DOCKER_CONFIG_BASE64=${try(data.local_sensitive_file.cache_repo_dockerconfigjson[0].content_base64, "")}",
164-
]
193+
# Use the environment specified by the envbuilder provider, if available.
194+
# FIXME: https://github.com/coder/terraform-provider-envbuilder/issues/31
195+
#env = var.cache_repo == "" ? local.docker_env : envbuilder_cached_image.cached.0.env
196+
env = local.docker_env
197+
# network_mode = "host" # Uncomment if testing with a registry running on `localhost`.
165198
host {
166199
host = "host.docker.internal"
167200
ip = "host-gateway"
@@ -298,3 +331,20 @@ resource "coder_app" "code-server" {
298331
threshold = 6
299332
}
300333
}
334+
335+
resource "coder_metadata" "container_info" {
336+
count = data.coder_workspace.me.start_count
337+
resource_id = coder_agent.main.id
338+
item {
339+
key = "workspace image"
340+
value = var.cache_repo == "" ? local.devcontainer_builder_image : envbuilder_cached_image.cached.0.image
341+
}
342+
item {
343+
key = "git url"
344+
value = local.repo_url
345+
}
346+
item {
347+
key = "cache repo"
348+
value = var.cache_repo == "" ? "not enabled" : var.cache_repo
349+
}
350+
}

0 commit comments

Comments
 (0)