개발 공부중

[TIL] 프로젝트에 Docker 적용하기 본문

카테고리 없음

[TIL] 프로젝트에 Docker 적용하기

개발자 leelee 2026. 9. 23. 00:14

 

안티그래비티로 작업하면서, 다른 PC에서도 이어서 작업할 수 있는 방법이 궁금해졌다.

프로젝트 코드를 옮기는 것은 어렵지 않지만, Python과 라이브러리까지 다시 설치하고 실행 환경을 맞추는 과정이 번거로울 것 같았다. 그때 알게 된 도구가 Docker였다.

 

 


1. Docker를 쓰면 무엇이 달라질까?

Docker는 프로그램과 실행에 필요한 환경을 이미지로 구성하고, 이를 컨테이너라는 독립된 공간에서 실행하는 도구다.

FastAPI 프로젝트라면 Python, 필요한 라이브러리, 소스코드 등을 이미지에 담을 수 있다.

처음 접할 때는 아래 세 가지를 구분하면 이해하기 쉽다.

Dockerfile 실행 환경을 만드는 설정 파일 조리법
이미지 프로그램 실행에 필요한 파일과 환경을 담은 패키지 준비된 밀키트
컨테이너 이미지를 바탕으로 만들어진 실행 공간 실제로 요리하는 공간

 

기존에는 다른 PC에서 프로젝트를 실행하려면 Python과 패키지 관리자를 설치하고 환경을 맞춰야 했다.

Docker 설정을 준비해두면, 다른 PC에서는 Docker를 통해 이 환경을 구성할 수 있다. 프로젝트 실행을 위해 PC에 Python과 uv를 별도로 설치할 필요가 줄어드는 것이다.

다만 Docker가 모든 환경 차이를 없애주는 것은 아니다. PC의 CPU 구조, 네트워크, 환경변수 등에 따라 추가 확인이 필요할 수 있고, 첫 실행에는 이미지와 패키지를 내려받는 시간도 걸린다.


2. 주소가 localhost:8000으로 같은데 Docker가 맞을까?

처음 가장 헷갈렸던 부분이다.

Docker를 사용해도 브라우저 접속 주소는 기존과 같은 http://localhost:8000이었다. 그렇다면 무엇이 달라진 걸까?

주소는 같지만, 서버가 실행되는 공간이 달라졌다.

실행 방식FastAPI가 실행되는 위치

PC에서 직접 실행 내 PC에 준비한 Python 환경
Docker로 실행 컨테이너 안의 Python 환경

Docker에서는 다음과 같은 포트 설정을 사용한다.

ports:
  - "8000:8000"

앞의 숫자는 내 PC의 포트, 뒤의 숫자는 컨테이너 안의 포트다.

브라우저에서 내 PC의 8000번 포트로 접속하면, Docker가 컨테이너의 8000번 포트로 요청을 전달한다. 그래서 서버가 컨테이너 안에 있어도 기존 주소로 접속할 수 있다.

만약 다음처럼 설정하면:

ports:
  - "9000:8000"

브라우저 접속 주소는 http://localhost:9000이 된다. 컨테이너 안의 FastAPI는 여전히 8000번 포트를 사용한다.

기존에 직접 실행한 서버가 PC의 8000번 포트를 사용 중이라면 Docker와 충돌할 수 있다. 기존 서버를 종료하거나 앞쪽 포트 번호를 변경해야 한다.


3-1. Windows 설치 중 만난 첫 번째 오류: 가상화 기능

Docker Desktop을 설치한 뒤 다음 오류가 나타났다.

Virtualization support not detected

가상화 기능을 사용할 수 없어 Docker Desktop이 시작되지 않는다는 뜻이다.

먼저 확인할 것: CPU 가상화 상태

Windows에서 다음 순서로 확인한다.

  1. Ctrl + Shift + Esc로 작업 관리자를 연다.
  2. 성능 → CPU로 이동한다.
  3. 가상화 항목이 사용 상태인지 확인한다.

비활성화되어 있다면 BIOS/UEFI에서 가상화 기능을 켜야 할 수 있다. 설정 이름과 진입 방법은 제조사마다 다르다.

나의 경우,

재부팅 후에도 오류가 계속되어, Windows의 가상 머신 플랫폼과 WSL 기능을 활성화하는 과정을 진행했다.

관리자 권한으로 PowerShell을 열고 다음 명령어를 실행한다.

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

명령이 완료되면 PC를 다시 시작한다.

