윈도우에서 Docker로 리눅스 개발 환경 만드는 법 설치부터 실전 세팅까지

2026-06-16 · Uncategorized · 읽는데 31분

윈도우에서 Docker로 리눅스 개발 환경 만드는 법 설치부터 실전 세팅까지

썸네일

이 글을 읽기 전에 알아야 할 것

몇 달 전, 나는 프로젝트 하나 때문에 밤샘을 했다. Springboot로 만든 개인 대시보드가 MariaDB에 의존하고 있었는데, 동아리 실습에서 MySQL을 써야 하는 상황이었다.

"뭐가 다르겠어"라는 안일한 생각에 무작정 MySQL을 설치했다. 결과는 처참했다.

두 DB가 포트 충돌을 일으키고, 데이터가 꼬이고, 결국 MariaDB를 밀어버렸다. 이 경험 이후로 나는 Docker의 필요성을 뼈저리게 느꼈다.

ChatGPT에게 조언을 구했더니 "Docker 쓰세요"라는 답변이 돌아왔다. 처음에는 "또 가상머신 설치하라는 거야?"라는 생각이 들었다.

VirtualBox나 VMware로 리눅스를 띄워본 경험이 있는 사람이라면 알 것이다. 무겁고, 느리고, 호스트와의 파일 공유도 불편하다.

하지만 Docker는 달랐다. 컨테이너라는 개념을 사용해서, 가상머신보다 훨씬 가볍고 빠르다.

실제로 Docker 컨테이너는 일반 가상머신 대비 약 50-70% 더 빠른 부팅 시간을 자랑한다. 벤치마크에 따르면, 동일한 애플리케이션을 실행할 때 Docker 컨테이너는 가상머신보다 메모리 사용량이 평균 30-40% 적다.

항목 Docker 컨테이너 전통적 가상머신 (VMware, VirtualBox)
부팅 시간 1-2초 30초-2분
디스크 용량 수십 MB - 수백 MB 수 GB 이상
메모리 효율 호스트 커널 공유로 낮은 오버헤드 OS 전체를 띄워 높은 오버헤드
성능 저하 거의 없음 (네이티브의 95-99%) 10-20% 성능 손실
격리 수준 프로세스 수준 격리 완전한 OS 격리
설정 난이도 Dockerfile로 코드화 가능 GUI/CLI 수동 설정 필요

Docker가 이렇게 효율적인 이유는 간단하다. 가상머신이 완전한 운영체제를 게스트로 띄우는 반면, Docker는 호스트의 리눅스 커널을 공유하면서 필요한 라이브러리와 바이너리만 격리해서 실행한다.

그래서 "컨테이너"라는 이름이 붙은 것이다. 하지만 여기서 문제가 생긴다.

Docker는 태생이 리눅스 기반이다. 윈도우에서 Docker를 사용하려면 어떻게 해야 할까? 과거에는 Docker Toolbox라는 도구를 써서 VirtualBox 위에 리눅스 VM을 띄우고 그 위에서 Docker를 돌리는 방식이었다.

성능이 형편없었다. 그러다 Microsoft가 WSL2(Windows Subsystem for Linux 2)를 내놓으면서 상황이 완전히 바뀌었다.

WSL2는 윈도우 안에서 실제 리눅스 커널을 실행할 수 있게 해준다. 여기에 Docker Desktop이 WSL2 백엔드를 지원하면서, 이제 윈도우에서도 거의 네이티브에 가까운 성능으로 Docker를 쓸 수 있게 되었다.

그럼 이제 본격적으로 시작해보자. 당신의 윈도우 PC를 리눅스 개발 환경으로 탈바꿈시키는 여정을.

설치 전 윈도우 설정

Docker Desktop을 설치하기 전에, 먼저 윈도우가 컨테이너 기술을 지원할 수 있도록 하드웨어와 소프트웨어를 준비해야 한다. 이 단계를 건너뛰면 설치 중에 "Hardware assisted virtualization must be enabled"라는 오류를 만나게 될 확률이 높다.

내 경험을 말해주자면, 처음 Docker를 설치할 때 이 오류를 보고 30분 동안 구글링을 한 적이 있다. 알고 보니 BIOS 설정 하나만 바꾸면 되는 문제였다.

