Kamu pasti pernah ngalamin ini: laptop baru, clone repo lama, terus npm install atau pip install gagal karena versi Node atau Python-nya beda. Atau lebih parah — kode jalan di laptop kamu, tapi di laptop teman satu tim error misterius yang butuh dua jam buat di-debug.
Itu bukan masalah skill. Itu masalah environment yang nggak konsisten.
Solusinya bukan "install ulang semua dependency dengan hati-hati". Solusinya adalah bikin environment kamu reproducible by design — dan Devcontainer adalah cara paling pragmatis buat ngelakuin itu tanpa harus bayar cloud sepeser pun.
Apa Itu Devcontainer (dan Kenapa Bukan Sekadar Docker Biasa)
Devcontainer adalah spec yang dikembangkan oleh Microsoft (tapi open source) yang mendefinisikan development environment kamu sebagai kode — biasanya satu file devcontainer.json di dalam folder .devcontainer/. Di dalamnya kamu bisa tentukan:
- Base Docker image yang dipakai
- Extension VS Code yang otomatis terinstall
- Port yang di-forward
- Script yang dijalankan setelah container nyala
- Environment variable
Bedanya sama Docker Compose biasa? Docker Compose fokus ke runtime (production atau staging). Devcontainer fokus ke developer experience — IDE integration, dotfiles, tooling — bukan cuma "container yang jalan".
Kamu bisa pakai Devcontainer di:
- VS Code (paling mature, pakai extension Dev Containers)
- GitHub Codespaces (cloud, tapi setup-nya sama persis)
- JetBrains IDE (support eksperimental)
- CLI langsung via
devcontainerCLI
Artikel ini fokus ke setup lokal di VS Code, karena itu yang paling relevan buat solo engineer yang nggak mau bayar Codespaces.
Setup Awal: Dari Zero ke Dev Environment yang Jalan
Prasyarat:
- Docker Desktop (atau Docker Engine di Linux) sudah jalan
- VS Code sudah install extension Dev Containers (
ms-vscode-remote.remote-containers)
Misalnya kamu punya project Python FastAPI. Struktur folder awal:
my-api/
├── main.py
├── requirements.txt
└── .devcontainer/
└── devcontainer.json
Isi devcontainer.json paling minimal yang langsung jalan:
{
"name": "FastAPI Dev",
"image": "mcr.microsoft.com/devcontainers/python:3.11",
"forwardPorts": [8000],
"postCreateCommand": "pip install -r requirements.txt",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"charliermarsh.ruff"
]
}
}
}
Terus di VS Code: Ctrl+Shift+P → Dev Containers: Reopen in Container.
VS Code bakal pull image, build container, install extension, jalankan postCreateCommand, dan buka workspace kamu di dalam container. Pertama kali memang butuh beberapa menit. Selanjutnya? Cepat, karena Docker caching.
Sekarang jalankan server:
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {"status": "ok", "env": "devcontainer"}
# Di terminal VS Code (sudah di dalam container)
uvicorn main:app --reload --host 0.0.0.0 --port 8000
Buka http://localhost:8000 di browser host kamu — jalan. Port forwarding sudah dihandle otomatis.
Tambah Database dengan Docker Compose
Project real butuh database. Ini yang bikin Devcontainer lebih powerful — kamu bisa compose beberapa service sekaligus.
Buat file docker-compose.yml di root project:
version: '3.8'
services:
app:
build:
context: .
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspace:cached
command: sleep infinity
environment:
- DATABASE_URL=postgresql://dev:dev@db:5432/devdb
depends_on:
- db
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
POSTGRES_DB: devdb
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
postgres-data:
Buat .devcontainer/Dockerfile:
FROM mcr.microsoft.com/devcontainers/python:3.11
# Install system dependencies kalau perlu
RUN apt-get update && apt-get install -y \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
Update devcontainer.json buat pakai Compose:
{
"name": "FastAPI + Postgres Dev",
"dockerComposeFile": "../docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"forwardPorts": [8000, 5432],
"postCreateCommand": "pip install -r requirements.txt",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"charliermarsh.ruff",
"mtxr.sqltools",
"mtxr.sqltools-driver-pg"
]
}
}
}
Sekarang setiap kali kamu buka project ini, Postgres sudah nyala otomatis, connection string sudah ada di environment variable, dan extension SQLTools sudah terinstall buat query langsung dari VS Code.
Gotcha yang Gue Temuin (Skip Ini Berarti Dua Jam Debugging)
1. File permission di Linux host
Kalau kamu di Linux (bukan Mac atau Windows), volume mount sering bikin file yang dibuat di dalam container punya owner root, bukan user kamu. Fix-nya: tambah di devcontainer.json:
"remoteUser": "vscode"
User vscode sudah ada di semua base image Microsoft dan punya UID yang bisa di-remap.
2. postCreateCommand gagal diam-diam
Kalau pip install gagal di postCreateCommand, VS Code tetap buka container — cuma dependency-nya nggak keinstall. Kamu nggak dapat error yang jelas. Solusi: cek log di Output panel → pilih "Dev Containers" dari dropdown.
Atau, tambahkan error handling eksplisit:
"postCreateCommand": "pip install -r requirements.txt && echo 'Dependencies installed OK'"
3. Git credential nggak ke-forward
Push ke GitHub dari dalam container bisa gagal karena credential nggak ada. Fix paling simpel: di devcontainer.json tambahkan:
"mounts": [
"source=${localEnv:HOME}/.gitconfig,target=/home/vscode/.gitconfig,type=bind,consistency=cached"
]
Kalau pakai SSH key, pastikan SSH agent kamu jalan di host dan tambahkan:
"remoteEnv": {
"SSH_AUTH_SOCK": "${localEnv:SSH_AUTH_SOCK}"
}
4. Hot reload nggak jalan di Mac
Di Mac, file watcher di dalam container kadang nggak nangkap perubahan file dari host karena cara Docker Desktop handle filesystem. Tambahkan WATCHFILES_FORCE_POLLING=true ke environment variable kalau pakai uvicorn --reload atau Vite:
"remoteEnv": {
"WATCHFILES_FORCE_POLLING": "true"
}
Bikin Devcontainer yang Bisa Dipakai Tim (atau Diri Sendiri 6 Bulan Lagi)
Solo engineer pun butuh ini. Kamu yang nulis kode hari ini bukan kamu yang buka repo 6 bulan lagi — dan kamu nggak mau debugging environment pas lagi semangat-semangatnya mau nambah fitur.
Beberapa praktik yang gue terapkan:
Pin versi image secara eksplisit:
"image": "mcr.microsoft.com/devcontainers/python:3.11-bullseye"
Jangan pakai latest. Tag latest hari ini beda sama latest bulan depan.
Pisahkan tool development dari dependency production:
# .devcontainer/Dockerfile
FROM mcr.microsoft.com/devcontainers/python:3.11-bullseye
# Dev tools — nggak masuk production image
RUN pip install ipython httpie pgcli
Tambahkan devcontainer-feature untuk tooling umum:
Devcontainer punya konsep "features" — snippet yang bisa kamu compose tanpa nulis Dockerfile dari scratch:
{
"name": "FastAPI Dev",
"image": "mcr.microsoft.com/devcontainers/python:3.11",
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/node:1": {
"version": "20"
}
}
}
Features ini di-maintain oleh komunitas dan Microsoft. Kamu bisa browse semua yang tersedia di containers.dev/features.
Pakai Devcontainer CLI untuk Workflow Non-VS Code
Kalau kamu sesekali kerja dari terminal tanpa VS Code (misalnya SSH ke server, atau pakai editor lain), ada @devcontainers/cli yang bisa kamu install:
npm install -g @devcontainers/cli
Build dan jalankan container dari terminal:
# Di root project
devcontainer up --workspace-folder .
Eksekusi command di dalam container:
devcontainer exec --workspace-folder . python -m pytest
Ini berguna banget buat CI/CD pipeline — kamu bisa jalankan test di environment yang identik sama dev environment lokal, bukan di environment CI yang konfigurasinya beda sendiri.
Contoh GitHub Actions yang pakai devcontainer CLI:
# .github/workflows/test.yml
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install devcontainer CLI
run: npm install -g @devcontainers/cli
- name: Run tests in devcontainer
run: |
devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . python -m pytest tests/ -v
Sekarang CI dan local environment kamu pakai container yang sama. Kalau test lulus di lokal, hampir pasti lulus di CI juga.
Yang Gue Lakuin Sekarang
Semua project baru gue mulai dengan .devcontainer/ dari hari pertama — bukan setelah setup-nya ribet. Biayanya cuma 10 menit di awal, dan itu menghemat berjam-jam debugging environment di kemudian hari.
Workflow gue sekarang:
git clonerepo- Buka di VS Code → Reopen in Container
- Langsung coding — semua dependency, database, dan tooling sudah ada
Nggak ada lagi "works on my machine". Kalau kamu mau mulai, ambil devcontainer.json minimal dari atas, sesuaikan dengan stack kamu, commit ke repo, dan coba buka ulang project di container. Dari situ kamu bisa iterasi.
Langkah lanjutan yang worth di-explore:
- Dotfiles support: Devcontainer bisa clone dotfiles repo kamu otomatis ke dalam container, jadi alias dan konfigurasi shell kamu ada di mana-mana
- Multi-root workspace: Kalau kamu kerja di monorepo, satu devcontainer bisa handle beberapa service sekaligus
- Prebuild di Codespaces: Kalau suatu saat project kamu butuh kolaborasi, this guide tentang setup yang sama langsung jalan di Codespaces tanpa konfigurasi ulang