이 명령은 Windows 기능을 활성화하는 명령이다. BIOS/UEFI의 CPU 가상화 설정까지 켜주는 것은 아니므로 두 항목을 구분해야 한다.


3-2. 두 번째 오류: WSL 업데이트 필요

다음으로 나타난 메시지는 다음과 같았다.

WSL needs updating

Docker가 사용하는 WSL의 업데이트가 필요하다는 안내였다.

터미널에서 다음 명령을 실행했다.

wsl --update

업데이트 후 Docker Desktop을 다시 실행해 상태를 확인했다.

설치 여부와 엔진 연결 상태를 확인하는 명령도 구분해두면 좋다.

docker --version

위 명령은 Docker 명령줄 도구의 버전을 확인한다.

docker version

이 명령으로 Client와 Server 정보가 정상적으로 표시되는지 확인하면, Docker 엔진과 통신하는지도 확인할 수 있다.

버전이 출력되는 것만으로 컨테이너를 실행할 준비가 끝났다고 단정하지 않는 것이 중요하다.


4. 프로젝트에 Docker 설정 파일 준비하기

Docker 실행 준비가 끝난 뒤 프로젝트에 다음 파일 세 개를 추가했다.

.dockerignore 이미지 빌드에 불필요한 파일 제외
Dockerfile Python 환경과 의존성, 실행 방법 정의
docker-compose.yml 포트, 환경변수, 소스 연결 등을 한곳에서 관리

아래 내용은 Python 3.12, uv, app/main.py, static 폴더를 사용하는 구조를 기준으로 한 설명용 예시다. 실제 프로젝트의 폴더 구조와 의존성 설정에 맞춰 조정해야 한다.

① .dockerignore

로컬 가상환경이나 비밀정보 파일이 빌드에 포함되지 않도록 제외한다.

.venv
__pycache__
*.pyc
.git
.pytest_cache
.env

여기서 .dockerignore와 .gitignore는 역할이 다르다.

  • .dockerignore: Docker 빌드에 전달할 파일을 제한
  • .gitignore: Git에서 새로 추적할 파일을 제한

.env는 두 곳에서 각각 관리해야 한다. 이미 Git이 추적 중인 파일은 .gitignore에 추가하는 것만으로 추적이 해제되지 않는다.

② Dockerfile

FROM python:3.12-slim

COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv

WORKDIR /app

COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-install-project

COPY app ./app
COPY static ./static

EXPOSE 8000

CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

주요 설정의 의미는 다음과 같다.

설정의미

FROM 기반으로 사용할 Python 이미지
WORKDIR /app 컨테이너 안의 작업 폴더
uv sync 프로젝트에 필요한 의존성 설치
COPY app ./app 소스코드를 이미지에 복사
EXPOSE 8000 앱이 사용할 포트를 명시
CMD 컨테이너가 시작될 때 실행할 기본 명령

EXPOSE만으로 PC의 포트가 연결되는 것은 아니다. 실제 포트 연결은 Compose의 ports에서 설정한다.

또한 --no-install-project는 프로젝트 자체의 설치를 건너뛰지만, 뒤의 uv run은 기본적으로 환경 동기화를 수행한다. 프로젝트 패키징 설정에 따라 추가 파일이나 설치 단계가 필요할 수 있다.

재현성을 더 높이려면 uv:latest 대신 검증한 버전이나 이미지 다이제스트로 고정할 수 있다.

③ docker-compose.yml

개발하면서 수정한 소스를 확인할 수 있도록 폴더 연결과 --reload를 설정한다.

services:
  bookmate:
    build: .
    container_name: bookmate-app
    ports:
      - "8000:8000"
    env_file:
      - .env
    volumes:
      - ./app:/app/app
      - ./static:/app/static
    command: ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
    restart: unless-stopped
  • build: .: 현재 폴더의 Dockerfile로 이미지를 만든다.
  • ports: PC와 컨테이너의 포트를 연결한다.
  • env_file: .env의 값을 컨테이너 환경변수로 전달한다.
  • volumes: PC의 소스 폴더를 컨테이너에 연결한다.
  • command: Dockerfile의 기본 실행 명령을 대신한다.

이 설정은 로컬 개발용이다. 실제 운영 배포에서는 --reload, 소스 폴더 연결, 비밀정보 관리 등을 별도로 검토해야 한다.


5. Docker로 서버 실행하기

docker-compose.yml이 있는 프로젝트 폴더에서 실행한다.

docker compose up --build -d