그 이후로는 설치 전에 반드시 하드웨어 가상화를 확인하는 습관이 생겼다. BIOS에서 확인해야 할 설정:

컴퓨터를 부팅할 때 F2, Del, F10 등의 키를 눌러 BIOS/UEFI 설정으로 진입한다.

여기서 찾아야 할 항목은 보통 다음과 같다:

  • Intel VT-x (Intel 사용자) 또는 AMD-V (AMD 사용자)
  • VT-d (I/O 가상화)
  • SVM Mode (일부 AMD 보드에서는 이렇게 표시됨)

이 모든 항목이 Enabled 상태여야 한다. 대부분의 최신 PC에서는 기본적으로 활성화되어 있지만, 게이밍 노트북이나 일부 조립 PC에서는 꺼져 있는 경우가 종종 있다.

이 설정을 마치면, 윈도우에서 WSL2를 활성화할 차례다. 관리자 권한으로 PowerShell을 열고 다음 명령어를 차례대로 입력한다:

powershell dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

첫 번째 명령어는 WSL 기능을 켜고, 두 번째 명령어는 가상 머신 플랫폼을 활성화한다. 이 작업이 끝나면 반드시 재부팅해야 한다.

재부팅하지 않으면 다음 단계로 넘어갈 수 없다. 재부팅 후, 다시 PowerShell을 관리자 권한으로 열고 WSL2를 기본 버전으로 설정한다:

powershell wsl --set-default-version 2

이 명령어가 실패한다면, 리눅스 커널 업데이트 패키지가 필요하다는 메시지가 뜰 것이다. Microsoft 공식 문서에서 "WSL2 Linux kernel update package"를 검색해서 다운로드받으면 된다.

파일 하나 받아서 설치하는 것뿐이니 2분이면 끝난다. 이제 리눅스 배포판을 설치할 차례다.

Microsoft Store에서 "Ubuntu"를 검색해서 설치하거나, PowerShell에서 직접 설치할 수 있다:

powershell wsl --install -d Ubuntu-22.04

설치가 완료되면 Ubuntu가 자동으로 실행되면서 사용자 이름과 비밀번호를 설정하라는 화면이 나온다. 여기서 설정한 계정 정보는 앞으로 WSL에서 sudo 명령어를 쓸 때 필요하니 잊지 말자.

설정 항목 필수 여부 비고
BIOS 가상화 활성화 필수 Intel VT-x 또는 AMD-V
WSL 기능 활성화 필수 PowerShell 명령어로
VirtualMachinePlatform 활성화 필수 WSL2에 필요
WSL2 기본 버전 설정 필수 wsl --set-default-version 2
리눅스 커널 업데이트 상황에 따라 오류 메시지 확인 후
Ubuntu 배포판 설치 추천 22.04 LTS 안정적

여기서 중요한 포인트: WSL 버전을 반드시 2로 설정해야 한다. WSL1은 리눅스 시스템 콜을 윈도우 시스템 콜로 변환하는 방식이라 Docker 엔진을 제대로 실행할 수 없다.

실제로 WSL1에서 Docker를 실행하려고 하면 "Docker does not support WSL1"이라는 오류가 발생한다. WSL2가 설치되었는지 확인하려면 다음 명령어를 입력한다:

powershell wsl -l -v

출력 결과에 Ubuntu의 VERSION이 2로 표시되어야 한다. 만약 1로 나온다면, 다음 명령어로 버전을 변경할 수 있다:

powershell wsl --set-version Ubuntu-22.04 2

이 과정이 끝나면 윈도우는 Docker를 받아들일 준비가 완료된 것이다. 이제 진짜 재미있는 부분이 시작된다.

다른 내용도 보러가기 #1

Docker Desktop 설치와 WSL2 연동

Docker Desktop을 설치하는 것은 생각보다 단순하다. Docker 공식 홈페이지(docker.com)에 접속해서 "Docker Desktop for Windows"를 다운로드받으면 된다.

설치 파일은 약 500MB 정도로, 인터넷 속도에 따라 2-5분 정도 소요된다. 설치를 실행하면 두 가지 옵션이 나온다:

  • Use WSL 2 instead of Hyper-V (추천)
  • Use Hyper-V

