Already have a .devcontainer/devcontainer.json that uses dockerComposeFile with
several services (app, database, seed, dashboard, …) and start it with "Dev Containers:
Clone Repository in Named Container Volume"? You can keep that setup and route it through
the Huddle proxy without rewriting it.
huddle migrate generates a small Compose override file that wires your services behind
Huddle. Your own docker-compose.yml, devcontainer.json, extensions, features,
initializeCommand, postCreateCommand and forwarded ports all stay exactly as they are.
Huddle's devcontainer-net network (created by huddle init) is internal: it has no
route to the internet of its own. The only way out is the Huddle proxy on huddle:80, which
enforces the firewall and terminates TLS with its own CA. So two things have to be true for a
service to reach the internet through Huddle:
- It is attached to the internal
devcontainer-netnetwork. - Its egress goes through the proxy (
HTTP(S)_PROXY) and it trusts the Huddle CA.
huddle migrate produces both for you, in an override file, so you never hand-write proxy
env vars, NO_PROXY, CA paths or socket mounts.
In your docker-compose.yml, add the label huddle.network: "true" to the (internal)
network your services already share. That is the only change you make to your own files —
it tells huddle migrate which services to wire.
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: my-project-devcontainer
command: sleep infinity
networks: [development]
depends_on: [db]
db:
image: mcr.microsoft.com/mssql/server:2019-latest
networks: [development]
dashboard:
image: mcr.microsoft.com/dotnet/aspire-dashboard:latest
networks: [development]
networks:
development:
internal: true # required: no direct route to the internet
labels:
huddle.network: "true" # Huddle wires every service on this networkThe network must be
internal: true. If it is not, a service could reach the internet directly and bypass Huddle's firewall/proxy —huddle migratewarns when it sees this.
From your project directory (where docker-compose.yml lives), with Huddle already running
(huddle init):
huddle migrateThis writes docker-compose.huddle.yml next to your compose file. For each service on the
marked network it adds, in the override only:
- the proxy env vars —
HTTP_PROXY/HTTPS_PROXY(+ lowercase)= http://huddle:80; NO_PROXYincludinghuddle(so the direct CA fetch tohuddle:3000skips the proxy);NODE_EXTRA_CA_CERTSpointing at the CA path;- a second network,
huddle, that maps to the existingdevcontainer-net(external: true) — your owndevelopmentnetwork is left untouched.
Example generated docker-compose.huddle.yml:
services:
app:
networks:
development:
huddle:
environment:
HTTP_PROXY: "http://huddle:80"
HTTPS_PROXY: "http://huddle:80"
http_proxy: "http://huddle:80"
https_proxy: "http://huddle:80"
NO_PROXY: "localhost,127.0.0.1,::1,[::1],huddle"
no_proxy: "localhost,127.0.0.1,::1,[::1],huddle"
NODE_EXTRA_CA_CERTS: /home/vscode/.huddle-ca.crt
# …db, dashboard likewise…
networks:
huddle:
external: true
name: devcontainer-nethuddle migrate only generates the override — it does not start anything. Three steps
to finish:
-
Make sure Huddle is running so
devcontainer-netexists:huddle init
-
Fetch the Huddle CA inside the container. Add this to your
devcontainer.json(huddleis inNO_PROXY, so the call goes directly to the Huddle API):Use the home of your
remoteUser; pass--ca-pathtohuddle migrateif it differs (e.g.--ca-path /home/node/.huddle-ca.crt). If the CA is never fetched, HTTPS is tunnelled un-intercepted and the container still works. -
Reference the override so the IDE merges it when it (re)creates the containers. In
devcontainer.json:"dockerComposeFile": ["docker-compose.yml", "docker-compose.huddle.yml"]
Or start it yourself:
docker compose -f docker-compose.yml -f docker-compose.huddle.yml up -d
You can keep using "Clone Repository in Named Container Volume" — the override is just an extra Compose file the Dev Containers extension merges.
| Flag | Purpose |
|---|---|
--ca-path <path> |
Where the CA lands in the container (NODE_EXTRA_CA_CERTS). Default /home/vscode/.huddle-ca.crt. |
--docker-socket |
Also wire Huddle's filtered Docker socket + DOCKER_HOST (see caveat below). |
--output <path> |
Write the override somewhere other than docker-compose.huddle.yml. |
--force |
Overwrite an existing override file. |
If your outer devcontainer itself runs Docker (docker compose up, Testcontainers, …) it
must talk to Huddle's filtered socket, never the raw engine. --docker-socket generates
the mount (/tmp/dc-sockets/<container_name>:/var/run/huddle) and
DOCKER_HOST=unix:///var/run/huddle/docker.sock for each service that has a fixed
container_name.
This part is generated but not yet served. When the IDE starts the container against the
real engine, Huddle is not in the create path and cannot inject the socket at create time.
Huddle would need to pre-provision the per-container filtered socket at a name-keyed path
before the container exists (tracked as a follow-up on issue #66). Until that lands, the
mount source will not exist and DOCKER_HOST will point at a missing socket — so only enable
--docker-socket once that gateway support is available. huddle migrate prints the same
warning.
The proxy/CA/network wiring (the default, without --docker-socket) is fully functional
today; it is the same pattern the Huddle repository's own .devcontainer/
uses.
- The marked network must be
internal: true. - A wired service must not also be attached to a second, non-internal network — that
would be an unfiltered route out.
huddle migratewarns on both. - Do not grant the container
NET_ADMIN; it could otherwise tear down the injected routing.