home / skills / digitalocean-labs / do-app-platform-skills / devcontainers

devcontainers skill

/skills/devcontainers

This skill helps you set up local development environments with production parity for App Platform apps using devcontainers.

npx playbooks add skill digitalocean-labs/do-app-platform-skills --skill devcontainers

Review the files below or copy the command above to add this skill to your agents.

Files (7)
SKILL.md
7.3 KB
---
name: devcontainers
version: 1.0.0
min_doctl_version: "1.82.0"
description: Set up local development environments with production parity for DigitalOcean App Platform. Use when setting up local dev, adding devcontainer to a project, running App Platform apps locally, or configuring backing services (Postgres, Redis, Kafka, S3).
related_skills: [designer, postgres, managed-db-services]
deprecated: false
---

# Dev Containers Skill

Set up local development environments with production parity for DigitalOcean App Platform applications.

**Primary value**: 30-second feedback loops instead of 7-minute deploy cycles.

## Quick Decision

```
What do you need?
├── New project setup → Workflow 1
├── Existing App Platform app → Workflow 2
└── CLI-only testing (no IDE) → See cli-workflow.md
```

---

## Quick Start: Clone and Copy

```bash
# Clone the reference devcontainer
git clone --depth 1 https://github.com/bikramkgupta/do-app-devcontainer.git /tmp/devcontainer-ref

# Copy to your project
cp -r /tmp/devcontainer-ref/.devcontainer /path/to/your-project/

# Clean up
rm -rf /tmp/devcontainer-ref
```

Then customize `COMPOSE_PROFILES` in `.devcontainer/devcontainer.json`:
```json
"containerEnv": {
  "COMPOSE_PROFILES": "app,postgres,minio"
}
```

---

## Available Profiles

| Profile | Service | Use When |
|---------|---------|----------|
| `postgres` | PostgreSQL 18 | SQL database |
| `mysql` | MySQL 8 | MySQL database |
| `mongo` | MongoDB 8 | Document database |
| `valkey` | Valkey 8 | Redis-compatible cache |
| `kafka` | Confluent Kafka 7.7 | Message streaming |
| `minio` | RustFS | S3-compatible storage |
| `opensearch` | OpenSearch 3.0 | Full-text search |

---

## Connection Strings

| Service | Connection String |
|---------|-------------------|
| PostgreSQL | `postgresql://postgres:password@postgres:5432/app` |
| MySQL | `mysql://mysql:mysql@mysql:3306/app` |
| MongoDB | `mongodb://mongodb:mongodb@mongo:27017/app?authSource=admin` |
| Valkey | `redis://valkey:6379` |
| Kafka | `kafka:9092` |
| RustFS | `http://minio:9000` (creds: `rustfsadmin/rustfsadmin`) |
| OpenSearch | `http://opensearch:9200` |

**Inside container**: Use service names (e.g., `postgres:5432`)
**From host**: Use `docker compose port` to find mapped ports

---

## Workflow 1: New Project Setup

**Trigger:** "I'm building a [language] app with [services]"

1. Copy `.devcontainer/` from reference repo (see Quick Start)
2. Set `COMPOSE_PROFILES` based on required services
3. Create `env-devcontainer.example` with connection strings
4. Open in VS Code/Cursor → "Reopen in Container"

**devcontainer.json template:**
```json
{
  "name": "App Platform Dev Environment",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspaces/app",
  "features": {
    "ghcr.io/devcontainers/features/github-cli:1": {},
    "ghcr.io/devcontainers/features/node:1": {},
    "ghcr.io/devcontainers/features/python:1": {},
    "ghcr.io/devcontainers-extra/features/uv:1": {},
    "ghcr.io/devcontainers-extra/features/digitalocean-cli:1": {},
    "ghcr.io/anthropics/devcontainer-features/claude-code:1": {},
    "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
  },
  "containerEnv": {
    "COMPOSE_PROFILES": "app,postgres"
  },
  "initializeCommand": "cd \"${localWorkspaceFolder}\" && bash .devcontainer/init.sh",
  "postCreateCommand": ".devcontainer/post-create.sh",
  "remoteUser": "vscode",
  "shutdownAction": "stopCompose"
}
```

---

## Workflow 2: Add to Existing App Platform App

**Trigger:** "I have an App Platform app, help me run it locally"

1. Read `.do/app.yaml` to detect services
2. Map App Platform → local containers:

| App Platform | Local Profile |
|--------------|---------------|
| `databases[].engine: PG` | `postgres` |
| `databases[].engine: MYSQL` | `mysql` |
| `databases[].engine: MONGODB` | `mongo` |
| `databases[].engine: REDIS` | `valkey` |
| Spaces attachment | `minio` |

3. Generate environment mapping:
```bash
# Production (App Platform injects)
# DATABASE_URL=${db.DATABASE_URL}

# Local Development
DATABASE_URL=postgresql://postgres:password@postgres:5432/app
```

---

## Environment Template

```bash
# env-devcontainer.example

# Database
DATABASE_URL=postgresql://postgres:password@postgres:5432/app

# Cache
REDIS_URL=redis://valkey:6379

# S3-compatible storage (RustFS)
SPACES_ENDPOINT=http://minio:9000
SPACES_KEY_ID=rustfsadmin
SPACES_SECRET_KEY=rustfsadmin
SPACES_BUCKET_NAME=my-app-local
SPACES_FORCE_PATH_STYLE=true
```

---

## What You Get from Reference Repo

