[Docker] docker로 puppeteer 크롤링 프로젝트 배포시 오류 해결하기

sm·2023년 3월 11일
2

AWS 서버에 puppeteer 사용한 프로젝트 배포하기

드디어,, 주말에 끝내고 말겠다는 집념으로 무사 배포에 성공했다.
결론적으로 http라서 배포에 헤맸던 것은 아니었다. 결론적으로 도커파일과 크롤링해오는 service.ts파일을 수정해주었더니 정말 기적적으로 배포에 성공했다.
정말 이거 성공하려고 1주일은 고생했던 것 같다.
결론적으로 dockerfile은 이렇게 설정해주었다.
일단 중요한 점은 puppeteer를 서버에서 실행해주려면 chromium과 필요한 패키지들을 설치해주어야 하는 것.

무튼 첫 도커 프로젝트 배포에 chatGPT의 도움도 많이 받았다.
고마워 챗GPT...


FROM node:16-alpine  # Node.js 16과 alpine Linux를 기반으로 하는 이미지 사용

RUN apk add --no-cache chromium nss freetype harfbuzz ca-certificates ttf-freefont udev xvfb x11vnc fluxbox dbus  # puppeteer 실행을 위해 필요한 패키지들을 설치

RUN apk add --no-cache --virtual .build-deps curl \
    && echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \
    && echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
    && echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
    && apk add --no-cache curl wget \
    && apk del .build-deps  # puppeteer 다운로드를 위해 필요한 라이브러리들을 설치하고 마지막에는 빌드를 위해 추가적으로 설치한 패키지들을 삭제

ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser  # puppeteer가 chromium-browser를 실행할 수 있도록 설정
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true  # 이미 chromium을 설치했기 때문에 puppeteer가 chromium을 다시 다운로드하지 않도록 설정
ENV DISPLAY=:99  # Xvfb에서 사용할 디스플레이 설정

WORKDIR /var/app  # 작업 디렉토리를 /var/app으로 설정

# 캐시를 이용해 npm 패키지 설치를 한번만 실행하도록 합니다.
COPY package.json package-lock.json ./
RUN npm ci --only=production  # production 환경에서 필요한 모듈들만 설치
RUN npm install puppeteer  # puppeteer 설치

COPY . .

RUN npm run build  # 앱 빌드

ENV NODE_OPTIONS="--max-old-space-size=2048"  # 메모리 사용량 설정

EXPOSE 3030  # 컨테이너의 포트를 3030으로 열어줌
CMD Xvfb :99 -screen 0 1024x768x16 -ac & node dist/src/main.js  # Xvfb를 실행하고, node 앱 실행

덧붙이자면 Xvfb는 가상화된 X Window 시스템을 생성해주는 X11 서버라고 한다. 이를 통해 실제로 화면이 없는 서버 컴퓨터에서도 그래픽 사용자 인터페이스(GUI) 기반의 어플리케이션을 실행시킬 수 있다고.. Puppeteer는 Chromium을 브라우저 엔진으로 사용하기 때문에, 해당 브라우저의 GUI 기능을 사용해야 하고 따라서, xvfb를 통해 GUI를 구현하는 환경을 만들어주어 Puppeteer가 정상적으로 동작하도록 한단다.


그리고 크롤링을 해오는 service.ts 파일에는

 const browser = await puppeteer.launch({
      headless: true,
      executablePath: '/usr/bin/chromium-browser',
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage',
        '--disable-gpu',
      ],
      ignoreHTTPSErrors: true,
    });

이렇게 옵션을 설정해주었다.

  • headless: 실행 중인 브라우저를 화면에 띄울지 여부를 결정하는 옵션. true로 설정하면 브라우저를 화면에 띄우지 않고 백그라운드에서 실행한다.

  • executablePath: 브라우저 실행 파일 경로를 지정하는 옵션. 위의 Dockerfile에서 ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser로 설정한 것과 같다.

  • args: 브라우저를 실행할 때 추가로 전달할 인수를 배열로 지정하는 옵션. 여기서는 Puppeteer가 Chromium 브라우저를 사용할 때 발생할 수 있는 문제를 방지하기 위한 인수를 지정하고 있다.
    --no-sandbox: Chrome이 Linux에서 쉘 권한을 가져오지 않도록 한다. 즉, 실행 중에는 컴퓨터 시스템에 어떤 영향도 미치지 않도록 보호한다.
    --disable-setuid-sandbox: setuid 권한이 있는 경우, 이 옵션은 Chromium의 내부 setuid sandbox를 비활성화한다. 이는 보안을 위한 옵션이다.
    --disable-dev-shm-usage: /dev/shm을 사용하지 않도록 설정하여, Chromium에서 메모리를 더 사용하고, 보안과 관련된 문제를 해결할 수 있다.
    --disable-gpu: GPU 가속을 사용하지 않도록 설정한다. GPU 가속을 사용하면 더 나은 성능을 제공할 수 있지만, 브라우저 실행 시 문제가 발생할 수도 있다. 이 옵션은 이러한 문제를 해결하기 위해 사용된다.

  • ignoreHTTPSErrors: HTTPS 에러를 무시하도록 하는 옵션. HTTPS 에러가 발생할 경우에도 Puppeteer가 작동하도록 한다.

혹시나 도움이 되길 바라며!

profile
📝 It's been waiting for you

1개의 댓글

comment-user-thumbnail
2024년 2월 27일

안녕하세요! 같은 에러로 고생하고 있는 사람입니다🥲 글 정말 많은 도움 됐습니다. 혹시 도커 이미지 빌드 과정에서 Error loading shared library ld-linux-x86-64.so.2: No such file or directory (needed by /usr/src/app/node_modules/.bin/node)나, Error: Cannot find module 'node-linux-x64/package.json' 같은 에러를 겪으신 적이 있으신가요? alpine 이미지 사용으로 나는 에러 같은데, 갈피를 못 잡겠어 댓글 남겨봅니다. puppeteer 어떤 버전 쓰셨는지도 궁금합니다! 좋은 하루 되세요!🥰

답글 달기