Skip to content

Consolidate GET /containers and GET /containers/devcontainers and render devcontainers (instead of containers) in the UI #666

Open
@mafredri

Description

@mafredri

Problem

Currently, the containers and devcontainers API endpoints are split and the UI only renders "containers" filtered on certain labels. This is not ideal from a managing of devcontainers standpoint as the devcontainer would disappear if the underlying container is removed.

Proposal (new combined format):

To fix this, we can update the containers endpoint to list devcontainers as well making the data available in the UI.

GET /api/v0/containers:

{
  "devcontainers": [
    {
      // Same fields as before. The container data will be duplicated here as there will also be an entry in "containers".
    }
  ],
  "containers": [
    {
      // Same fields as before, but remove `devcontainer_*` fields.
    }
  ]

With this unified endpoint, we can still support old container access methods as well as opt to render .devcontainers in the UI rather than .containers filtered on labels. We can also remove the devcontainer_dirty and devcontainer_status fields from .containers as those were added as a stop-gap to show devcontainer state.

Why we want this?

We need a way to represent devcontainers even when there is no container running, or they are in an error state. For example, during recreation of a devcontainer, the devcontainer may be temporarily missing from the UI, or in the event of an error, completely disappear and require manual intervetion.

UI impact

Consider the existing UI:

Image

Notice the dev container being represented as dev container: inspiring_curran.

This has two problems when taking into account sub agents in dev containers (#621).

  1. The agent name keeps changing on container recreation, breaking existing URLs and connection attempts (e.g. coder ssh workspace.<random_words>)
  2. The docker container name is not a valid agent name (underscores _ are not permitted)

As can be observed from the /api/v0/devcontainers endpoint below, dev containers already have a name (ideally) either defined via devcontainer.json .customize field (TODO create issue) or via Terraform resource if used.

Ideally this dev container should be rendered as dev container: coder (inspiring_curran) or similar. Likewise its status should be properly represented (running, starting, stopped, error).

Definition of done

  1. Merge GET /api/v0/containers and GET /api/v0/containers/devcontainers under GET /api/v0/containers
  2. Remove .devcontainer_dirty and .devcontainer_status fields from .container entries
  3. Render dev containers from the newly added .devcontainers field instead of .containers
  4. Show .name and .container.name in the format proposed above
  5. Keep logic for "dirty", but use .dirty from devcontainer (instead of container.devcontainer_dirty)
  6. Represent devcontainer .status in the UI
  7. The devcontainers are always rendered, even if the container is stopped

For reference, the existing endpoints render the following content:

GET /api/v0/containers:

{
  "containers": [
    {
      "created_at": "2025-06-03T12:12:04.213068588Z",
      "id": "42b1be73cdcc818c0d9f6afefae5569fb82cb56fa9b9df8efab7a43bb352d1f0",
      "name": "gifted-bouman",
      "image": "vsc-coder-16501171b99410a3c45670c2393882c63fca0ca319d89a5c3f48672fec889697-features-uid",
      "labels": {
        "devcontainer.config_file": "/home/coder/coder/.devcontainer/devcontainer.json",
        "devcontainer.local_folder": "/home/coder/coder",
        "devcontainer.metadata": "[ {\"id\":\"ghcr.io/devcontainers/features/docker-in-docker:2\",\"privileged\":true,\"entrypoint\":\"/usr/local/share/docker-init.sh\",\"mounts\":[{\"source\":\"dind-var-lib-docker-${devcontainerId}\",\"target\":\"/var/lib/docker\",\"type\":\"volume\"}],\"customizations\":{\"vscode\":{\"extensions\":[\"ms-azuretools.vscode-docker\"],\"settings\":{\"github.copilot.chat.codeGeneration.instructions\":[{\"text\":\"This dev container includes the Docker CLI (`docker`) pre-installed and available on the `PATH` for running and managing containers using a dedicated Docker daemon running inside the dev container.\"}]}}}}, {\"customizations\":{\"vscode\":{\"extensions\":[\"biomejs.biome\"]}}} ]",
        "org.opencontainers.image.ref.name": "ubuntu",
        "org.opencontainers.image.version": "22.04"
      },
      "running": true,
      "ports": [],
      "status": "running",
      "volumes": {
        "/home/coder/coder": "/workspaces/coder",                                                                                                                                                                                                                                                                                  "/var/lib/docker/volumes/dind-var-lib-docker-188djrll4q61ascc3gh2s0phshvifcn964vkc68dp1l7v7eqqjtn/_data": "/var/lib/docker"                                                                                                                                                                                              },
      "devcontainer_status": "running",
      "devcontainer_dirty": false
    }
  ]
}

GET /api/v0/containers/devcontainers:

{
  "devcontainers": [
    {
      "id": "3c8cfbac-aff2-400b-86d5-0e51036fda80",
      "name": "coder",
      "workspace_folder": "/home/coder/coder",
      "config_path": "/home/coder/coder/.devcontainer/devcontainer.json",
      "status": "running",
      "dirty": false,
      "container": {
        "created_at": "2025-06-03T12:12:04.213068588Z",
        "id": "42b1be73cdcc818c0d9f6afefae5569fb82cb56fa9b9df8efab7a43bb352d1f0",
        "name": "gifted_bouman",
        "image": "vsc-coder-16501171b99410a3c45670c2393882c63fca0ca319d89a5c3f48672fec889697-features-uid",
        "labels": {
          "devcontainer.config_file": "/home/coder/coder/.devcontainer/devcontainer.json",
          "devcontainer.local_folder": "/home/coder/coder",
          "devcontainer.metadata": "[ {\"id\":\"ghcr.io/devcontainers/features/docker-in-docker:2\",\"privileged\":true,\"entrypoint\":\"/usr/local/share/docker-init.sh\",\"mounts\":[{\"source\":\"dind-var-lib-docker-${devcontainerId}\",\"target\":\"/var/lib/docker\",\"type\":\"volume\"}],\"customizations\":{\"vscode\":{\"extensions\":[\"ms-azuretools.vscode-docker\"],\"settings\":{\"github.copilot.chat.codeGeneration.instructions\":[{\"text\":\"This dev container includes the Docker CLI (`docker`) pre-installed and available on the `PATH` for running and managing containers using a dedicated Docker daemon running inside the dev container.\"}]}}}}, {\"customizations\":{\"vscode\":{\"extensions\":[\"biomejs.biome\"]}}} ]",
          "org.opencontainers.image.ref.name": "ubuntu",
          "org.opencontainers.image.version": "22.04"
        },
        "running": true,
        "ports": [],
        "status": "running",
        "volumes": {
          "/home/coder/coder": "/workspaces/coder",
          "/var/lib/docker/volumes/dind-var-lib-docker-188djrll4q61ascc3gh2s0phshvifcn964vkc68dp1l7v7eqqjtn/_data": "/var/lib/docker"
        },
        "devcontainer_status": "running",
        "devcontainer_dirty": false
      }
    }
  ]
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions