“제 컴퓨터에서는 되는데요.” 개발팀에서 이 문장이 나오면 대개 반나절은 날아간다. 새로운 팀원이 합류할 때마다 JDK 버전 맞추고, Node.js 설치하고, 환경변수 세팅하다가 하루를 통째로 쓰는 일은 2026년에도 여전하다. Dev Container는 이 문제를 구조적으로 잘라낸다. 핵심은 간단하다. 로컬 PC에서 코딩하는 게 아니라 Docker 컨테이너 안에서 개발한다. IDE가 컨테이너에 원격 접속하고, 런타임, 빌드 도구, 린터가 전부 컨테이너 안에 들어 있다. devcontainer.json 파일 하나에 이 환경을 정의해두면 팀원 누구든 동일한 개발환경을 재현한다. 클라우드 IDE 도입 기업을 대상으로 한 2025년 DZone 설문에서 Dev Container 기반 온보딩 소요 시간이 기존 대비 약 70% 줄었다는 응답이 나왔다. 이번 포스팅에서는 devcontainer 개념부터 Spring Boot, Node.js 실전 설정, Features, CI/CD 연동까지 정리한다.
Dev Container가 뭔데 이렇게 난리인가

Dev Container는 Docker 컨테이너 안에서 개발하는 방식이다. 코드를 로컬에서 편집하고 로컬에 깔린 런타임으로 실행하는 기존 방식과 근본적으로 다르다. IDE(VS Code, JetBrains 등)가 컨테이너에 원격 접속하고, 코드 편집, 빌드, 디버깅, 테스트 실행까지 전부 컨테이너 내부에서 일어난다. 소스 코드 파일은 로컬 디스크에 있고 볼륨 마운트로 컨테이너에 연결되기 때문에, 컨테이너가 사라져도 코드는 사라지지 않는다.
| 항목 | 기존 방식 | Dev Container |
|---|---|---|
| 코드 편집 | 로컬 PC의 IDE에서 직접 | IDE가 컨테이너에 원격 접속하여 편집 |
| 런타임/SDK | 로컬에 직접 설치 (JDK, Node.js 등) | 컨테이너 안에 설치됨 |
| DB/인프라 | 별도 Docker로 띄우거나 로컬 설치 | 같은 Compose 네트워크에서 함께 기동 |
| 환경 공유 | 위키 문서 + 구두 전달 | devcontainer.json 커밋 하나로 끝 |
| 소스 코드 저장 위치 | 로컬 디스크 | 로컬 디스크 (볼륨 마운트) |
devcontainer.json 파일에 런타임, 도구, IDE 설정을 한꺼번에 적어두면 IDE가 알아서 읽고 컨테이너 환경을 만든다. VS Code 전용 기능이라고 오해하는 경우가 많은데, 실제로는 containers.dev에서 관리하는 오픈 표준 스펙이다.
구성 방식은 크게 세 갈래다. 미리 만들어진 이미지를 바로 쓰는 Image 기반, 커스텀 Dockerfile을 빌드하는 방식, 그리고 여러 서비스를 함께 띄우는 Docker Compose 기반이다. VS Code뿐 아니라 JetBrains Gateway, GitHub Codespaces, DevPod까지 이 스펙을 지원하므로 특정 IDE에 종속될 걱정은 없다. containers.dev 공식 문서에 따르면 2025년 기준 13개 이상의 에디터, 도구, 서비스가 이 표준을 채택했다.
5분 만에 시작하는 Dev Container
VS Code 기준으로 필요한 건 두 가지다. Docker Desktop과 Dev Containers 확장(ms-vscode-remote.remote-containers). OS는 Windows 10 이상, macOS, 또는 Docker CE/EE 18.06 이상이 설치된 Linux면 된다. JetBrains 사용자라면 JetBrains Gateway에서 devcontainer.json을 바로 인식하고, 아예 IDE 없이 터미널에서만 쓰고 싶다면 devcontainer CLI(npm install -g @devcontainers/cli)로도 동일하게 컨테이너를 띄울 수 있다. 여기서는 VS Code 기준으로 설명하지만, devcontainer.json 설정 자체는 어떤 도구에서든 동일하다. 프로젝트 루트에 .devcontainer/devcontainer.json 파일을 생성한다.
{
"name": "My Project",
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/devcontainers/features/node:1": { "version": "20" }
},
"forwardPorts": [3000],
"customizations": {
"vscode": {
"extensions": ["dbaeumer.vscode-eslint"]
}
}
}JSONUbuntu 베이스 이미지 위에 Node.js 20을 설치하고, 3000번 포트를 호스트로 포워딩하며, ESLint 확장까지 자동으로 넣어주는 설정이다. image가 베이스 이미지, features가 추가 도구, customizations가 IDE 쪽 설정을 맡는다. Microsoft 공식 베이스 이미지(mcr.microsoft.com/devcontainers)를 쓰면 Dockerfile을 따로 만들 필요가 거의 없다.
파일을 저장한 뒤 VS Code 명령 팔레트(Ctrl+Shift+P)에서 “Dev Containers: Reopen in Container”를 실행하면 된다. 첫 실행 시 이미지 다운로드에 1~2분 정도 걸리고, 이후에는 캐시 덕분에 수 초 내에 컨테이너가 시작된다.
Spring Boot 프로젝트에 Dev Container 붙이기

