Docker로 Python+Chrome+SeleniumBase 환경 구축 및 배포하기

한빈수윤·2025년 4월 2일

파이프라인

목록 보기
1/3

이미지 빌드, 로컬 테스트, 소스코드 수정 및 재빌드까지

이번 포스트에서는 Docker를 이용하여 Python 환경에 Chrome과 SeleniumBase를 포함하는 이미지를 구축하는 방법을 단계별로 설명합니다. 이 환경은 이후 Cloud Run과 Cloud Tasks를 활용해 대량 크롤링 작업을 분산 실행할 때도 유용하게 사용할 수 있습니다.


1. 프로젝트 폴더 준비 및 파일 구성

프로젝트 폴더 생성
먼저 로컬에 새 폴더(예: my-selenium-app)를 생성합니다.
VSCode를 실행하고 File > Open Folder...를 선택하여 이 폴더를 엽니다.

필수 파일 구성
프로젝트 폴더 내에 아래와 같은 파일들을 생성합니다:

my-selenium-app/
├── Dockerfile
├── requirements.txt    (선택사항: 추가 Python 패키지 목록)
└── test_search.py      (예제 테스트 소스 코드)

2. Dockerfile 작성하기 (멀티스테이지 빌드)

멀티스테이지 빌드를 사용하면 변경 가능성이 낮은 기본 환경(Python+Chrome)과, 자주 바뀌는 소스 코드(예: 크롤링 스크립트)를 분리할 수 있어 빌드 캐시를 효율적으로 사용할 수 있습니다.

VSCode에서 Dockerfile 파일을 열고 아래 내용을 입력하세요:

[dockerfile]

# Stage 1: Base - Python 3.11-slim과 Chrome을 설치 (변경 가능성이 낮은 기본 환경)
FROM python:3.11-slim as base