각 옵션의 의미는 다음과 같다.

  • up: 필요한 컨테이너를 생성하고 실행
  • --build: 실행 전에 이미지 빌드
  • -d: 백그라운드 실행

첫 실행에는 기반 이미지와 패키지를 내려받아야 하므로 시간이 걸릴 수 있다.

실행 상태는 다음 명령으로 확인한다.

docker compose ps

오류가 있다면 로그를 확인한다.

docker compose logs --tail=100 bookmate

컨테이너가 실행 중인지 확인하는 것과 웹페이지가 정상 응답하는지 확인하는 것은 별개다. 마지막에는 브라우저에서도 접속해본다.


6. 실제로 헷갈렸던 접속 주소: 0.0.0.0

서버를 실행한 뒤 로그에 표시된 주소를 보고 다음 주소로 접속했다.

http://0.0.0.0:8000

하지만 접속되지 않았다.

0.0.0.0은 서버가 컨테이너 안의 모든 IPv4 네트워크 인터페이스에서 요청을 받도록 지정하는 수신 주소다. 브라우저 접속 주소로 사용하도록 안내하는 값이 아니다.

내 PC에서 접속할 때는 다음 주소를 사용한다.

http://localhost:8000

또는:

http://127.0.0.1:8000

정리하면 다음과 같다.

주소사용 목적

0.0.0.0 서버 실행 시 수신 범위 지정
localhost / 127.0.0.1 현재 PC에서 서버 접속
서버 PC의 실제 IP 다른 기기에서 서버 접속

7. 다른 PC에서도 실행하려면?

여기까지는 내 PC에서 Docker를 설정하고 실행하는 과정이다. 다음은 다른 PC에서도 실행하기 위한 준비 방법이다.

기존 PC에서의 준비사항

프로젝트 코드와 Docker 설정 파일을 GitHub에 올린다. 실제 API 키나 DB 접속 정보가 들어 있는 .env는 제외한다.

먼저 변경 파일을 확인한다.

git status

Docker 설정 파일 세 개만 추가하려면 다음처럼 지정할 수 있다.

git add .dockerignore Dockerfile docker-compose.yml

커밋에 포함될 파일을 확인한다.

git diff --cached --name-only

문제가 없다면 커밋한다.

git commit -m "feat: add Docker configuration"

이미 원격 추적 브랜치가 설정되어 있다면 다음 명령으로 올린다.

git push

브랜치 이름을 확인하지 않고 main이나 master로 임의 지정하지 않는 편이 좋다.

새로운 PC에서 준비할 것

  1. Docker Desktop을 설치하고 실행한다.
  2. 프로젝트 코드를 내려받는다.
  3. 프로젝트 폴더에 .env를 준비한다.
  4. Compose 명령으로 서버를 실행한다.

Git이 설치되어 있다면 저장소를 복제할 수 있다.

git clone <저장소_URL>
cd <프로젝트_폴더>

Git을 사용하지 않는다면 프로젝트 ZIP을 내려받아 압축을 풀어도 된다.

환경변수까지 준비한 뒤 실행한다.

docker compose up --build -d

새 PC의 브라우저에서 접속한다.

http://localhost:8000

이때 만들어지는 것은 새 PC에서 실행되는 새로운 컨테이너다. 원래 PC의 컨테이너에 원격 접속하는 방식이 아니다.

두 PC의 .env가 같은 외부 DB를 가리키면 데이터도 같은 DB에 저장된다. 실행 환경을 새로 만든다고 DB까지 별도로 복제되는 것은 아니다.


8. 개발하면서 자주 사용할 명령어

목적명령어

서버 실행 docker compose up -d
이미지 빌드 후 실행 docker compose up --build -d
실행 상태 확인 docker compose ps
로그 실시간 확인 docker compose logs -f bookmate
컨테이너 중지 docker compose stop
컨테이너와 기본 네트워크 제거 docker compose down

소스 폴더 연결과 자동 재시작이 설정되어 있다면 일반적인 Python 코드 수정마다 이미지를 다시 만들 필요는 없다.

반면 Dockerfile이나 의존성 파일을 변경했다면 이미지를 다시 빌드해야 할 수 있다.

docker compose down을 실행해도 프로젝트 코드와 외부 DB가 삭제되는 것은 아니다. 다만 컨테이너 내부에만 저장한 파일은 컨테이너 제거 시 사라질 수 있으므로, 보존할 데이터는 별도 저장 구성을 해야 한다.

 

Comments