Java 21 + Spring Boot + PostgreSQL 조합이라면 Docker Compose 기반이 가장 현실적이다. 앱 컨테이너와 DB 컨테이너를 동시에 띄워야 하기 때문이다. .devcontainer/devcontainer.json부터 보자.
{
"name": "Spring Boot Dev",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"features": {
"ghcr.io/devcontainers/features/java:1": {
"version": "21",
"installGradle": true
}
},
"customizations": {
"vscode": {
"extensions": [
"vscjava.vscode-java-pack",
"vmware.vscode-spring-boot"
],
"settings": {
"java.configuration.runtimes": [
{
"name": "JavaSE-21",
"path": "/usr/local/sdkman/candidates/java/current"
}
]
}
}
},
"postCreateCommand": "./gradlew dependencies"
}JSONdockerComposeFile로 Compose 파일 경로를 잡고, service에는 개발자가 실제로 접속할 서비스명을 넣는다. features에서 Java 21과 Gradle을 깔고, customizations로 Java Extension Pack과 Spring Boot 확장이 자동으로 붙는다. postCreateCommand에 Gradle 의존성 다운로드를 걸어두면 컨테이너가 뜨자마자 바로 코드를 짤 수 있는 상태가 된다.
Docker Compose로 DB까지 한 방에 띄우기
이어서 .devcontainer/docker-compose.yml 파일을 작성한다.
services:
app:
image: mcr.microsoft.com/devcontainers/base:ubuntu
volumes:
- ..:/workspace:cached
command: sleep infinity
networks:
- dev-network
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: devuser
POSTGRES_PASSWORD: devpass
POSTGRES_DB: myapp
ports:
- "5432:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- dev-network
networks:
dev-network:
volumes:
postgres-data:YAMLcommand: sleep infinity가 좀 이상해 보일 수 있는데, 컨테이너가 꺼지지 않고 계속 떠 있게 하려는 트릭이다. volumes의 cached 옵션은 macOS에서 파일 동기화 속도를 올려준다. PostgreSQL 16은 별도 서비스로 띄우고 dev-network로 연결했다. Spring Boot application.yml에서 DB 호스트를 db(서비스명)로 잡으면 컨테이너끼리 바로 통신한다.
Node.js + TypeScript devcontainer 설정은 더 간단하다
Node.js 쪽은 Spring Boot보다 훨씬 간단하다. Microsoft가 관리하는 TypeScript+Node.js 전용 이미지를 쓰면 Dockerfile도 Docker Compose도 필요 없다. devcontainer.json 하나면 끝이다.
{
"name": "Node.js TypeScript",
"image": "mcr.microsoft.com/devcontainers/typescript-node:20",
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"forwardPorts": [3000, 5173],
"postCreateCommand": "npm install",
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
}
}JSONtypescript-node:20 이미지에 Node.js 20, TypeScript, npm이 다 들어 있다. forwardPorts에 3000(Express 등)과 5173(Vite 기본 포트)을 걸어두면 로컬 브라우저에서 컨테이너 안의 개발 서버에 바로 접근된다. postCreateCommand에 npm install을 넣어두는 것도 포인트다. 컨테이너가 만들어지면서 의존성이 같이 깔려서, 별도 셋업 없이 코딩을 시작할 수 있다. GitHub CLI Feature는 PR이나 이슈 관리를 컨테이너 안에서 직접 하려고 넣었다.
devcontainer Features – 레고 블록처럼 조립하는 개발 도구

