[AWS] Windows에서 AWS EC2까지: Docker로 Python 서비스 배포하기
프로젝트를 진행하면서 프론트엔드(React)와 백엔드(Java)는 Docker 없이 직접 빌드하여 배포했다. 하지만 AI 기능을 담당하는 Python 백엔드는 의존성 관리와 배포 환경의 일관성을 위해 Docker를 활용하기로 결정했다. 이번 글에서는 Windows 환경에서 Docker를 설치하고, Python 애플리케이션을 Docker 이미지로 빌드한 후 Amazon EC2에 배포하는 전체 과정을 정리했다.
Docker란?
Docker는 애플리케이션을 개발, 배포, 실행하기 위한 오픈소스 플랫폼이다. Docker를 사용하면 애플리케이션과 그 의존성을 "컨테이너"라는 표준화된 유닛으로 패키징할 수 있다. 이 컨테이너는 개발 환경, 테스트 환경, 프로덕션 환경 등 어디서든 동일하게 실행될 수 있어 "내 컴퓨터에서는 잘 돌아가는데..."라는 상황을 방지할 수 있다.
위 그림은 Docker의 기본 워크플로우를 보여준다. 개발자의 로컬 컴퓨터에서 Dockerfile을 작성하고 이를 빌드하여 Docker 이미지를 생성한다. 이 이미지는 Docker Hub와 같은 레지스트리에 푸시되고, 클라우드 환경(AWS)에서 이미지를 풀(pull)한 후 컨테이너로 실행한다. 이 과정을 통해 개발 환경과 프로덕션 환경 사이의 일관성을 유지할 수 있다.
위 그림은 Docker 시스템의 구조를 더 자세히 보여준다. 왼쪽은 단일 컨테이너 실행을, 오른쪽은 하나의 이미지로부터 여러 컨테이너를 실행하는 확장성을 보여준다. Dockerfile로부터 이미지를 빌드하고, 이 이미지는 불변성을 가지며, 필요에 따라 여러 컨테이너 인스턴스를 실행할 수 있다. 이러한 구조는 마이크로서비스 아키텍처와 스케일링에 매우 적합하다.
1. Windows 기능 켜기/끄기 설정
1.1 가장 먼저 컴퓨터 검색창에 Windows 기능 켜기/끄기를 검색한다.
1.2 Hyper-V, Linux용 Windows 하위 시스템, Virtual Machine Platform을 체크하고 확인을 누른다. 그럼 컴퓨터가 바로 재부팅 된다.
2. Docker 실행을 위한 WSL2 설정
Docker Desktop for Windows는 WSL2(Windows Subsystem for Linux)를 기반으로 실행된다. 따라서 먼저 WSL2를 설치하고 설정해야 한다.
# WSL 기본 버전을 2로 설정
wsl --set-default-version 2
# WSL 업데이트
wsl --update
# 다시 한번 기본 버전이 2로 설정되었는지 확인
wsl --set-default-version 2
WSL2 설치 후에는 Microsoft Store에서 Ubuntu를 설치했다. 이는 Linux 환경을 Windows에서 사용할 수 있게 해주는 배포판이다.
3. Docker Desktop 설치
3.1 Windows용 Docker Desktop을 Docker 공식 웹사이트에서 다운로드하여 자기 사양에 맞게 설치한다.
3.2 설치 과정에서 WSL2 통합 기능을 활성화하여 WSL2 기반으로 Docker가 작동하도록 설정한다.
4. Dockerfile 작성
AI 백엔드를 위한 Dockerfile을 프로젝트 루트 디렉토리에 생성했다. 이 파일은 컨테이너 이미지를 어떻게 구성할지 정의한다.
# Python 3.12 베이스 이미지 사용
FROM python:3.12-slim
# 작업 디렉토리 설정
WORKDIR /app
# 의존성 파일 복사 및 설치
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 애플리케이션 코드 복사
COPY . .
# 포트 노출 (애플리케이션이 사용하는 포트로 변경하세요)
EXPOSE 8000
# 애플리케이션 실행 명령
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
이 Dockerfile은 다음과 같은 역할을 한다.
- Python 3.12 슬림 버전 이미지를 기반으로 사용
- 작업 디렉토리를 /app으로 설정
- requirements.txt 파일을 복사하고 필요한 패키지 설치
- 애플리케이션 코드를 컨테이너로 복사
- 8000번 포트를 외부에 노출
- 애플리케이션 실행 명령 지정 (uvicorn을 사용해 FastAPI 애플리케이션 실행)
5. Docker 이미지 빌드 및 배포
5.1 로컬에서 Docker 이미지 빌드
먼저 Docker Desktop을 실행하고, 로컬(CMD)에서 Dockerfile이 있는 프로젝트 경로로 이동한 후 파이썬 애플리케이션의 Docker 이미지를 빌드한다.
# Docker 이미지 빌드
# -t 옵션으로 이미지 이름 지정, . 은 현재 디렉토리의 Dockerfile을 사용한다는 의미
docker build -t ai-backend .
이미지 빌드가 완료되면, 이 이미지를 Docker Hub에 업로드하기 위해 태그를 지정하고 푸시한다. 이렇게 하면 EC2와 같은 다른 환경에서도 이미지를 가져와 사용할 수 있다.
# 이미지에 태그 지정 (Docker Hub 계정명/이미지명:태그)
# Docker Hub에 푸시하기 위해 계정명을 포함한 태그 지정
docker tag ai-backend hwng/ai-backend:latest
# Docker Hub에 로그인
# 계정 인증 정보를 입력해 Docker Hub에 로그인
docker login
# 이미지 푸시
# 태그된 이미지를 Docker Hub에 업로드
docker push hwng/ai-backend:latest
위 과정을 통해 Docker Hub에 업로드했다. 이후 EC2 인스턴스에서 이 이미지를 가져와 실행할 수 있다.
5.2 기존 컨테이너 정리 (EC2 서버에서) - 필수사항
이미 EC2에 동일한 이름의 컨테이너가 실행 중인 경우, 새로운 버전을 같은 이름으로 배포하기 전에 반드시 기존 컨테이너를 정리해야 한다. Docker는 동일한 이름의 컨테이너가 이미 존재할 경우 새 컨테이너를 실행할 수 없기 때문이다. 나는 이전에 동일한 이름으로 배포했던 컨테이너가 있어 다음 과정을 진행했다.
# 실행 중인 컨테이너 확인
# 현재 실행 중인 모든 컨테이너 목록 표시
docker ps
# 컨테이너 중지
# 실행 중인 컨테이너를 안전하게 중지
docker stop ai-backend-container
# 컨테이너 삭제
# 중지된 컨테이너 삭제
docker rm ai-backend-container
# (선택사항) 기존 이미지 삭제 - 디스크 공간 확보를 위해
# 이전 버전 이미지 삭제로 디스크 공간 확보
docker rmi hwng/ai-backend:latest
모든 명령이 성공적으로 완료되었는지 확인하기 위해 다음 명령어로 확인했다:
# 모든 컨테이너 목록 확인 (중지된 것 포함)
docker ps -a
# 이미지 목록 확인
docker images
5.3 EC2에 Docker 설치 및 이미지 배포
5.3.1 Docker 설치 (최초 1회만 실행)
EC2 인스턴스에서 다음 명령어를 실행하여 Docker를 설치하고 이미지를 배포했다. Docker 설치는 EC2 인스턴스에 처음 한 번만 수행하면 된다.
# 패키지 목록 업데이트
sudo apt update
# Docker 설치
sudo apt install docker.io -y
# Docker 서비스 시작
sudo systemctl start docker
# 부팅 시 Docker 자동 시작 설정
sudo systemctl enable docker
# 현재 사용자를 docker 그룹에 추가 (sudo 없이 docker 명령어 실행 가능)
sudo usermod -aG docker ubuntu
# (마지막 명령어 실행 후 SSH 연결을 끊고 다시 접속해야 함)
5.3.2 Docker 이미지 배포 및 실행
Docker가 설치된 EC2 인스턴스에서 다음 명령어를 실행하여 이미지를 가져오고 컨테이너를 실행한다.
# Docker Hub에서 이미지 가져오기
docker pull hwng/ai-backend:latest
# 컨테이너 실행(메모리 제한 설정)
# -d: 백그라운드 실행
# -p 8000:8000: 호스트의 8000 포트를 컨테이너의 8000 포트에 매핑
# --name: 컨테이너 이름 지정
# --memory, --memory-swap: 메모리 사용량 제한
# --restart=on-failure: 오류 발생 시 자동 재시작
docker run -d -p 8000:8000 --name ai-backend-container \
--memory="256m" --memory-swap="512m" \
--restart=on-failure \
hwng/ai-backend:latest
# 컨테이너 실행 확인
# 실행 중인 컨테이너 목록 표시
docker ps
# 로그 확인
# 컨테이너의 로그 출력 확인
docker logs ai-backend-container
이렇게 해서 파이썬 애플리케이션이 EC2 인스턴스에서 Docker 컨테이너로 실행되었다.
마무리
Docker를 활용하여 AI 백엔드를 배포함으로써 몇 가지 중요한 이점을 얻을 수 있었다.
- 환경 일관성: 로컬 개발 환경과 프로덕션 환경 간의 차이로 인한 문제를 최소화했다.
- 의존성 관리: Python 패키지와 그 의존성을 컨테이너 내부에 격리하여 관리할 수 있게 되었다.
- 배포 간소화: 새 버전 배포 시 이미지만 교체하면 되므로 배포 프로세스가 단순해졌다.
- 자원 제한: 컨테이너에 메모리 제한을 설정하여 전체 시스템의 안정성을 높였다.
앞으로는 CI/CD 파이프라인을 구축하여 코드 변경 시 자동으로 Docker 이미지를 빌드하고 배포하는 방식으로 개선할 계획이다. Docker를 활용한 배포 방식은 처음에는 설정이 다소 복잡할 수 있지만, 한번 구축해 놓으면 일관된 환경에서 애플리케이션을 쉽게 배포하고 관리할 수 있다는 장점이 있는것 같다.