반드시 첫 번째 옵션을 선택하자. Hyper-V를 선택하면 Windows Pro/Enterprise에서만 동작하고, Docker 성능도 WSL2 대비 10-15% 느리다. 게다가 Hyper-V는 VirtualBox나 VMware와 충돌을 일으키는 경우가 많아서, 개발자들 사이에서는 WSL2가 사실상 표준이 되었다.

설치가 완료되면 윈도우를 재시작해야 한다. 재시작 후 바탕화면 우측 하단 트레이에 고래 모양 아이콘이 나타나면 성공이다.

하지만 여기서 끝이 아니다. Docker Desktop이 WSL2와 제대로 연동되도록 설정을 만져줘야 한다.

트레이의 Docker 아이콘을 우클릭하고 Settings를 선택한다. 왼쪽 메뉴에서 Resources → WSL Integration으로 이동한다.

여기서 "Enable integration with my default WSL distro" 옵션을 활성화하고, 아래 목록에서 설치한 Ubuntu를 체크한다. 이 설정의 의미는 이렇다: Docker Desktop이 WSL2 안에서 실행되도록 함으로써, 윈도우에서 리눅스 컨테이너를 마치 네이티브처럼 사용할 수 있게 된다.

이 설정을 하지 않으면 Docker Desktop이 자체 Hyper-V VM을 띄우게 되는데, 그러면 파일 공유 속도가 느려지고 WSL과의 통합도 불편해진다. 설정을 마치고 Apply & Restart 버튼을 누르면 Docker Desktop이 재시작된다.

Docker Desktop 설정 항목 권장값 이유
WSL 2 백엔드 사용 활성화 성능 최적화, Hyper-V 충돌 방지
WSL 통합 활성화 (Ubuntu 선택) 파일 공유 속도 향상
Resources - Memory 4-8GB (여유에 따라) 컨테이너 실행에 필요
Resources - CPUs 2-4개 빌드 속도 향상
Resources - Swap 1-2GB 메모리 부족 시 대비

이제 설치가 제대로 되었는지 확인해보자. PowerShell이나 WSL 터미널을 열고 다음 명령어를 입력한다:

bash docker --version

버전 정보가 출력되면 Docker가 정상적으로 설치된 것이다. 이어서 Hello World 컨테이너를 실행해보자:

bash docker run hello-world

처음 실행하면 이미지를 다운로드받은 후 "Hello from Docker!" 메시지가 출력된다. 이 메시지를 보면 얼마나 감격스러운지 모른다.

나는 이 문구를 보고 "드디어 해냈다"라는 생각에 주먹을 쥐었다. 하지만 모든 것이 순조롭지만은 않았다.

Docker Desktop을 설치한 지 일주일쯤 지나서, 갑자기 vmmem이라는 프로세스가 메모리를 6GB나 잡아먹는 현상이 발생했다. 구글링해보니 WSL2의 메모리 관리 문제였다.

해결 방법은 간단했다. 사용자 홈 디렉토리(C:\Users\사용자이름)에 .wslconfig 파일을 만들고 다음 내용을 입력했다:

[wsl2] memory=4GB processors=4 swap=2GB localhostForwarding=true

이 설정은 WSL2가 사용할 수 있는 최대 메모리를 4GB로 제한하고, CPU 코어를 4개로 지정하며, 스왑 공간을 2GB로 설정한다. localhostForwarding은 WSL2 내부에서 실행되는 서비스를 윈도우 브라우저에서 localhost로 접근할 수 있게 해준다.

설정을 적용하려면 PowerShell에서 다음 명령어로 WSL을 재시작해야 한다:

powershell wsl --shutdown

그리고 WSL 터미널을 다시 열면 설정이 적용된다. 이 작업 이후로 메모리 문제는 완전히 사라졌다.

Docker Desktop 설치가 끝났다면, 이제 진짜 개발 환경을 구축할 차례다. 단순히 Docker가 돌아간다는 사실만으로는 아무것도 할 수 없다.

우리가 원하는 건 "어떻게 개발에 활용할 것인가"다.

VS Code로 컨테이너 개발 환경 구성하기