Feature는 Dockerfile 없이 도구를 설치하는 패키지 시스템이다. features 객체에 한 줄 추가하면 끝이다. 공식 저장소(github.com/devcontainers/features)에 Microsoft가 관리하는 Feature가 28개 등록되어 있고, 커뮤니티 제작 Feature까지 합치면 수백 개에 이른다.
자주 사용하는 Features를 정리하면 다음과 같다.
| Feature | 용도 | 설정 예시 |
|---|---|---|
ghcr.io/devcontainers/features/node:1 | Node.js 런타임 | { "version": "20" } |
ghcr.io/devcontainers/features/java:1 | JDK + 빌드 도구 | { "version": "21", "installGradle": true } |
ghcr.io/devcontainers/features/python:1 | Python 런타임 | { "version": "3.12" } |
ghcr.io/devcontainers/features/docker-in-docker:1 | 컨테이너 안에서 Docker 사용 | {} |
ghcr.io/devcontainers/features/github-cli:1 | GitHub CLI | {} |
ghcr.io/devcontainers/features/aws-cli:1 | AWS CLI v2 | {} |
{
"features": {
"ghcr.io/devcontainers/features/java:1": { "version": "21" },
"ghcr.io/devcontainers/features/node:1": { "version": "20" },
"ghcr.io/devcontainers/features/docker-in-docker:1": {}
}
}JSON이렇게 여러 Feature를 한번에 조합하면 된다. Java와 Node.js를 동시에 깔면서 Docker-in-Docker까지 켜는 구성이다. Feature끼리 독립적으로 설치되므로 충돌 걱정은 없다. 사내 표준 도구가 있다면 프라이빗 레지스트리에 커스텀 Feature를 올려서 팀 전체에 배포하는 것도 가능하다.
devcontainer Lifecycle Hooks – 컨테이너가 살아나는 순간을 제어한다

