- name
- multi-container-workspaces
- description
- Use when setting up dev containers with sidecar services like databases, caches, or message brokers. Covers Docker Compose integration, service networking, and multi-service devcontainer.json configuration.
USE FOR: Docker Compose sidecar services, database/cache/queue containers alongside dev containers, multi-service networking, service health checks
DO NOT USE FOR: general devcontainer.json schema (use devcontainer), Docker-in-Docker for building images (use docker-in-docker), production Kubernetes deployment (use iac/kubernetes)
- license
- MIT
- metadata
- {"displayName":"Multi-Container Workspaces","author":"Tyler-R-Kendrick"}
- compatibility
- claude, copilot, cursor
- references
- [{"title":"Dev Containers Specification","url":"https://containers.dev/"},{"title":"Docker Compose Official Documentation","url":"https://docs.docker.com/compose/"}]
# Multi-Container Workspaces
## Overview
Multi-container workspaces use Docker Compose to run sidecar services (databases, caches, queues) alongside the main dev container. The dev container connects to sidecars over the Compose network, giving you a production-like topology in development.
## Basic Setup
### docker-compose.yml
```yaml
services:
app:
build:
context: .
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspace:cached
command: sleep infinity
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: devpass
POSTGRES_DB: myapp
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
pgdata:
```
### devcontainer.json
```jsonc
{
"name": "Full Stack App",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"runServices": ["app", "db", "redis"],
"shutdownAction": "stopCompose",
"forwardPorts": [3000, "db:5432", "redis:6379"],
"postCreateCommand": "npm ci && npm run db:migrate",
"remoteEnv": {
"DATABASE_URL": "postgresql://dev:devpass@db:5432/myapp",
"REDIS_URL": "redis://redis:6379"
}
}
```
## Key Properties
| Property | Description |
|----------|-------------|
| `dockerComposeFile` | Path(s) to Compose file(s). Can be a string or array. |
| `service` | The service to attach the editor to (your dev container). |
| `workspaceFolder` | Path inside the container where the repo is mounted. |
| `runServices` | Which services to start. Omit to start all. |
| `shutdownAction` | `stopCompose` (stop all) or `none` (leave running). |
| `forwardPorts` | Forward ports; use `"service:port"` for sidecar ports. |
## Multiple Compose Files
Override the base Compose file with a dev-specific overlay:
```jsonc
{
"dockerComposeFile": [
"docker-compose.yml",
"docker-compose.dev.yml"
],
"service": "app"
}
```
The dev overlay can add volumes, environment variables, or features only needed in development.
## Compose Override Example
```yaml
# docker-compose.dev.yml
services:
app:
volumes:
- ..:/workspace:cached
environment:
- ASPNETCORE_ENVIRONMENT=Development
command: sleep infinity
```
## Service Networking
All services in the same Compose file share a network. Reference sidecars by their service name:
- `db:5432` — PostgreSQL
- `redis:6379` — Redis
- `rabbitmq:5672` — RabbitMQ
- `azurite:10000` — Azure Storage emulator
No `localhost` — always use the **service name** as the hostname.
## Health Checks and Dependencies
Ensure sidecars are ready before running setup commands:
```yaml
services:
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U dev"]
interval: 5s
timeout: 3s
retries: 5
app:
depends_on:
db:
condition: service_healthy
```
## Parallel postCreateCommand
Run multiple setup steps concurrently:
```jsonc
{
"postCreateCommand": {
"backend": "dotnet restore",
"frontend": "npm ci",
"migrations": "npm run db:migrate",
"seed": "npm run db:seed"
}
}
```
## Best Practices
- Always use `"shutdownAction": "stopCompose"` to clean up sidecar containers when the Codespace stops.
- Use named volumes for database data so it survives container rebuilds.
- Add health checks to sidecar services and `depends_on` with `condition: service_healthy` for the app service.
- Reference sidecars by service name, never `localhost` — they are separate containers on the Compose network.
- Keep sidecar images pinned to major versions (e.g., `postgres:16`, not `postgres:latest`) for reproducibility.
- Use `remoteEnv` for connection strings so they are available in the integrated terminal.
- Separate dev-only configuration into a `docker-compose.dev.yml` overlay to keep production Compose files clean.
GitHub에서 보기