서론
포트 충돌을 이전에 해결하지 못했다.현재까지 진행한 내용은 내가 생각했던 개발 환경 세팅과는 다른 방향이었다.
이에 대해 고민하며 지금까지의 접근법을 정리하고자 한다.
지금까지의 상황
내가 구현하고 싶었던 환경
- 컨테이너를 통한 개발 환경 통일
- 컨테이너 내부에서 개발 진행 후 빌드 및 디버깅
1차로 구현한 환경 (https://seomj74.tistory.com/390)
- 컨테이너를 단순히 실행 도구(Runtime)로만 사용
- docker-compose up 한 번에 모든 서비스가 다 동작
- Front
- 이미지 빌드에서 Node.js 실행 환경만 갖춘 상태
- /app/node_modules 익명 볼륨을 생성
- 운영체제 간의 라이브러리 충돌 방지(호스트와 컨테이너)
- 컨테이너가 생성될 때마다 npm install을 체크 (docker-compose command)
- 컨테이너가 생성될 때마다 package.json을 읽어 라이브러리를 설치
- 기동 속도 저하
- Back
- 이미지 빌드에서 ubuntu 위에 Java만 설치하여 순수 JDK 환경 상태
- Ubuntu 이미지 사용 (ubuntu:22.04)
- 자바를 실행하기에는 불필요한 패키지가 많아 무거움
- Ubuntu 이미지 사용 (ubuntu:22.04)
- 호스트 캐시( ~/.gradle:/root/.gradle )를 공유
- 초기 구동이 빠름
- 파일 잠금(Lock) 충돌이나 권한 문제 발생
- ./gradlew 파일을 실행
- /app 폴더에 있는 코드를 컴파일하고 빌드하여 Spring Boot 앱 실행
- 이미지 빌드에서 ubuntu 위에 Java만 설치하여 순수 JDK 환경 상태
- 문제
- JDK는 컨테이너에, 캐시와 코드는 호스트에 있는 것을 사용
- 개발 환경 통일과 거리가 멈
- JDK는 컨테이너에, 캐시와 코드는 호스트에 있는 것을 사용
2차로 구현한 환경 (https://seomj74.tistory.com/391)
- docker-compose up을 진행하지만 실행은 선택적
- WSL 2 기반 환경 통일
- WSL 2 내부에 IDE의 핵심 엔진 설치
- IntelliJ와 WebStorm에서 WSL 2 엔진과 통신하며 진행
- Front
- 이미지 빌드 시 npm install 진행
- 소스 코드가 변해도 package.json이 수정되지 않으면 속도가 빠름
- 수정 시 컨테이너 내 npm install 혹은 이미지 재빌드 필요
- 기존에 생성되던 익명 볼륨을 기명 볼륨으로 바꾸어 재사용성을 높임
- 호스트와 컨테이너 분리
- 호스트의 node_modules가 컨테이너를 덮어 쓰지 않음으로써 컨테이너 내 빌드 안정성 확보
- 이미지 빌드 시 npm install 진행
- Back
- 이미지 빌드
- 경량화 이미지 사용 (eclipse-temurin:21-jdk-alpine)
- gradlew, build.gradle 등 설정 파일만 먼저 복사하여 빌드 도구 캐싱
- build.gradle이 변경되면 ./gradlew build 혹은 이미지 재빌드 필요
- Gradle 실행 엔진 다운로드
- profiles를 통해 선택적 실행
- DB, Redis 등 필요한 도구만 띄워두고 로컬 개발 진행 후 컨테이너를 띄워 테스트
- 리소스 관리 효율적
- DB, Redis 등 필요한 도구만 띄워두고 로컬 개발 진행 후 컨테이너를 띄워 테스트
- 빌드 결과물과 캐시 격리를 통해 컴파일 충돌 방지
- 이미지 빌드
- 문제
- package.json이나 build.gradle이 변경될 때마다 이미지를 다시 빌드하거나 컨테이너 내부에서 수동 설치해야 함
정리
1차와 2차의 경우 내가 구현하고자 하는 방향과 많이 다르다는 것을 알 수 있다.
본인의 경우, 컨테이너가 개발 환경 역할만 하길 바랬기에 컨테이너를 띄우고 내부에 접속해서 빌드, 디버깅이 가능한 환경을 바랬다. Java, OS, 의존성 버전 등을 맞춰야 추후 "내 컴퓨터에선 되는데?"를 방지할 수 있을 것이라 생각했다.
하지만, 이는 앱 자체를 실행하는 환경에 가깝다.
프론트의 경우에는 HMR(Hot Module Replacement)로 인해 빌드없이 소스 코드 수정만으로 웹 사이트에서 즉시 확인이 가능했다.
백엔드의 경우에는 수정 시 마다 빌드가 필요했다. 컨테이너가 실행 중인 상황이며 이미 포트를 점유하고 있기에 개발자가 내부에서 수동 빌드 및 실행을 하려고 하면 포트 충돌이 발생했다.
개선
이를 해결하기 위해 다시 고민해보기 시작했다. 알아보던 와중 Dev Container에서 devcontainer.json이라는 게 존재한다는 것을 발견했다.
devcontainer.json
정의된 도구와 런타임 스택에 대한 개발 컨테이너를 구성하는 데 필요한 모든 메타데이터와 설정 값을 가진다.
더 자세한 항목들이 궁금하면 아래 링크를 참고하길 바란다.
https://containers.dev/implementors/json_reference/
Dev Container metadata reference
The devcontainer.json file contains any needed metadata and settings required to configure a development container for a given well-defined tool and runtime stack. It can be used by tools and services that support the dev container spec to create a develop
containers.dev
Dockerfile은 OS와 런타임을 어떻게 구성할지를 정의하는 파일로, 설계도와 같은 역할
docker-compose는 서비스 간의 네트워크와 데이터 저장소를 연결하는 역할
devcontainer.json은 IDE가 개발자를 위해 수행할 동작을 정의
적용
3차로 구현할 환경
- 실행하지 않고 컨테이너만 유지하여 개발 환경만 제공
- 빌드를 도커에서 진행하지 않고 개발자가 필요할 때 IDE에서 직접 진행
- Front
- 이미지 빌드
- npm install을 진행하여 frontend_node_modules 볼륨에 저장
- bash와 git 등 개발에 필요한 도구들을 미리 설치
- 대기 상태 유지
- devcontainer.json을 통해 VS Code나 WebStorm/IntelliJ같은 IDE가 컨테이너 내부의 서비스에 직접 접
- 패키지를 추가해야 하면 IDE 터미널에서 npm install 실행
- npm run dev를 통해 개발자아 원할 때 앱 실행
- 이미지 빌드
- Back
- 이미지 빌드
- eclipse-temurin:21-jdk를 사용하여 git, curl, procps 등을 설치
- ENV GRADLE_USER_HOME=/home/gradle_cache와 기명 볼륨(gradle_cache)을 연결
- postCreateCommand를 통해 컨테이너가 생성되자마자 실행 권한 부여와 Gradle 엔진 확인
- IntelliJ가 컨테이너 내부로 접속하여 소스 코드를 인덱싱하고 직접 명령
- 이미지 빌드
코드
Front devcontainer.json
{
"name": "Frontend Dev Environment",
"dockerComposeFile": "../../docker-compose.yml",
"service": "frontend",
"workspaceFolder": "/app"
"forwardPorts": [5173]
}
Back devcontainer.json
{
"name": "Backend Dev Environment",
"dockerComposeFile": "../../docker-compose.yml",
"service": "backend",
"workspaceFolder": "/app",
"context": "../../",
"customizations": {
"jetbrains": {
"backend": "IntelliJ"
}
},
"postCreateCommand": "chmod +x gradlew && ./gradlew --version",
"forwardPorts": [8080, 5005, 3306],
"remoteUser": "root"
}
docker-compose.yaml
services:
backend:
build:
context: ../../
dockerfile: ./Infra/local_dev/backend.Dockerfile
volumes:
- ../../Backend:/app
- /app/build
- /app/.gradle
- gradle_cache:/home/gradle_cache
ports:
- "8080:8080"
- "5005:5005"
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/testdb
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=1234
- SPRING_DATA_REDIS_HOST=redis
depends_on:
- mysql
- redis
frontend:
build:
context: ../../
dockerfile: ./Infra/local_dev/frontend.Dockerfile
volumes:
- ../../Frontend:/app
- frontend_node_modules:/app/node_modules
ports:
- "5173:5173"
mysql:
image: mysql:8.0
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=1234
- MYSQL_DATABASE=testdb
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7.2-alpine
volumes:
- redis_data:/data
ports:
- "6379:6379"
volumes:
mysql_data:
frontend_node_modules:
redis_data:
gradle_cache:
Front Dockerfile
FROM node:20-alpine
WORKDIR /app
RUN apk add --no-cache bash git
COPY Frontend/package*.json ./
RUN npm install
COPY Frontend/ .
CMD ["tail", "-f", "/dev/null"]
Back Dockerfile
FROM eclipse-temurin:21-jdk
WORKDIR /app
RUN apt-get update && apt-get install -y \
git \
bash \
curl \
procps \
&& rm -rf /var/lib/apt/lists/*
ENV GRADLE_USER_HOME=/home/gradle_cache
COPY Backend/gradlew .
COPY Backend/gradle gradle
COPY Backend/build.gradle Backend/settings.gradle ./
RUN chmod +x gradlew
RUN ./gradlew --version --no-daemon
COPY Backend/ .
CMD ["tail", "-f", "/dev/null"]
VS Code
VS Code에서 .devcontainer 디렉터리가 있는 위치를 오픈한다.
참고로 .devcontainer가 오픈한 폴더 바로 아래에 있지 않으면 못 찾으니 유의하도록!
dev container 플러그인을 설치해야 한다. 이는 설치되어 있다는 가정하에 설명한다. 설치하지 않았다면 플러그인에서 검색해서 그냥 설치해주면 끝이다. (간단)
그러면 오른쪽 하단에 Reopen in Container라고 뜬다. 이걸 클릭하자.

혹은 Ctrl + Shift + P로 접근해서 Rebuild and Reopen in Container를 선택하자.

그러면 아래와 같이 devcontainer.json을 기준으로 어떤 것을 오픈할 것인지 묻는다.

Front
Front 컨테이너로 접속해서 실행하면 된다.
npm run dev -- --host 0.0.0.0

Back
필요한 플러그인을 설치하고 Run하면 된다.


WebStorm & IntelliJ
참고로 WebStorm과 IntelliJ는 계속 시도했으나 접속이 안된다. Ultimate 버전에서만 제공하는 기능으로 알고 있다.
https://www.jetbrains.com/help/idea/connect-to-devcontainer.html
Dev Container overview | IntelliJ IDEA
www.jetbrains.com
devcontainer.json에서 우클릭 후 Dev Containers에서 실행하면 된다. 아마 Ultimate 버전을 사용 중이라면 무리없이 접근이 되지 않을까 싶다.

참고
'Study > Docker' 카테고리의 다른 글
| [Docker] 로컬 개발 환경 세팅(vscode, IntelliJ) (2) (2) | 2026.01.24 |
|---|---|
| [Docker] 로컬 개발 환경 세팅(vscode, IntelliJ) (1) - 실패 (1) | 2026.01.21 |
| [Docker]Docker Image Layer (0) | 2023.11.17 |
| [Docker]Docker 사용하기 2 (공유) (0) | 2023.02.11 |
| [Docker]Docker 사용하기 (0) | 2023.02.11 |