Dev Container — Mac·Windows·Linux 통합 개발 환경
VS Code Dev Container로 OS 차이를 제거한다. Docker 기반 reproducible dev env — devcontainer.json 한 파일로 팀 전체 동일 환경.
"내 머신에선 됐는데"는 보통 OS 차이에서 시작한다. Mac에는 brew·Apple Silicon, Windows에는 PowerShell·UTF-16, Linux 머신에는 systemd. 같은 Node 버전·같은 패키지를 깔아도 미묘한 차이가 나타난다.
Dev Container (VS Code Dev Containers + 표준 devcontainer.json)는 OS 차이를 Docker 컨테이너로 봉인한다. 팀 모두가 같은 Linux 환경 안에서 일하고 IDE만 호스트에서 띄운다. 이 가이드는 Mac·Windows·Linux 어느 호스트에서도 같은 dev container를 띄우는 셋업.
TL;DR
- Docker 런타임 설치 (Mac: OrbStack/Docker Desktop, Win: Docker Desktop/WSL Docker, Linux: docker)
- VS Code + Dev Containers 확장 (
ms-vscode-remote.remote-containers) - 프로젝트 루트에
.devcontainer/devcontainer.json한 파일 Cmd/Ctrl+Shift+P→ Dev Containers: Reopen in Container — 컨테이너에서 IDE가 다시 뜸- 팀원: clone → 위 명령 1번 → 동일 환경
사전 조건
- VS Code 1.95+
- Docker 런타임 — 각 OS별 가이드: mac/docker-setup · windows/docker-wsl2
- 프로젝트가 Git 관리 (devcontainer.json 공유 위해)
1. 왜 Dev Container를 쓰나
해결되는 문제
- "내 머신에선 됐는데" — 컨테이너 안에선 OS·툴체인 동일
- 온보딩 속도 — 신입이 README 30줄 안 보고 1 클릭으로 동작
- 버전 충돌 — 프로젝트 A는 Node 18, B는 Node 22 — 호스트 mise/nvm 없이 격리
- OS-specific 빌드 문제 — Apple Silicon ARM 빌드 issues, Windows 경로 길이 이슈 등 회피
- CI 환경과 일치 — 컨테이너를 GitHub Actions와 동일 base image로 쓰면 차이 제거
Dev Container가 약한 영역
- GUI 앱 개발 — Mac native, Windows native UI 빌드는 컨테이너 부적합
- GPU 의존 워크로드 — 일부 GPU 패스스루 가능하지만 호스트 직접 실행이 안정적
- 저성능 머신 — Docker 자체 RAM 1–2GB 더 잡아먹음 (16GB 머신은 괜찮음)
2. 최소 devcontainer.json
.devcontainer/devcontainer.json:
{
"name": "My Project Dev",
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-22-bookworm",
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"postCreateCommand": "npm install",
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
},
"forwardPorts": [3000, 5173],
"remoteUser": "node"
}핵심 필드:
| 필드 | 역할 |
|---|---|
image | Docker base image (Node, Python, Go, Rust 등 공식) |
features | 추가 도구 (git, gh, docker-in-docker, awscli 등 카탈로그) |
postCreateCommand | 컨테이너 첫 생성 후 1회 실행 (의존성 설치 등) |
customizations.vscode.extensions | 컨테이너 안에 자동 설치할 VS Code 확장 |
forwardPorts | 호스트로 노출할 포트 |
remoteUser | 컨테이너 안에서 사용할 사용자 (보안상 non-root 권장) |
3. 첫 실행
VS Code 명령 팔레트 (Cmd/Ctrl+Shift+P) → Dev Containers: Reopen in Container.
- 처음 약 1–3분 (이미지 pull +
postCreateCommand실행) - 완료 후 VS Code 하단에
Dev Container: My Project Dev표시
# 컨테이너 안 터미널 (VS Code Terminal)
uname -a
# Linux 1234abcd 6.10.x #1 SMP Debian ...
which node
# /usr/local/share/nvm/versions/node/v22.x/bin/node호스트 OS와 무관하게 같은 Linux 환경.
4. base image 선택
devcontainer.json의 image:에 들어갈 base image. 공식 카탈로그:
| 언어 / 스택 | Image |
|---|---|
| Node.js | mcr.microsoft.com/devcontainers/javascript-node:1-{18,20,22}-bookworm |
| Python | mcr.microsoft.com/devcontainers/python:1-{3.11,3.12,3.13}-bookworm |
| Go | mcr.microsoft.com/devcontainers/go:1-{1.22,1.23} |
| Rust | mcr.microsoft.com/devcontainers/rust:1-bookworm |
| Java | mcr.microsoft.com/devcontainers/java:1-{17,21}-bookworm |
| .NET | mcr.microsoft.com/devcontainers/dotnet:1-9.0-bookworm |
| Universal (다언어) | mcr.microsoft.com/devcontainers/universal:2-linux |
추천: 프로젝트가 단일 언어면 해당 언어 image, 멀티 언어면 base + features 조합.
또는 직접 Dockerfile 작성:
{
"name": "My Custom Dev",
"build": {
"dockerfile": "Dockerfile",
"context": ".."
}
}5. features — 1줄로 도구 추가
features 항목은 공식 카탈로그 (https://containers.dev/features) 의 모듈. 1줄 추가만으로 도구 설치.
자주 쓰는 것:
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {}, // 컨테이너 안에서 docker 실행
"ghcr.io/devcontainers/features/aws-cli:1": {},
"ghcr.io/devcontainers/features/terraform:1": {},
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {}
}6. Docker-in-Docker — 컨테이너 안에서 컨테이너
Dev container 안에서 docker run 이 가능해야 하는 경우 (docker-compose 테스트, build 검증):
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "latest",
"dockerDashComposeVersion": "v2"
}
}또는 호스트 Docker socket 공유 (가볍지만 보안 약함):
"mounts": [
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
]7. 호스트 ↔ 컨테이너 파일 mount
기본적으로 워크스페이스 폴더는 /workspaces/{project} 로 자동 mount.
추가 mount:
"mounts": [
"source=${localEnv:HOME}/.aws,target=/home/node/.aws,type=bind,readonly",
"source=${localEnv:HOME}/.gitconfig,target=/home/node/.gitconfig,type=bind"
]macOS의 mount 성능 이슈는 docker-setup §5.2 참조 (VirtioFS 권장).
8. 환경변수·시크릿
정적 환경변수
"containerEnv": {
"NODE_ENV": "development",
"LOG_LEVEL": "debug"
}시크릿 (커밋 금지)
.env 파일을 mount 또는 localEnv 로 전달:
"containerEnv": {
"GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}",
"OPENAI_API_KEY": "${localEnv:OPENAI_API_KEY}"
}호스트 셸의 환경변수가 컨테이너로 주입됨. .env는 .gitignore.
9. 멀티 컨테이너 (docker-compose 통합)
DB·Redis 등 의존 서비스를 같이 띄울 때:
.devcontainer/docker-compose.yml:
services:
app:
image: mcr.microsoft.com/devcontainers/javascript-node:1-22-bookworm
volumes:
- ..:/workspaces/myapp
command: sleep infinity
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: dev
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:.devcontainer/devcontainer.json:
{
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/myapp"
}VS Code는 app 컨테이너에 attach하고, db는 자동 시작.
10. CI와 동일 환경 — devcontainer-cli
devcontainer.json을 CI에서도 그대로 사용:
npm install -g @devcontainers/cli
# 컨테이너 빌드 + 명령 실행
devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . npm testGitHub Actions:
# .github/workflows/test.yml
- name: Test in dev container
uses: devcontainers/ci@v0.3
with:
runCmd: npm testCI 통과 = 로컬에서도 동일 결과 보장.
11. 검증
# 호스트
docker --version
# 컨테이너 안 (VS Code Terminal)
uname -a # Linux ...
which node # /usr/local/share/...
echo $NODE_ENV # development (devcontainer.json containerEnv 반영)
node --version # 컨테이너의 Node 버전
git --version # features로 설치한 git위 5가지가 모두 컨테이너에서 응답하면 셋업 완료.
12. 트러블슈팅
"Failed to connect" / 컨테이너 시작 실패
- Docker 런타임이 켜져 있는가 (Docker Desktop 메뉴바,
orb status,colima status) docker ps로 다른 컨테이너 충돌 확인- VS Code → Command Palette → "Dev Containers: Rebuild Without Cache"
빌드가 너무 오래 걸림
- 첫 빌드는 base image 다운로드 포함 (수 GB) — 정상
- 두 번째부터 캐시 활용.
postCreateCommand도 캐시되지 않음 (매 rebuild마다 재실행) onCreateCommand(1회만) vspostCreateCommand(rebuild마다) 구분
파일 권한 문제 (Permission denied)
- 컨테이너 UID와 호스트 UID 불일치 (특히 Linux 호스트)
remoteUser명시 +updateRemoteUserUID: true:"remoteUser": "vscode", "updateRemoteUserUID": true
forwardPorts 가 작동 안 함
- 컨테이너 안의 앱이
0.0.0.0또는::에 바인딩하는가 (127.0.0.1은 안 됨) - 예: Next.js의 경우
next dev -H 0.0.0.0
호스트 Git 설정이 안 잡힘
.gitconfig자동 mount는 옵션 — 명시적으로mounts추가- 또는
features의 git이gitconfig카피본 사용
너무 큰 node_modules에서 IDE 느림
- VS Code 검색에서
node_modules제외 (files.watcherExclude) - 또는
node_modules를 호스트 mount가 아닌 컨테이너 내부 볼륨으로:"mounts": [ "source=${localWorkspaceFolderBasename}-node-modules,target=/workspaces/${localWorkspaceFolderBasename}/node_modules,type=volume" ]
13. 다음 단계
- Mac Docker — /mac/docker-setup (런타임 비교)
- Windows Docker WSL2 — /windows/docker-wsl2
- Remote development — /multi-os/remote-development — 원격 머신을 dev 환경으로
- Dotfiles 동기화 — /mac/dotfiles — chezmoi로 dev container 안에도 dotfiles 적용
참고
변경 이력
- 2026-05-16: 첫 작성. devcontainer.json 핵심·base image 선택·features·docker-compose 통합·CI 통합·트러블슈팅 6종.