-
Notifications
You must be signed in to change notification settings - Fork 949
docs: add comprehensive dev containers documentation with examples #18582
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
718e6f9
ba7a36c
ef8a4ea
f4db3da
df07196
18998b7
ddc5893
048cf5b
5dc41a5
be23e85
ec77a25
06d714c
8f392c0
2fe5291
33d3eed
747822e
d9f818c
c10eb7e
3f8970e
0d0a9ba
88e7c0f
8f5e613
e83d564
03c60bf
cfcef3c
acdbe4d
1deae60
d3fd3b8
6ee9fd4
7b2ba10
30372fc
f7c5272
9eb367d
abd91a2
032edc3
1804190
67702ae
e8cff18
1af39a8
11891da
0b5cd24
6485b8f
f1df910
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,110 @@ | ||||||||||||||
# Advanced Dev Container Configuration | ||||||||||||||
|
||||||||||||||
This page extends the [devcontainers documentation](./devcontainers.md) with patterns for multiple dev containers, | ||||||||||||||
user-controlled startup, repository selection, and infrastructure tuning. | ||||||||||||||
|
||||||||||||||
## Run Multiple Dev Containers | ||||||||||||||
|
||||||||||||||
Run independent dev containers in the same workspace so each component appears as its own agent. | ||||||||||||||
|
||||||||||||||
In this example, there are two: `frontend` and `backend`: | ||||||||||||||
|
||||||||||||||
```terraform | ||||||||||||||
# Clone each repo | ||||||||||||||
module "git-clone-frontend" { | ||||||||||||||
count = data.coder_workspace.me.start_count | ||||||||||||||
source = "dev.registry.coder.com/modules/git-clone/coder" | ||||||||||||||
|
||||||||||||||
agent_id = coder_agent.main.id | ||||||||||||||
url = "https://github.com/your-org/frontend.git" | ||||||||||||||
base_dir = "/home/coder/frontend" | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will result in |
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
module "git-clone-backend" { | ||||||||||||||
count = data.coder_workspace.me.start_count | ||||||||||||||
source = "dev.registry.coder.com/modules/git-clone/coder" | ||||||||||||||
|
||||||||||||||
agent_id = coder_agent.main.id | ||||||||||||||
url = "https://github.com/your-org/backend.git" | ||||||||||||||
base_dir = "/home/coder/backend" | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
# Dev container resources | ||||||||||||||
resource "coder_devcontainer" "frontend" { | ||||||||||||||
count = data.coder_workspace.me.start_count | ||||||||||||||
agent_id = coder_agent.main.id | ||||||||||||||
workspace_folder = "/home/coder/frontend/${module.git-clone-frontend[0].folder_name}" | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
resource "coder_devcontainer" "backend" { | ||||||||||||||
count = data.coder_workspace.me.start_count | ||||||||||||||
agent_id = coder_agent.main.id | ||||||||||||||
workspace_folder = "/home/coder/backend/${module.git-clone-backend[0].folder_name}" | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Simplification. |
||||||||||||||
} | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
Each dev container appears as a separate agent, so developers can connect to any | ||||||||||||||
component in the workspace. | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't have a better suggestion, but "component" feels a bit off for me and it's feels like we're calling dev containers both dev containers and components. |
||||||||||||||
|
||||||||||||||
## Conditional Startup | ||||||||||||||
|
||||||||||||||
Use `coder_parameter` booleans to let workspace creators choose which dev containers start automatically, | ||||||||||||||
reducing resource usage for unneeded components: | ||||||||||||||
|
||||||||||||||
```terraform | ||||||||||||||
data "coder_parameter" "enable_frontend" { | ||||||||||||||
type = "bool" | ||||||||||||||
name = "Enable frontend container" | ||||||||||||||
Comment on lines
+55
to
+57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I suggest alternative terminology here so that we don't accidentally suggest that the exclusion of |
||||||||||||||
default = true | ||||||||||||||
mutable = true | ||||||||||||||
order = 3 | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
resource "coder_devcontainer" "frontend" { | ||||||||||||||
count = data.coder_parameter.enable_frontend.value ? data.coder_workspace.me.start_count : 0 | ||||||||||||||
agent_id = coder_agent.main.id | ||||||||||||||
workspace_folder = "/home/coder/frontend/${module.git-clone-frontend[0].folder_name}" | ||||||||||||||
} | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
## Repository-selection Patterns | ||||||||||||||
|
||||||||||||||
Prompt users to pick a repository or team at workspace creation time and clone the selected repo(s) automatically into the workspace: | ||||||||||||||
|
||||||||||||||
1. Add a parameter to the template: | ||||||||||||||
|
||||||||||||||
```terraform | ||||||||||||||
data "coder_parameter" "project" { | ||||||||||||||
name = "project" | ||||||||||||||
display_name = "Choose a project" | ||||||||||||||
type = "string" | ||||||||||||||
default = "https://github.com/coder/coder.git" | ||||||||||||||
|
||||||||||||||
option { | ||||||||||||||
name = "coder/coder" | ||||||||||||||
value = "https://github.com/coder/coder.git" | ||||||||||||||
} | ||||||||||||||
option { | ||||||||||||||
name = "Dev Container template" | ||||||||||||||
value = "https://github.com/devcontainers/template-starter.git" | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe https://github.com/coder/envbuilder-starter-devcontainer instead? I realize this is just an example, but that specific (Although, we may want to remove envbuilder from the name there.) |
||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
1. Change the `git-clone` module to accept the `value` as the `url`: | ||||||||||||||
|
||||||||||||||
```terraform | ||||||||||||||
module "git-clone" { | ||||||||||||||
count = data.coder_workspace.me.start_count | ||||||||||||||
source = "dev.registry.coder.com/modules/git-clone/coder" | ||||||||||||||
agent_id = coder_agent.main.id | ||||||||||||||
url = data.coder_parameter.project.value | ||||||||||||||
base_dir = "/home/coder" | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Indentation is a bit off on some of these, I recommend sticking to 2 spaces without exception. |
||||||||||||||
} | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
## Troubleshooting | ||||||||||||||
|
||||||||||||||
1. Run `docker ps` inside the workspace to ensure Docker is available. | ||||||||||||||
1. Check `/tmp/coder-agent.log` for agent logs. | ||||||||||||||
1. Verify that the workspace image includes Node/npm. |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,57 @@ | ||||||
# Choose an Approach To Dev Containers | ||||||
|
||||||
Coder supports two independent ways to run Dev Containers inside a workspace. | ||||||
|
||||||
Both implement the [Dev Container specification](https://containers.dev/), but they differ in how the container is built, | ||||||
who controls it, and which runtime requirements exist. | ||||||
|
||||||
Use this page to decide which path fits your project or platform needs. | ||||||
|
||||||
## Options at a Glance | ||||||
|
||||||
| Capability / Trait | Dev Containers integration (CLI-based) | Envbuilder Dev Containers | | ||||||
|------------------------------------------|------------------------------------------|-------------------------------------------| | ||||||
| Build engine | `@devcontainers/cli` + Docker | Envbuilder transforms the workspace image | | ||||||
| Runs separate Docker container | Yes (parent workspace + child container) | No (modifies the parent container) | | ||||||
| Multiple Dev Containers per workspace | Yes | No | | ||||||
| Rebuild when `devcontainer.json` changes | Yes (auto-prompt) | Limited (requires full workspace rebuild) | | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mafredri what do we think on the wording of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, it feels a bit off. Perhaps "(user initiated, change detection)". |
||||||
| Docker required in workspace | Yes | No (works in restricted envs) | | ||||||
| Templates | Standard `devcontainer.json` | Terraform + Envbuilder blocks | | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is "Templates" referring to here exactly? Dev Container Templates, Coder Templates? |
||||||
| Suitable for CI / AI agents | Yes. Deterministic, composable | Less ideal. No isolated container | | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this mean? Why is envbuilder not suitable? It's "just a workspace" in the end and arguably the container is potentially more isolated/locked down compared to a workspace where Docker is allowed to be run. |
||||||
|
||||||
## How To Migrate From Envbuilder to the Dev Containers Integration | ||||||
|
||||||
1. Ensure the workspace image can run Docker and has sufficient resources: | ||||||
|
||||||
```shell | ||||||
docker ps | ||||||
``` | ||||||
|
||||||
1. Remove any Envbuilder blocks that reference `coder_dev_envbuilder` from the template. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? |
||||||
1. Add (or keep) a standard `.devcontainer/` folder with `devcontainer.json` in the repository. | ||||||
1. Follow the [dev containers documentation](./devcontainers.md) for the full list of steps and options. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: It'd be nice to have consistent capitalization. I see some mixed use of My suggestion: |
||||||
|
||||||
At minimum, add the `devcontainers-cli` module and `coder_devcontainer` resource: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's also OK to manually install |
||||||
|
||||||
```terraform | ||||||
module "devcontainers_cli" { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Nit: Consistency, as per https://dev.registry.coder.com/modules/coder/devcontainers-cli |
||||||
source = "dev.registry.coder.com/modules/devcontainers-cli/coder" | ||||||
agent_id = coder_agent.main.id | ||||||
} | ||||||
resource "coder_devcontainer" "project" { # `project` in this example is how users will connect to the dev container: `ssh://project.<workspace>.me.coder` | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, the comment could be removed. (FYI for Edward, the resource name did play a role in the past, but not in the code that was released in GA.) |
||||||
count = data.coder_workspace.me.start_count | ||||||
agent_id = coder_agent.main.id | ||||||
workspace_folder = "/home/coder/project" | ||||||
} | ||||||
``` | ||||||
|
||||||
1. Start a new workspace. | ||||||
Coder detects and launches the dev container automatically. | ||||||
1. Verify ports, SSH, and rebuild prompts function as expected. | ||||||
|
||||||
## Related Reading | ||||||
|
||||||
- [Dev Containers Integration](./index.md) | ||||||
- [Troubleshooting Dev Containers](../../../user-guides/devcontainers/troubleshooting-dev-containers.md) | ||||||
- [Envbuilder on GitHub](https://github.com/coder/envbuilder) | ||||||
- [Dev Container specification](https://containers.dev/) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should mention here that the names come from the project name (i.e. folder they are cloned into).