컨테이너가 만들어지고 시작되는 과정에서 특정 시점에 명령을 끼워 넣을 수 있다. 의존성 설치, DB 시딩, SSL 인증서 세팅 같은 반복 작업을 자동으로 처리하는 데 쓴다. 공식 스펙(containers.dev/implementors/json_reference)에 정의된 훅은 여섯 가지다.
| Hook | 실행 시점 | 대표 용도 |
|---|---|---|
initializeCommand | 컨테이너 생성 전, 호스트에서 실행 | 호스트 사전 조건 검증, 환경변수 세팅 |
onCreateCommand | 컨테이너 최초 생성 시 | 저장소 서브모듈 초기화 |
updateContentCommand | 소스 변경 감지 시 | 코드 재생성, 빌드 캐시 갱신 |
postCreateCommand | 컨테이너 생성 직후 (create + update 이후) | 의존성 설치, DB 마이그레이션 |
postStartCommand | 컨테이너 시작될 때마다 | 백그라운드 서비스 기동 |
postAttachCommand | IDE가 컨테이너에 접속할 때마다 | 환영 메시지, 상태 점검 |
initializeCommand만 유일하게 호스트 머신에서 실행된다는 점에 주의하자. 나머지 다섯 개는 전부 컨테이너 안에서 돌아간다.
{
"postCreateCommand": {
"deps": "npm install",
"db": "npm run db:migrate",
"seed": "npm run db:seed"
},
"postStartCommand": "npm run dev:services"
}JSONpostCreateCommand에 객체를 넘기면 각 명령이 병렬로 돌아간다. deps, db, seed는 그냥 레이블이라 이름은 자유롭게 정하면 된다. npm install, DB 마이그레이션, 시드 데이터 삽입이 동시에 진행되니 초기 대기 시간이 확 줄어든다. 헷갈리기 쉬운 부분인데, 문자열로 넘기면 순차 실행이고 객체로 넘기면 병렬 실행이다.
devcontainer로 팀 전체가 같은 환경에서 일하려면
혼자 쓸 때도 편하지만, Dev Container가 빛을 발하는 건 팀에서 쓸 때다. devcontainer.json을 .devcontainer/ 디렉토리에 커밋하면 모든 팀원이 같은 환경을 공유하게 된다. 다만 운영하다 보면 몇 가지 원칙이 필요하다.
devcontainer.json에는 팀 표준 도구만 넣는다. 린터, 포매터, 필수 확장 정도다. Vim 플러그인이나 개인 테마 같은 건 각자 VS Code settings.json에서 알아서 관리하도록 두는 게 낫다. 컨테이너 시작 속도도 신경 써야 한다. Dockerfile을 매번 빌드하면 첫 실행에 5~10분씩 잡아먹는다. 프리빌트 이미지를 레지스트리에 올려두면 수 초 만에 뜬다. freeCodeCamp의 Dev Container 도입 사례에서도 프리빌트 이미지 전환 후 팀원 평균 컨테이너 시작 시간이 8분에서 15초로 단축되었다고 보고한 바 있다.
devcontainer CLI로 CI/CD에서도 같은 환경 쓰기
로컬에서 통과한 테스트가 CI에서 실패하는 문제는 devcontainer CLI로 해결한다. npm으로 설치하면 CI 서버에서도 로컬과 동일한 컨테이너 환경으로 테스트를 돌릴 수 있다. devcontainers/cli 패키지는 npm에서 꾸준히 다운로드 수가 늘고 있다.
npm install -g @devcontainers/cli
devcontainer build --workspace-folder .
devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . npm testShellScript순서대로 컨테이너를 빌드하고, 올리고, 안에서 테스트를 실행한다. --workspace-folder는 devcontainer.json이 있는 프로젝트 루트를 가리킨다. devcontainer exec에 넘기는 명령어는 자유롭게 바꿀 수 있어서 npm test 대신 ./gradlew test나 pytest를 넣어도 된다.
직접 CLI를 쓰는 게 번거롭다면 devcontainers/ci 공식 GitHub Action이 있다.
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: devcontainers/ci@v0.3
with:
runCmd: npm testYAML이 Action은 저장소의 devcontainer.json을 그대로 읽어서 컨테이너를 빌드하고, runCmd에 지정한 명령을 실행한다. 이미지 캐싱도 자동으로 처리되기 때문에 두 번째 실행부터는 빌드 시간이 크게 줄어든다. 설정 파일이 하나이니 로컬과 CI의 환경 차이가 구조적으로 발생할 수 없다.
Dev Container vs Vagrant vs Docker Compose, 뭐가 다른가

