Docker — 어디서나 똑같이 실행하기¶
"내 컴퓨터에서는 되는데요?"¶
개발하면서 자주 겪는 상황입니다.
개발자 A 컴퓨터: Python 3.11, bcrypt 4.0 → 잘 됨
개발자 B 컴퓨터: Python 3.9, bcrypt 3.2 → 오류
배포 서버: Python 3.10, 패키지 없음 → 실행 안 됨
Docker는 이 문제를 해결합니다.
Docker 컨테이너: OS, Python 버전, 패키지 전부 포함
→ 어느 컴퓨터에서든 완전히 동일한 환경으로 실행
Docker 핵심 개념¶
이미지 (Image)¶
실행 환경을 담은 읽기 전용 설계도입니다.
이미지: python:3.11-slim + fastapi + uvicorn + 소스코드
컨테이너 (Container)¶
이미지를 실제로 실행한 인스턴스입니다.
이미지 컨테이너
설계도 → 건물
클래스 → 객체 (인스턴스)
같은 이미지로 여러 컨테이너를 실행할 수 있습니다.
Dockerfile¶
이미지를 만드는 명령 목록입니다.
Dockerfile 작성¶
# Dockerfile
# 1. 베이스 이미지 선택 (Python 3.11, 용량 작은 slim 버전)
FROM python:3.11-slim
# 2. 작업 디렉토리 설정
WORKDIR /app
# 3. 의존성 먼저 복사 (캐시 활용)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 4. 소스코드 복사
COPY . .
# 5. 포트 노출 (문서 목적)
EXPOSE 8000
# 6. 실행 명령
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
requirements.txt를 먼저 복사하는 이유:
소스코드만 바뀔 때 패키지 설치 단계를 캐시에서 재사용할 수 있습니다.
이미지 빌드 및 실행¶
# 이미지 빌드
docker build -t myapp .
# -t: 이미지 이름 지정
# .: Dockerfile이 있는 디렉토리
# 컨테이너 실행
docker run -p 8000:8000 myapp
# -p 호스트포트:컨테이너포트
# 백그라운드 실행
docker run -d -p 8000:8000 --name myapp-container myapp
# 실행 중인 컨테이너 목록
docker ps
# 컨테이너 중지
docker stop myapp-container
# 로그 확인
docker logs myapp-container
docker logs -f myapp-container # 실시간 스트리밍
환경 변수 전달¶
# 실행 시 환경 변수 전달
docker run -p 8000:8000 \
-e SECRET_KEY=mysecretkey \
-e DATABASE_URL=sqlite:///app.db \
myapp
# .env 파일로 전달
docker run -p 8000:8000 --env-file .env myapp
Docker Compose — 여러 컨테이너 관리¶
백엔드 서버 + 데이터베이스를 함께 실행할 때 유용합니다.
# docker-compose.yml
version: "3.9"
services:
api:
build: .
ports:
- "8000:8000"
environment:
- SECRET_KEY=${SECRET_KEY}
- DATABASE_URL=postgresql://postgres:password@db:5432/appdb
depends_on:
- db
volumes:
- .:/app # 개발 시 코드 변경 즉시 반영
db:
image: postgres:15
environment:
- POSTGRES_DB=appdb
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data # 데이터 영속성
volumes:
postgres_data:
# 모든 서비스 시작
docker compose up
# 백그라운드 실행
docker compose up -d
# 중지
docker compose down
# 로그 확인
docker compose logs api
.dockerignore¶
불필요한 파일이 이미지에 포함되지 않도록 합니다.
# .dockerignore
.env
*.db
__pycache__/
.git/
*.pyc
node_modules/
이미지 크기 최적화¶
# 좋은 예: slim 베이스 이미지 + 불필요한 파일 제외
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY main.py database.py auth.py ./
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
# 이미지 크기 확인
docker images myapp
Docker Hub — 이미지 공유¶
# Docker Hub에 로그인
docker login
# 이미지 태그 지정
docker tag myapp username/myapp:latest
# 업로드
docker push username/myapp:latest
# 다른 곳에서 받기
docker pull username/myapp:latest
클라우드 서비스(Railway, Render 등)에 이미지를 직접 배포할 때 사용합니다.
개발 환경에서 Docker 활용¶
# docker-compose.dev.yml — 개발 전용
services:
api:
build: .
ports:
- "8000:8000"
volumes:
- .:/app # 코드 변경이 컨테이너에 즉시 반영
command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload
env_file:
- .env
db:
image: postgres:15
ports:
- "5432:5432" # 로컬에서 DB 직접 접근 가능
environment:
- POSTGRES_DB=appdb
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
docker compose -f docker-compose.dev.yml up
실습 미션¶
미션 1: Dockerfile 작성¶
기존 FastAPI 프로젝트에 Dockerfile을 만들고:
1. docker build -t myapp . 로 이미지를 빌드하세요.
2. docker run -p 8000:8000 myapp 으로 실행하세요.
3. http://localhost:8000/docs 에 접속해 확인하세요.
미션 2: 환경 변수 전달¶
1. SECRET_KEY를 Dockerfile에 하드코딩하지 않고,
실행 시 -e 옵션으로 전달하세요.
2. SECRET_KEY 없이 실행하면 서버가 오류를 내는지 확인하세요.
미션 3: Docker Compose¶
docker-compose.yml을 작성해:
1. api 서비스와 postgres 서비스를 함께 실행하세요.
2. docker compose up 하나로 전체 환경이 시작되는지 확인하세요.
3. docker compose down 후 재시작해도 DB 데이터가 유지되는지 확인하세요.
미션 4 (심화): 멀티 스테이지 빌드¶
Dockerfile을 멀티 스테이지로 개선하세요:
- 빌드 단계: 의존성 설치
- 실행 단계: 최소한의 파일만 포함
이미지 크기가 줄어드는지 확인하세요.
핵심 요약¶
| 개념 | 설명 |
|---|---|
| 이미지 | 실행 환경을 담은 읽기 전용 설계도 |
| 컨테이너 | 이미지를 실행한 인스턴스 |
| Dockerfile | 이미지를 만드는 명령 목록 |
-p 8000:8000 |
호스트:컨테이너 포트 매핑 |
| Docker Compose | 여러 컨테이너를 함께 정의하고 실행 |
volumes |
컨테이너와 호스트 간 파일 공유/영속화 |
.dockerignore |
이미지에서 제외할 파일 목록 |
Docker는 "실행 환경 자체를 코드로 관리"하는 도구입니다.
팀 전원이 동일한 환경에서 개발하고 배포할 수 있습니다.