devAlice
← Multi-OS

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

  1. Docker 런타임 설치 (Mac: OrbStack/Docker Desktop, Win: Docker Desktop/WSL Docker, Linux: docker)
  2. VS Code + Dev Containers 확장 (ms-vscode-remote.remote-containers)
  3. 프로젝트 루트에 .devcontainer/devcontainer.json 한 파일
  4. Cmd/Ctrl+Shift+PDev Containers: Reopen in Container — 컨테이너에서 IDE가 다시 뜸
  5. 팀원: clone → 위 명령 1번 → 동일 환경

사전 조건

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"
}

핵심 필드:

필드역할
imageDocker 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.jsonimage:에 들어갈 base image. 공식 카탈로그:

언어 / 스택Image
Node.jsmcr.microsoft.com/devcontainers/javascript-node:1-{18,20,22}-bookworm
Pythonmcr.microsoft.com/devcontainers/python:1-{3.11,3.12,3.13}-bookworm
Gomcr.microsoft.com/devcontainers/go:1-{1.22,1.23}
Rustmcr.microsoft.com/devcontainers/rust:1-bookworm
Javamcr.microsoft.com/devcontainers/java:1-{17,21}-bookworm
.NETmcr.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 test

GitHub Actions:

# .github/workflows/test.yml
- name: Test in dev container
  uses: devcontainers/ci@v0.3
  with:
    runCmd: npm test

CI 통과 = 로컬에서도 동일 결과 보장.


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회만) vs postCreateCommand(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. 다음 단계


참고

변경 이력

  • 2026-05-16: 첫 작성. devcontainer.json 핵심·base image 선택·features·docker-compose 통합·CI 통합·트러블슈팅 6종.

댓글