“그냥 Vagrant 쓰면 안 돼?” 혹은 “Docker Compose만으로 충분하지 않아?”라는 질문이 나올 수 있다. 세 도구의 목적은 겹치지만, 접근 방식이 다르다. Vagrant는 VM 기반이라 무겁고, Docker Compose 단독으로는 IDE 연동이 수동이다.
| 항목 | Dev Container | Vagrant | Docker Compose (단독) |
|---|---|---|---|
| IDE 통합 | 네이티브 (VS Code, JetBrains) | 플러그인 필요 | 수동 설정 |
| 설정 파일 | devcontainer.json | Vagrantfile | docker-compose.yml |
| 시작 속도 | 수 초 | 수 분 | 수 초 |
| 클라우드 지원 | Codespaces, DevPod | 제한적 | 수동 |
| 학습 곡선 | 낮음 | 중간 | 중간 |
| 도구 생태계 | 공식 28개 + 커뮤니티 수백 개 Feature | 커뮤니티 Box | 해당 없음 |
| 리소스 사용 | 컨테이너 수준 | VM 수준 (무거움) | 컨테이너 수준 |
이미 Docker Compose를 쓰고 있다면 Dev Container를 얹는 게 가장 현실적이다. dockerComposeFile로 기존 Compose 파일을 그대로 참조하면 되니까 마이그레이션 비용이 거의 없다. Vagrant는 윈도우 드라이버 테스트처럼 OS 수준 격리가 꼭 필요한 경우에나 고르면 된다.
직접 써보니 이렇더라
예전에 새 백엔드 개발자가 들어오면 위키 문서 링크를 던져주고 반나절을 기다렸다. JDK 설치, IntelliJ 세팅, Docker로 PostgreSQL 띄우기, 환경변수 잡기. 중간에 JDK 버전이 안 맞거나 Gradle 래퍼가 꼬이면 하루가 날아갔다. devcontainer.json을 넣은 뒤로는 “저장소 클론 받고 Reopen in Container 누르세요”가 온보딩의 전부다. 솔직히 처음에는 “이게 진짜 될까” 싶었는데, 된다.
예상 못 한 보너스도 있었다. 누군가 Node.js 버전을 올리거나 린터를 추가하면 devcontainer.json 변경이 PR에 잡힌다. 코드 리뷰에서 환경 설정까지 같이 보게 되는 거다. 위키 문서 구석에 묻혀서 아무도 업데이트 안 하던 그 세팅 가이드가 사라졌다. 개인적으로 좋은 개발환경이란 존재를 의식할 필요 없는 환경이라고 생각하는데, devcontainer.json이 딱 그렇다. 터미널 기반 개발 도구에 관심이 있다면 lazygit 사용법 총정리도 함께 읽어보면 좋다.
FAQ
Dev Container는 Docker 없이도 쓸 수 있나요?
현재로서는 Docker(또는 호환 런타임)가 필수다. 다만 GitHub Codespaces를 쓰면 로컬에 Docker 없이도 클라우드에서 Dev Container 환경을 돌릴 수 있다. DevPod는 Docker 외에 Kubernetes나 AWS도 프로바이더로 지원한다.
JetBrains IDE에서도 Dev Container를 지원하나요?
지원한다. JetBrains Gateway가 devcontainer.json을 읽어서 원격 개발환경을 만들어 준다. IntelliJ IDEA, PyCharm, WebStorm 모두 된다. 2025년부터 지원이 안정화되었고, VS Code 팀원과 같은 devcontainer.json을 공유하는 데 문제가 없다.
Dev Container 안에서 Docker를 사용할 수 있나요?
된다. ghcr.io/devcontainers/features/docker-in-docker:1 Feature를 추가하면 컨테이너 안에서 Docker 데몬이 돌아간다. Testcontainers로 통합 테스트를 돌리거나 Docker 이미지를 빌드하는 작업을 Dev Container 안에서 그대로 할 수 있다. 한 가지 주의할 점은 Docker-in-Docker가 privileged 모드를 요구한다는 것이다. 조직 보안 정책에 따라 막혀 있을 수 있으니 미리 확인하자.
기존 프로젝트에 Dev Container를 추가하면 기존 개발 흐름이 깨지나요?
안 깨진다. .devcontainer/ 디렉토리 하나 추가하는 것뿐이다. Dev Container를 안 쓰는 팀원은 이 디렉토리를 그냥 무시하면 된다. 기존 Dockerfile이나 docker-compose.yml과도 충돌 없이 공존하고, devcontainer.json에서 기존 Compose 파일을 참조하는 식으로 점진적으로 도입하면 된다.
