1
- # Configure a template for dev containers
1
+ # Configure a Template for Dev Containers
2
2
3
- To enable dev containers in workspaces, configure your template with the dev containers
3
+ Dev containers provide consistent, reproducible development environments using the
4
+ [ Development Containers specification] ( https://containers.dev/ ) .
5
+ Coder's dev container support allows developers to work in fully configured environments with their preferred tools and extensions.
6
+
7
+ To enable dev containers in workspaces, [ configure your template] ( ../creating-templates.md ) with the dev containers
4
8
modules and configurations outlined in this doc.
5
9
10
+ ## Why Use Dev Containers
11
+
12
+ Dev containers improve consistency across environments by letting developers define their development setup within
13
+ the code repository.
14
+
15
+ When integrated with Coder templates, dev containers provide:
16
+
17
+ - ** Project-specific environments** : Each repository can define its own tools, extensions, and configuration.
18
+ - ** Zero setup time** : Developers start workspace with fully configured environments without additional installation.
19
+ - ** Consistency across teams** : Everyone works in identical environments regardless of their local machine.
20
+ - ** Version-controlled environments** : Development environment changes are tracked alongside code changes.
21
+
22
+ The Dev Container integration replaces the legacy Envbuilder integration.
23
+ Visit [ Choose an approach to Dev Containers] ( ./dev-containers-envbuilder.md ) for more information about how they compare.
24
+
25
+ ## Prerequisites
26
+
27
+ - Dev containers require Docker to build and run containers inside the workspace.
28
+
29
+ Ensure your workspace infrastructure has Docker configured with container creation permissions and sufficient resources.
30
+
31
+ If it doesn't, follow the steps in [ Docker in workspaces] ( ./docker-in-workspaces.md ) .
32
+
33
+ - The ` devcontainers-cli ` module requires npm.
34
+
35
+ - You can use an image that already includes npm, such as ` codercom/enterprise-node:ubuntu ` .
36
+
6
37
## Install the Dev Containers CLI
7
38
8
39
Use the
9
40
[ devcontainers-cli] ( https://registry.coder.com/modules/devcontainers-cli ) module
10
- to ensure the ` @ devcontainers/cli` is installed in your workspace:
41
+ to install ` devcontainers/cli ` in your workspace:
11
42
12
43
``` terraform
13
44
module "devcontainers-cli" {
14
45
count = data.coder_workspace.me.start_count
15
46
source = "dev.registry.coder.com/modules/devcontainers-cli/coder"
16
- agent_id = coder_agent.dev .id
47
+ agent_id = coder_agent.main .id
17
48
}
18
49
```
19
50
20
- Alternatively, install the devcontainer CLI manually in your base image.
51
+ Alternatively, install ` @devcontainer/cli ` manually in your base image:
52
+
53
+ ``` shell
54
+ RUN npm install -g @devcontainers/cli
55
+ ```
21
56
22
- ## Configure Automatic Dev Container Startup
57
+ ## Define the Dev Container Resource
23
58
24
- The
25
- [ ` coder_devcontainer ` ] ( https://registry.terraform.io/providers/coder/coder/latest/docs/resources/devcontainer )
26
- resource automatically starts a dev container in your workspace, ensuring it's
27
- ready when you access the workspace:
59
+ If you don't use the [ ` git-clone ` ] ( #clone-the-repository ) module, point the resource at the folder that contains ` devcontainer.json ` :
28
60
29
61
``` terraform
30
62
resource "coder_devcontainer" "my-repository" {
31
63
count = data.coder_workspace.me.start_count
32
- agent_id = coder_agent.dev .id
33
- workspace_folder = "/home/coder/my-repository"
64
+ agent_id = coder_agent.main .id
65
+ workspace_folder = "/home/coder/project" # or /home/coder/project/.devcontainer
34
66
}
35
67
```
36
68
37
69
> [ !NOTE]
38
- >
39
70
> The ` workspace_folder ` attribute must specify the location of the dev
40
71
> container's workspace and should point to a valid project folder containing a
41
72
> ` devcontainer.json ` file.
42
73
43
- <!-- nolint:MD028/no-blanks-blockquote -->
74
+ ## Add Dev Container Features
44
75
45
- > [ !TIP]
46
- >
47
- > Consider using the [ ` git-clone ` ] ( https://registry.coder.com/modules/git-clone )
48
- > module to ensure your repository is cloned into the workspace folder and ready
49
- > for automatic startup.
76
+ Enhance your dev container experience with additional features.
77
+ For more advanced use cases, consult the [ advanced dev containers doc] ( ./advanced-dev-containers.md ) .
50
78
51
- ## Enable Dev Containers Integration
79
+ ### Custom applications
52
80
53
- To enable the dev containers integration in your workspace, you must set the
54
- ` CODER_AGENT_DEVCONTAINERS_ENABLE ` environment variable to ` true ` in your
55
- workspace container:
81
+ Add apps to the dev container workspace resource for one-click access.
56
82
57
83
``` terraform
58
- resource "docker_container" "workspace" {
59
- count = data.coder_workspace.me.start_count
60
- image = "codercom/oss-dogfood:latest"
61
- env = [
62
- "CODER_AGENT_DEVCONTAINERS_ENABLE=true",
63
- # ... Other environment variables.
64
- ]
65
- # ... Other container configuration.
84
+ "coder": {
85
+ "apps": [
86
+ {
87
+ "slug": "cursor",
88
+ "displayName": "Cursor",
89
+ "url": "cursor://coder.coder-remote/openDevContainer?owner=${localEnv:CODER_WORKSPACE_OWNER_NAME}&workspace=${localEnv:CODER_WORKSPACE_NAME}&agent=${localEnv:CODER_WORKSPACE_PARENT_AGENT_NAME}&url=${localEnv:CODER_URL}&token=$SESSION_TOKEN&devContainerName=${localEnv:CONTAINER_ID}&devContainerFolder=${containerWorkspaceFolder}&localWorkspaceFolder=${localWorkspaceFolder}",
90
+ "external": true,
91
+ "icon": "/icon/cursor.svg",
92
+ "order": 1
93
+ },
94
+ ```
95
+
96
+ <details ><summary >Expand for a full example:</summary >
97
+
98
+ This is an excerpt from the [ .devcontainer.json] ( https://github.com/coder/coder/blob/main/.devcontainer/devcontainer.json ) in the Coder repository:
99
+
100
+ ``` terraform
101
+ resource "coder_devcontainer" "my-repository" {
102
+ ...
103
+ {
104
+ "customizations": {
105
+ ...
106
+ "coder": {
107
+ "apps": [
108
+ {
109
+ "slug": "cursor",
110
+ "displayName": "Cursor",
111
+ "url": "cursor://coder.coder-remote/openDevContainer?owner=${localEnv:CODER_WORKSPACE_OWNER_NAME}&workspace=${localEnv:CODER_WORKSPACE_NAME}&agent=${localEnv:CODER_WORKSPACE_PARENT_AGENT_NAME}&url=${localEnv:CODER_URL}&token=$SESSION_TOKEN&devContainerName=${localEnv:CONTAINER_ID}&devContainerFolder=${containerWorkspaceFolder}&localWorkspaceFolder=${localWorkspaceFolder}",
112
+ "external": true,
113
+ "icon": "/icon/cursor.svg",
114
+ "order": 1
115
+ },
116
+ // Reproduce `code-server` app here from the code-server
117
+ // feature so that we can set the correct folder and order.
118
+ // Currently, the order cannot be specified via option because
119
+ // we parse it as a number whereas variable interpolation
120
+ // results in a string. Additionally we set health check which
121
+ // is not yet set in the feature.
122
+ {
123
+ "slug": "code-server",
124
+ "displayName": "code-server",
125
+ "url": "http://${localEnv:FEATURE_CODE_SERVER_OPTION_HOST:127.0.0.1}:${localEnv:FEATURE_CODE_SERVER_OPTION_PORT:8080}/?folder=${containerWorkspaceFolder}",
126
+ "openIn": "${localEnv:FEATURE_CODE_SERVER_OPTION_APPOPENIN:slim-window}",
127
+ "share": "${localEnv:FEATURE_CODE_SERVER_OPTION_APPSHARE:owner}",
128
+ "icon": "/icon/code.svg",
129
+ "group": "${localEnv:FEATURE_CODE_SERVER_OPTION_APPGROUP:Web Editors}",
130
+ "order": 3,
131
+ "healthCheck": {
132
+ "url": "http://${localEnv:FEATURE_CODE_SERVER_OPTION_HOST:127.0.0.1}:${localEnv:FEATURE_CODE_SERVER_OPTION_PORT:8080}/healthz",
133
+ "interval": 5,
134
+ "threshold": 2
135
+ },
136
+ {
137
+ "slug": "windsurf",
138
+ "displayName": "Windsurf Editor",
139
+ "url": "windsurf://coder.coder-remote/openDevContainer?owner=${localEnv:CODER_WORKSPACE_OWNER_NAME}&workspace=${localEnv:CODER_WORKSPACE_NAME}&agent=${localEnv:CODER_WORKSPACE_PARENT_AGENT_NAME}&url=${localEnv:CODER_URL}&token=$SESSION_TOKEN&devContainerName=${localEnv:CONTAINER_ID}&devContainerFolder=${containerWorkspaceFolder}&localWorkspaceFolder=${localWorkspaceFolder}",
140
+ "external": true,
141
+ "icon": "/icon/windsurf.svg",
142
+ "order": 3
143
+ },
144
+ {
145
+ "slug": "zed",
146
+ "displayName": "Zed Editor",
147
+ "url": "zed://ssh/${localEnv:CODER_WORKSPACE_AGENT_NAME}.${localEnv:CODER_WORKSPACE_NAME}.${localEnv:CODER_WORKSPACE_OWNER_NAME}.coder${containerWorkspaceFolder}",
148
+ "external": true,
149
+ "icon": "/icon/zed.svg",
150
+ "order": 4
151
+ },
152
+ }
153
+ ]
154
+ }
155
+ },
66
156
}
67
157
```
68
158
69
- This environment variable is required for the Coder agent to detect and manage
70
- dev containers. Without it, the agent will not attempt to start or connect to
71
- dev containers even if the ` coder_devcontainer ` resource is defined.
159
+ </details >
160
+
161
+ ### Agent naming
162
+
163
+ Coder names dev container agents in this order:
164
+
165
+ 1 . ` customizations.coder.name ` in ` devcontainer.json `
166
+ 1 . Project directory name (name of folder containing ` devcontainer.json ` or ` .devcontainer ` folder)
167
+ 1 . If the project directory name is already taken, the name is expanded to include the parent folder.
72
168
73
- ## Complete Template Example
169
+ For example, if the path is ` /home/coder/some/project ` and ` project ` is taken, then the agent is ` some-project ` .
74
170
75
- Here's a simplified template example that enables the dev containers
76
- integration:
171
+ ### Multiple dev containers
172
+
173
+ ``` terraform
174
+ resource "coder_devcontainer" "frontend" {
175
+ count = data.coder_workspace.me.start_count
176
+ agent_id = coder_agent.main.id
177
+ workspace_folder = "/home/coder/frontend"
178
+ }
179
+ resource "coder_devcontainer" "backend" {
180
+ count = data.coder_workspace.me.start_count
181
+ agent_id = coder_agent.main.id
182
+ workspace_folder = "/home/coder/backend"
183
+ }
184
+ ```
185
+
186
+ ## Example Docker Dev Container Template
187
+
188
+ <details ><summary >Expand for the full file:</summary >
77
189
78
190
``` terraform
79
191
terraform {
@@ -87,19 +199,18 @@ provider "coder" {}
87
199
data "coder_workspace" "me" {}
88
200
data "coder_workspace_owner" "me" {}
89
201
90
- resource "coder_agent" "dev " {
202
+ resource "coder_agent" "main " {
91
203
arch = "amd64"
92
204
os = "linux"
93
205
startup_script_behavior = "blocking"
94
206
startup_script = "sudo service docker start"
95
207
shutdown_script = "sudo service docker stop"
96
- # ...
97
208
}
98
209
99
210
module "devcontainers-cli" {
100
211
count = data.coder_workspace.me.start_count
101
- source = "dev. registry.coder.com/modules/devcontainers-cli/coder"
102
- agent_id = coder_agent.dev .id
212
+ source = "registry.coder.com/modules/devcontainers-cli/coder"
213
+ agent_id = coder_agent.main .id
103
214
}
104
215
105
216
resource "coder_devcontainer" "my-repository" {
0 commit comments