Docker Desktop만 설치했다고 해서 바로 개발을 시작할 수 있는 건 아니다. 실제로 유용하게 쓰려면 VS Code와의 통합이 필수다.

VS Code는 마이크로소프트가 만든 에디터답게 WSL 및 Docker와의 연동이 환상적이다. 먼저 VS Code를 설치하지 않았다면 공식 사이트(code.visualstudio.com)에서 다운로드받아 설치한다.

설치가 끝나면 세 가지 확장 프로그램이 필요하다:

  1. Remote - WSL - WSL 내부에서 VS Code를 실행하게 해준다
  2. Dev Containers - Docker 컨테이너 내부에서 VS Code를 실행하게 해준다
  3. Docker - VS Code 내에서 Docker 명령어를 GUI로 실행할 수 있게 해준다

이 세 가지 확장 프로그램을 설치하면, 더 이상 터미널에서만 작업할 필요가 없다. VS Code의 모든 기능(인텔리센스, 디버깅, 익스텐션)을 컨테이너 안에서도 그대로 사용할 수 있다.

실전 예제: Django 개발 환경 구축

실제 프로젝트로 예를 들어보자. 우리가 Django 웹 애플리케이션을 개발한다고 가정해보자. 일반적인 방법은 로컬에 Python을 설치하고, 가상 환경을 만들고, 필요한 패키지를 설치하는 것이다. 하지만 이 방법은 "내 컴퓨터에서는 되는데"라는 문제를 자주 일으킨다.

Docker를 사용하면 이 문제가 완전히 해결된다. 프로젝트 루트 디렉토리에 .devcontainer 폴더를 만들고, 그 안에 devcontainer.json 파일과 Dockerfile을 작성한다.

Dockerfile 예시:

```dockerfile FROM python:3.11-slim

RUN apt-get update && apt-get install -y \ git \ curl \ && rm -rf /var/lib/apt/lists/*

WORKDIR /workspace

COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt ```

devcontainer.json 예시:

json { "name": "Django Dev Container", "build": { "dockerfile": "Dockerfile" }, "forwardPorts": [8000], "customizations": { "vscode": { "extensions": [ "ms-python.python", "ms-python.vscode-pylance" ] } } }

이 파일들을 만들고 VS Code에서 명령 팔레트(Ctrl+Shift+P)를 열어 "Dev Containers: Reopen in Container"를 선택하면, VS Code가 자동으로 Docker 이미지를 빌드하고 컨테이너를 실행한 후 그 안에서 작업할 수 있게 해준다. 처음 이 기능을 썼을 때는 "이게 된다고?"라는 생각이 들었다.

실제로 컨테이너 안에서 VS Code가 떴고, 파일을 수정하면 컨테이너 내부에 바로 반영되었다. 터미널도 컨테이너 안에서 열렸고, Python 버전도 컨테이너에 설정된 대로였다.

개발 방식 장점 단점
로컬 직접 설치 설정 간단, 직관적 환경 충돌 위험, 재현 어려움
가상 환경 (venv) Python 패키지 격리 시스템 라이브러리 충돌 가능
Docker 컨테이너 완전한 격리, 재현성 초기 설정 필요, 디스크 사용량 증가
Docker + Dev Containers VS Code 통합, 편의성 확장 프로그램 의존

Dev Containers의 가장 큰 장점은 "팀 전체가 동일한 환경"을 가질 수 있다는 점이다. 프로젝트 리포지토리에 .devcontainer 폴더만 포함되어 있으면, 새로운 팀원이 와서 git clone 한 다음 "Reopen in Container"를 누르는 것만으로 모든 개발 환경이 자동으로 구성된다.

실제로 우리 동아리에서 이 방식을 도입했을 때, 신입 부원의 환경 설정 시간이 평균 2시간에서 15분으로 줄었다. "파이썬 버전이 달라요", "패키지 설치가 안 돼요" 같은 질문도 사라졌다.

하지만 Dev Containers에도 트레이드오프가 있다. 컨테이너 안에서 작업하다 보면 파일 I/O가 약간 느려질 수 있다.