# 시스템 필수 패키지 설치 (wget, gnupg, ca-certificates)
RUN apt-get update && apt-get install -y --no-install-recommends \
    wget \
    gnupg \
    gnupg1 \
    gnupg2 \
    ca-certificates && rm -rf /var/lib/apt/lists/*

# 구글 크롬 설치 (공식 키와 저장소 추가)
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list \
    && apt-get update && apt-get install -y --no-install-recommends google-chrome-stable && rm -rf /var/lib/apt/lists/*

# 크롬 실행에 필요한 라이브러리 설치
RUN apt-get update && apt-get install -y --no-install-recommends \
    libnss3 \
    libgconf-2-4 \
    libappindicator3-1 \
    fonts-liberation && rm -rf /var/lib/apt/lists/*

# Stage 2: Dependencies - pip 종속성 설치 (SeleniumBase 등)
FROM base as deps
WORKDIR /app
# (옵션) requirements.txt를 사용할 경우, 아래 두 줄 주석 해제
# COPY requirements.txt .
# RUN pip install --upgrade pip && pip install -r requirements.txt
# 여기서는 SeleniumBase를 직접 설치
RUN pip install --upgrade pip && pip install seleniumbase

# Stage 3: Application - 자주 변경되는 소스 코드 복사
FROM deps as final
WORKDIR /app
COPY . .
EXPOSE 8080
# CMD를 환경변수 PORT를 사용하여 Python 내장 HTTP 서버를 실행하도록 함
CMD ["sh", "-c", "python -m http.server ${PORT:-8080}"]

참고:

  • CMD는 테스트용으로 Python 내장 HTTP 서버를 실행합니다.

  • 나중에 실제 크롤링 또는 웹 애플리케이션 실행 시, CMD를 해당 실행 명령어로 변경하면 됩니다.

3. 예제 테스트 코드 작성하기

프로젝트 폴더 내에 test_search.py 파일을 생성하고 아래 코드를 붙여넣습니다. 이 코드는 50개의 검색어를 10개씩 배치로 나눠 구글 검색을 실행하는 예제입니다.

import time
from seleniumbase import SB
from selenium.webdriver.common.keys import Keys

def search_keyword(keyword):
    """단일 검색어로 구글 검색 후 결과 페이지 제목을 반환"""
    with SB(uc=True, test=True, locale="ko") as sb:
        sb.open("https://www.google.com")
        sb.wait_for_element("input[name='q']", timeout=10)
        sb.type("input[name='q']", keyword)
        sb.send_keys("input[name='q']", Keys.ENTER)
        sb.wait_for_element("h3", timeout=10)
        title = sb.find_element("title").text
    return {"keyword": keyword, "title": title}

def run_batch(batch):
    """한 배치의 검색어들을 순차 실행"""
    batch_results = []
    for keyword in batch:
        print(f"** 검색 실행: {keyword}")
        result = search_keyword(keyword)
        batch_results.append(result)
        time.sleep(1)  # 각 검색 사이 1초 딜레이
    return batch_results

def main():
    # 예시 50개의 검색어 목록 (원하는 검색어로 수정 가능)
    keywords = [
        "세탁기", "쿠쿠", "쿠쿠전자", "LG전자", "삼성", "다이슨", "엘지", "현대", "기타", "전자",
        "컴퓨터", "휴대폰", "카메라", "음향기기", "스마트워치", "스피커", "프린터", "노트북", "태블릿", "TV",
        "가전", "모니터", "마우스", "키보드", "스캐너", "드론", "로봇", "게임콘솔", "오디오", "빔프로젝터",
        "냉장고", "세탁기2", "에어컨", "청소기", "전자렌지", "식기세척기", "커피머신", "전기밥솥", "헤어드라이기", "전기면도기",
        "비데", "공기청정기", "로봇청소기", "스팀청소기", "와인셀러", "전자책", "블루투스", "스마트홈", "네스트", "AI가전"
    ]
    
    # 10개씩 배치로 나누기
    batch_size = 10
    batches = [keywords[i:i+batch_size] for i in range(0, len(keywords), batch_size)]
    
    all_results = []
    for idx, batch in enumerate(batches, start=1):
        print(f"\n=== 배치 {idx} 실행 중 ===")
        batch_results = run_batch(batch)
        all_results.extend(batch_results)
        time.sleep(5)  # 배치 간 5초 딜레이
    
    print("\n전체 검색 결과:")
    for res in all_results:
        print(res)

if __name__ == "__main__":
    main()

설명:

  • 이 코드는 로컬에서 50개의 검색어를 10개씩 나눠서 실행합니다.

  • 각 검색어별로 구글 검색 결과 페이지의 제목을 추출해 출력합니다.

4. Docker 이미지 빌드하기

프로젝트 폴더(my-selenium-app)에서 터미널(또는 VSCode 터미널)을 열고 아래 명령어를 실행합니다:

docker build --platform linux/amd64 -t my-seleniumbase-image .
  • 빌드가 완료되면 my-seleniumbase-image라는 이름의 Docker 이미지가 생성됩니다.

5. 로컬에서 Docker 컨테이너 실행 및 테스트

이미지가 정상적으로 빌드되었는지 확인하려면 아래 명령어로 컨테이너를 실행합니다:

docker run --rm -e PORT=8080 -p 8080:8080 my-seleniumbase-image
  • 이 명령은 컨테이너 내부에서 CMD로 설정한 python -m http.server ${PORT:-8080} 명령을 실행합니다.

  • 브라우저에서 http://localhost:8080에 접속하여 Python HTTP 서버가 정상 실행되는지 확인할 수 있습니다.

  • 테스트 코드 실행 확인:
    만약 CMD를 "python", "test_search.py"로 변경했다면, 테스트 코드가 실행되어 각 검색어에 대한 로그와 결과가 터미널에 출력되어야 합니다.

6. 소스 코드 수정 및 재빌드

소스 코드 수정:
VSCode에서 test_search.py 파일이나 다른 소스 코드를 수정합니다.
(이 단계는 자주 변경되는 부분이며, 기본 환경은 변경되지 않으므로 캐시가 활용되어 빌드 시간이 단축됩니다.)

이미지 재빌드:
수정 후 다시 아래 명령어로 이미지를 빌드합니다:

docker build --platform linux/amd64 -t my-seleniumbase-image .

컨테이너 재실행:

docker run --rm -e PORT=8080 -p 8080:8080 my-seleniumbase-image

변경된 소스 코드가 반영되어 테스트가 실행되는지 확인합니다.

7. Cloud Run 및 Cloud Tasks로 확장 (추후)

Cloud Run 배포:
위 단계까지 로컬 테스트가 완료되면, 이미지를 Container Registry(GCR)에 Push하고 Cloud Run에 배포할 수 있습니다.

Cloud Tasks 분산 실행:
Cloud Tasks를 사용해 4500개 작업(예: 45개씩 100번)을 분산 실행하도록 Python 스크립트를 작성하여 Cloud Run 서비스의 엔드포인트를 호출할 수 있습니다.


추가)

실제로 로컬에서 나눠서 돌리면 이렇게 나온다!

profile
버거운 컴공 적응기>**<^*^##

0개의 댓글