```
.devcontainer/
├── devcontainer.json           # IDE configuration
├── docker-compose.yml          # All 7 backing services
├── init.sh                     # Git worktree support
├── post-create.sh              # Post-creation setup
├── .env                        # Generated (gitignored)
└── tests/                      # Service connectivity tests
    ├── agent-test.sh           # E2E validation
    ├── run-all-tests.sh        # Master test runner
    └── test-*.sh               # Individual service tests
```

---

## Testing Services

```bash
# Test all running services
.devcontainer/tests/run-all-tests.sh --all

# Test specific services
.devcontainer/tests/run-all-tests.sh postgres minio

# List available tests
.devcontainer/tests/run-all-tests.sh --list
```

---

## Health Check Timing

| Service | Ready Time |
|---------|------------|
| PostgreSQL, MySQL, MongoDB, Valkey, RustFS | <10s |
| Kafka | 60s+ (KRaft init) |
| OpenSearch | 30-60s (JVM warmup) |

---

## Quick Troubleshooting

| Issue | Fix |
|-------|-----|
| Port conflict | Config uses dynamic ports (`127.0.0.1:0:PORT`), should not conflict |
| Git commands fail | Rebuild container to re-run `init.sh` |
| Kafka slow to start | Wait 60s+, check: `docker compose logs kafka` |
| OpenSearch OOM | Increase heap: `OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g` |
| Permission denied | Run: `sudo chown -R vscode:vscode /home/vscode` |

---

## Reference Files

| File | Content |
|------|---------|
| [service-templates.md](reference/service-templates.md) | All 7 docker-compose service blocks |
| [s3-storage-patterns.md](reference/s3-storage-patterns.md) | RustFS setup, local vs production |
| [agent-verification.md](reference/agent-verification.md) | CLI testing workflow for AI agents |
| [cli-workflow.md](reference/cli-workflow.md) | Port forwarding, env loading, startup |
| [language-configurations.md](reference/language-configurations.md) | Node, Python, Go hot reload configs |

---

## Limitations

This skill does **not** handle:
- Cloud deployment → use **deployment** skill
- Production app specs → use **designer** skill
- Database migrations → bring your own migration tool
- DigitalOcean Functions → not containerizable
- SSL/TLS → local uses HTTP; production handles SSL automatically

---

## Integration with Other Skills

- **→ designer**: Design production app spec after local testing
- **→ deployment**: Set up GitHub Actions CI/CD
- **→ postgres**: Configure managed database permissions
- **→ troubleshooting**: Debug production issues

---

## External References

- [VS Code Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers)
- [Docker Compose](https://docs.docker.com/compose/)
- [Reference Implementation](https://github.com/bikramkgupta/do-app-devcontainer)

Overview

This skill sets up local development environments that mirror DigitalOcean App Platform services so you can run apps locally with production-like backing services. It provides a ready devcontainer, docker-compose profiles for common services, connection strings, and workflows to add devcontainers to new or existing App Platform projects. The goal is fast local feedback loops and reliable service mapping to reduce deploy-test cycles.

How this skill works

The skill provides a reference .devcontainer with a docker-compose that includes selectable profiles (postgres, mysql, mongo, valkey, kafka, minio, opensearch). It maps App Platform service definitions to local container profiles, generates local environment templates, and includes init/post-create scripts and tests to validate service connectivity. Use VS Code or a similar IDE to "Reopen in Container" or run CLI workflows for non-IDE scenarios.

When to use it

  • Starting a new project and you want production parity locally
  • Adding a devcontainer to an existing DigitalOcean App Platform app
  • Running App Platform apps locally with backing services (DB, cache, S3, Kafka)
  • Testing service connectivity and local environment variables before deploying
  • CI validation or agent testing with the provided test scripts

Best practices

  • Copy the reference .devcontainer into your repo and customize COMPOSE_PROFILES for only required services
  • Keep env-devcontainer.example in source with non-sensitive example values; generate a gitignored .env for secrets
  • Use service names inside the container (e.g., postgres:5432); use docker compose port from host when needed
  • Run built-in tests (.devcontainer/tests/run-all-tests.sh) after container start to verify connectivity
  • For slow services (Kafka/OpenSearch) allow extra startup time and monitor logs; adjust memory for OpenSearch if needed

Example use cases

  • New language app: scaffold .devcontainer, set COMPOSE_PROFILES, open in VS Code and iterate with hot reload
  • Existing App Platform app: parse .do/app.yaml, map attachments to local profiles, and generate local DATABASE_URL/REDIS_URL
  • Agent or CI testing: run .devcontainer/tests/agent-test.sh inside the devcontainer to validate integrations
  • Develop S3-compatible features: run RustFS (minio) locally with example SPACES_* env values
  • Debugging local service issues: use docker compose logs and the provided test scripts to isolate failures

FAQ

How do I pick which services to run locally?

Set COMPOSE_PROFILES to only the services your app needs (e.g., app,postgres,minio). Running fewer services speeds startup and reduces resource use.

How do connection strings differ inside vs. outside the container?

Inside the container use service hostnames like postgres:5432. From the host use docker compose port to get mapped ports or rely on the .env created by the devcontainer scripts.

Kafka and OpenSearch are slow to start; what should I do?

Allow 60s+ for Kafka (KRaft init) and 30–60s for OpenSearch JVM warmup. Check logs with docker compose logs kafka or opensearch and increase OpenSearch heap via OPENSEARCH_JAVA_OPTS if OOM occurs.

Does this handle migrations or production deploys?

No. This skill focuses on local parity and developer workflows. Use a dedicated migration tool for database migrations and the deployment skill or CI for production deployments.