특히 WSL2의 경우, 윈도우 파일 시스템(/mnt/c)에 접근할 때 성능 저하가 발생한다. 이 문제를 피하려면 프로젝트 파일을 WSL2 파일 시스템(예: /home/username/projects)에 저장하는 것이 좋다.

VS Code 하단 왼쪽 모서리를 보면 초록색 표시기가 있다. 여기에 "WSL: Ubuntu" 또는 "Dev Container: Django"라고 표시되면 현재 작업 중인 환경을 바로 알 수 있다.

이 표시기를 클릭하면 다른 환경으로 전환할 수도 있다. 이제 실제로 컨테이너 안에서 Django 서버를 실행해보자. VS Code의 통합 터미널(Ctrl+`)을 열고 다음 명령어를 입력한다:

bash python manage.py runserver 0.0.0.0:8000

그리고 윈도우 브라우저에서 http://localhost:8000에 접속하면 Django 기본 페이지가 뜬다. 이 모든 과정이 컨테이너 안에서 실행되고 있지만, 우리는 마치 로컬에서 작업하는 것처럼 느낄 수 있다.

Docker Compose로 멀티 컨테이너 운영하기

하나의 컨테이너만으로는 실제 애플리케이션을 구성하기 어렵다. 대부분의 웹 애플리케이션은 웹 서버, 데이터베이스, 캐시 서버 등 여러 컴포넌트로 이루어져 있다.

이들을 각각 컨테이너로 띄우고 서로 연결하려면 Docker Compose가 필요하다. Docker Compose는 YAML 파일 하나로 여러 컨테이너의 실행을 정의하고 관리할 수 있게 해준다.

Docker Desktop을 설치하면 Compose도 함께 설치되므로 별도로 설치할 필요가 없다. 실전 예제: Spring Boot + MySQL + Redis

실제로 내가 사용 중인 스프링 부트 프로젝트의 구성을 예로 들어보자. 이 프로젝트는 데이터베이스로 MySQL을, 세션 저장소로 Redis를 사용한다.

Docker Compose를 사용하면 이 세 가지를 한 번에 띄울 수 있다. 프로젝트 루트에 docker-compose.yml 파일을 만든다:

```yaml version: '3.8'

services: mysql: image: mysql:8.0 container_name: spring-mysql environment: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_DATABASE: myapp MYSQL_USER: user MYSQL_PASSWORD: userpassword ports: - "3306:3306" volumes: - mysql-data:/var/lib/mysql networks: - app-network

redis: image: redis:7-alpine container_name: spring-redis ports: - "6379:6379" networks: - app-network

app: build: . container_name: spring-app ports: - "8080:8080" environment: SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/myapp SPRING_DATASOURCE_USERNAME: user SPRING_DATASOURCE_PASSWORD: userpassword SPRING_REDIS_HOST: redis depends_on: - mysql - redis networks: - app-network

volumes: mysql-data:

networks: app-network: ```

이 파일의 핵심은 networks 항목이다. 모든 서비스를 같은 네트워크에 배치하면, 서비스 이름(예: mysql, redis)으로 서로를 찾을 수 있다.

그래서 스프링 부트 설정에서 데이터베이스 URL을 jdbc:mysql://mysql:3306/myapp처럼 쓸 수 있는 것이다. depends_on은 서비스 간 실행 순서를 지정한다.

여기서는 MySQL과 Redis가 먼저 실행된 후에 애플리케이션이 실행된다. 하지만 주의할 점이 있다.

depends_on은 컨테이너가 "실행되었는지"만 확인하지, 그 안의 서비스가 "준비되었는지"는 확인하지 않는다. MySQL이 부팅되는 데 10-20초가 걸리는데, 그 사이에 애플리케이션이 먼저 실행되면 연결 오류가 발생할 수 있다.

이 문제를 해결하려면 애플리케이션 코드에 재시도 로직을 넣거나, wait-for-it.sh 같은 스크립트를 사용해야 한다. Spring Boot의 경우 spring.datasource.hikari.initialization-fail-timeout 설정을 -1로 하면 연결이 될 때까지 기다리게 할 수 있다.

서비스 이미지 크기 메모리 사용량 포트 데이터 영속성
MySQL 8.0 약 600MB 200-500MB 3306 볼륨 필요
Redis 7 약 30MB 10-50MB 6379 옵션
Spring Boot 빌드에 따라 200-500MB 8080 불필요

이 Compose 파일을 실행하려면 터미널에서 다음 명령어를 입력한다:

bash docker-compose up -d

-d 옵션은 백그라운드에서 실행하라는 의미다. 실행 후에는 docker-compose ps로 상태를 확인할 수 있다.

모든 컨테이너가 "Up" 상태로 표시되면 성공이다. 브라우저에서 http://localhost:8080에 접속해서 애플리케이션이 정상 동작하는지 확인한다.

만약 오류가 발생하면 docker-compose logs 명령어로 로그를 확인할 수 있다. 특정 서비스의 로그만 보고 싶다면 docker-compose logs app처럼 서비스 이름을 지정하면 된다.

여기서 중요한 점은 데이터 영속성이다. MySQL 컨테이너를 그냥 실행하면 컨테이너를 내릴 때 데이터가 모두 사라진다.

이를 방지하기 위해 volumes를 사용했다. mysql-data:/var/lib/mysql은 호스트의 mysql-data 볼륨을 컨테이너의 /var/lib/mysql 디렉토리에 마운트하라는 의미다.

이렇게 하면 컨테이너를 삭제해도 데이터는 유지된다. Docker Compose를 사용하면서 가장 많이 실수하는 부분이 바로 이 데이터 영속성이다.

개발 중인데 갑자기 DB를 초기화해야 하는 상황이 아니라면, 항상 볼륨을 사용하는 습관을 들이는 것이 좋다. 또 하나 팁을 주자면, docker-compose.yml 파일을 여러 개 만들어서 환경별로 관리할 수 있다.

예를 들어 docker-compose.dev.yml에는 개발용 설정(포트 매핑, 볼륨 마운트 등)을, docker-compose.prod.yml에는 프로덕션용 설정(이미지 태그, 환경 변수 등)을 나눠서 작성한다. 실행할 때는 -f 옵션으로 파일을 지정한다:

bash docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d

이 방식은 특히 팀 프로젝트에서 유용하다. 개발자는 개발용 설정을, CI/CD 파이프라인은 프로덕션 설정을 사용할 수 있기 때문이다.

다른 내용도 보러가기 #2

문제 해결과 최적화 팁

Docker를 사용하다 보면 다양한 문제에 부딪힌다. 이 섹션에서는 실제로 내가 겪었던 문제들과 그 해결 방법을 공유하려고 한다.

문제 1: "vmmem" 프로세스가 메모리를 너무 많이 먹는다

이 문제는 WSL2 사용자라면 누구나 한 번쯤 겪는다. WSL2는 기본적으로 호스트 시스템의 메모리를 무제한으로 사용할 수 있도록 설정되어 있다.

그래서 리눅스에서 메모리 캐시가 쌓이면 vmmem 프로세스가 점점 커진다. 앞서 언급한 .wslconfig 파일을 사용하는 것이 가장 효과적인 해결책이다.

여기에 추가로, 주기적으로 WSL을 재시작하는 습관을 들이는 것도 도움이 된다:

powershell wsl --shutdown

이 명령어는 WSL2를 완전히 종료시킨다. 그리고 다음에 WSL 명령어를 실행하거나 Docker Desktop을 사용할 때 자동으로 다시 시작된다.

문제 2: "no space left on device" 오류

Docker는 이미지와 컨테이너를 저장하는 데 디스크 공간을 많이 사용한다. 시간이 지나면 사용하지 않는 이미지와 컨테이너가 쌓여서 디스크가 가득 찰 수 있다.

해결 방법은 정기적으로 Docker를 정리하는 것이다:

bash docker system prune -a --volumes

이 명령어는 주의해서 사용해야 한다. 현재 실행 중인 컨테이너와 관련된 이미지는 제거되지 않지만, 그 외의 모든 것은 삭제된다.

나는 한 달에 한 번 정도 이 명령어를 실행한다. 보통 10-20GB의 디스크 공간을 확보할 수 있다.

문제 3: "port is already allocated" 오류

로컬에서 이미 MySQL을 실행 중인데, Docker로 또 MySQL을 띄우려고 하면 포트 충돌이 발생한다. 이 경우 두 가지 선택지가 있다:

  1. 로컬 MySQL을 중지하고 Docker MySQL을 사용한다
  2. Docker MySQL의 포트를 변경한다 (예: 3307)

두 번째 방법을 선택한다면, docker-compose.yml에서 포트 매핑을 변경하면 된다:

yaml ports: - "3307:3306"

이렇게 하면 호스트의 3307 포트가 컨테이너의 3306 포트로 연결된다. 애플리케이션에서는 localhost:3307로 접속하면 된다.

문제 증상 해결 방법 적용 시점
메모리 과다 사용 vmmem이 6GB+ .wslconfig 설정 WSL 재시작 후
디스크 부족 "no space left" 에러 docker system prune 주기적 실행
포트 충돌 "port allocated" 에러 포트 변경 또는 서비스 중지 즉시
권한 문제 "permission denied" 사용자 그룹에 docker 추가 재로그인 후
빌드 속도 저하 도커파일 빌드 느림 레이어 캐싱 최적화 Dockerfile 수정 시

문제 4: 권한 문제

리눅스 컨테이너 안에서 생성된 파일은 기본적으로 root 소유로 생성되는 경우가 있다. 이 경우 호스트에서 파일을 수정하려고 하면 권한 오류가 발생한다.

해결 방법은 컨테이너 실행 시 사용자 ID를 지정하는 것이다:

bash docker run -u $(id -u):$(id -g) -v $(pwd):/workspace my-image

Docker Compose에서는 user 항목으로 지정할 수 있다:

yaml services: app: user: "1000:1000"

여기서 1000은 대부분의 리눅스 첫 번째 사용자의 UID/GID다. 윈도우에서 WSL2를 사용하는 경우에도 기본 사용자의 UID는 1000이다.

최적화 팁: Dockerfile 레이어 캐싱

Dockerfile을 작성할 때 명령어 순서는 빌드 시간에 큰 영향을 미친다. Docker는 각 명령어(레이어)의 결과를 캐시한다.

자주 변경되는 부분을 나중에 배치하면, 변경이 있을 때마다 전체를 다시 빌드하지 않아도 된다. 나쁜 예:

dockerfile COPY . /app RUN pip install -r requirements.txt

좋은 예:

dockerfile COPY requirements.txt /app RUN pip install -r requirements.txt COPY . /app

좋은 예에서는 requirements.txt가 변경되지 않는 한 pip install 단계는 캐시를 사용한다. 소스 코드가 변경되어도 의존성 패키지를 다시 설치하지 않으므로 빌드 시간이 크게 단축된다.

실제로 이 최적화를 적용한 후, 내 프로젝트의 Docker 빌드 시간이 평균 5분에서 30초로 줄었다. 소스 코드만 변경했을 때는 5초면 충분했다.

마지막 팁: Docker Desktop의 리소스 제한

Docker Desktop 설정에서 CPU와 메모리 사용량을 제한할 수 있다. 개발용 노트북에서 Docker를 실행한다면, 메모리를 4GB로 제한하는 것을 추천한다.

너무 많이 할당하면 다른 애플리케이션이 느려지고, 너무 적게 할당하면 컨테이너 실행이 실패할 수 있다. 내 경험상, Spring Boot 애플리케이션 + MySQL + Redis를 동시에 실행하려면 최소 4GB의 메모리가 필요했다.

여유가 있다면 8GB를 할당하는 것이 안전하다. 이렇게 Docker로 개발 환경을 구축하고 나면, 이전처럼 "내 컴퓨터에서는 되는데"라는 말을 더 이상 할 필요가 없어진다.

모든 개발자가 동일한 환경에서 작업하고, 배포도 그 환경을 그대로 사용할 수 있다. 처음에는 설정이 번거롭게 느껴질 수 있다.

하지만 한 번 구축해두면 프로젝트를 추가할 때마다 그 효용성을 체감하게 된다. 나는 지금 새로운 프로젝트를 시작할 때마다 가장 먼저 Docker 환경부터 만든다.

그만큼 시간과 스트레스를 줄여주는 도구다.

관련 영상

같이 보면 좋은 글