프로젝트를 진행할 때, 프론트엔드 배포는 주로 nginx를 base image로 하여 빌드된 결과물을 nginx가 서빙하는 폴더 내에 위치시켜 보여주는 식으로 진행했다.
인터넷에 React 배포 / React + Docker 배포 검색했을 때 가장 쉽고 많이 찾을 수 있어 당연하게 했던 것 같다.
그러던 중 프론트엔드 도커 파일을 작성할 일이 있었다. 당연히 위 방식으로 진행했다. 근데 특히나 오타나 약간의 UI 변경 등 잦은 수정이 필요한 프론트엔드에서 위의 방식대로 진행하면 비효율적이라는 피드백을 받았다. nginx 이미지가 변경되는 것이 아닌 굳이 오타 수정하는데 해당 이미지도 다시 받고 올린다는 게 맞는가? 에 대한 얘기였다.
빌드 파일만 달라지지 nginx 이미지 자체에 대해서는 변경이 없다는 의미!
그래서 좀 더 효율적인 배포가 되도록 구성해 봤다.
✅ 기존 방식
1. index.html 생성
- 실제 배포할 때는 빌드된 결과물
- 예를 들어 React + Vite의 경우 dist 폴더
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>Deploy Test</title>
</head>
<body>
<div id="root">v1</div>
</body>
</html>
2. Dockerfile 생성
FROM nginx
COPY index.html /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
3. Docker Image 생성
docker build -t fe:v1 .
4. Docker Container 실행
docker run -d -p 8080:80 --name fe fe:v1
5. Container 실행 확인
✅ 새로 구성한 방식
자 생각해 보자.
기존 방식에서 변경사항이 있었을 때, 의미가 있던 부분은 COPY index.html /usr/share/nginx/html 이다. 변경된 빌드 파일을 nginx가 서빙하는 폴더에 넣어주는 것!
그렇다면 nginx 이미지는 계속 떠 있으면서 이 부분을 변경하려면 어떻게 해야 할까?
내가 생각한 답은 Docker Volume이다.
nginx가 container로 뜰 때 /usr/share/nginx/html 폴더가 build 결과물이 담길 볼륨을 바라보게 하면 된다! 즉, 변경 사항이 생겨 새로 빌드가 이뤄졌을 때 그 결과물이 nginx container에 마운트 된 볼륨에 저장되면 해당 볼륨을 바라보고 있는 nginx도 새로운 빌드 파일을 서빙하게 된다.
1. Nginx 실행
docker pull nginx
docker run -d -p 8080:80 -v nginx-vol:/usr/share/nginx/html --name fe nginx:stable-alpine
2. index.html 생성
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>Deploy Test</title>
</head>
<body>
<div id="root">v1</div>
</body>
</html>
3. Dockerfile, entrypoint.sh 생성
- 위 이미지는 변경된 파일을 복사해 주는 역할만 한다.
- 따라서 index.html을 컨테이너 내부로 옮겨주고 해당 파일을 volume에 복사될 수 있도록 한다.
- 그냥 도커 파일 내부에 한 번에 입력해 줘도 된다.
Dockerfile
FROM busybox
WORKDIR /build
ADD index.html .
ADD entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["sh", "/entrypoint.sh"]
entrypoint.sh
#!/bin/bash
cp -r /build/. /usr/share/nginx/html
4. Docker Image 생성
docker build -t fe:v1 .
5. Docker Container 실행
docker run -v nginx-vol:/usr/share/nginx/html fe:v1
6. Container 실행 확인
- nginx 시작페이지가 아닌 새로운 페이지가 뜨는 것을 확인할 수 있다.
✅ 실제 배포 환경에서는?
위는 index.html의 body부분의 텍스트만 변경해 보며 테스트했었다. 실제 배포에 이용할 때는 멀티스테이지 빌드를 이용하면 된다. dockerfile 부분만 변경하기!
Dockerfile
#########
# BUILD #
#########
FROM node:16.20.0 AS BUILD_FRONTEND
RUN mkdir -p /app
WORKDIR /app
ADD . .
RUN npm install
RUN npm run build
#########
## RUN ##
#########
FROM busybox
WORKDIR /build
COPY --from=BUILD_FRONTEND app/dist/. .
ADD entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["sh", "/entrypoint.sh"]
이렇게 도커 파일을 구성하면 프론트엔드 빌드 파일이 작으면 작을수록 효과가 크다는 장점이 있다.
실제 배포 파일을 확인했을 때 사용하고 있던 nginx는 80MB, 프론트엔드 빌드 파일은 불과 2.4MB였다!
2.4MB를 위해 80MB을 계속 죽이고 올린다는 건 확실히 비효율적이다. 물론 80MB 받고 올리는 건 순식간이지만
gitjub action에 위 과정을 포함해 더 추가하면 CICD 완성!
앞으로 뭘 하든 좀 더 효율적인 방안이 없나 고민해야겠다… 😭 뭐든 당연하게 생각하지 않기….
'프로그래밍 > 프론트엔드' 카테고리의 다른 글
Vite Alias 설정하기 (0) | 2024.03.24 |
---|---|
[Vue.js] Watch vs Computed (0) | 2023.05.30 |