요즘 대부분의 서비스는 frontend와 backend를 분리해서 개발하고 있고, frontend와 backend 모두를 별도의 컨테이너로 만들고 Docker 또는 Kubernetes 환경에서 실행하는 경향이 있다.
PC의 로컬 환경에서 개발할 때 apt나 brew 등의 패키지 매니저를 이용해서 node를 설치하게 되면 node의 버전을 고정하기가 어렵다. nvm을 설치하면 node의 버전을 고정해서 사용하게 되기 때문에 엔터프라이즈 애플리케이션 개발에서는 필수라고 할 수 있다.
패키지 매니저를 사용한다고 하면 설치되는 node와 npm 버전을 종종 확인하여 Dockerfile에 반영해주자.
node --verison
npm --version
FROM node:18.20.5 as build
중략
RUN npm install -g [email protected] && npm install && npx browserslist@latest --update-db
이하 생략
이와 같이 node와 npm의 버전을 지정하여 사용하거나 설치하는 것을 권장한다.
nvm을 사용하게 되면 환경을 구축할 때 버전을 지정하게 되므로 일부러 업그레이드하지 않는 한 계속 같은 버전을 사용하게 되므로 node/npm 간 호환성이나 의존성 충돌 문제에서 좀 더 안전하다고 할 수 있다.
빌드는 node 컨테이너 내부에서 수행되도록 한다. 다음의 Dockerfile을 참고하면, 두 단계로 나눠서 하고 있는 것을 알 수 있는데 이를 "멀티 스테이지 빌드"라고 한다.
FROM node:18.20.5 as build
WORKDIR /app
COPY frontend/package.json frontend/package-lock.json .
RUN npm install -g [email protected] && npm install && npx browserslist@latest --update-db
COPY frontend/ .
RUN npm run build
FROM nginx:1.25
COPY --from=build /app/dist /usr/share/nginx/html
COPY frontend/default.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
node 컨테이너를 만들고 여기에 개발 환경의 package.json과 package-lock.json을 복사한다. 이 두 파일을 복사해야 개발 환경에서 없었던 의존성간 충돌이 빌드 환경에서 갑자기 발생하지 않는다. 이 두 파일 중 특히 package-lock.json 파일이 의존성간 버전을 고정하기 때문에 개발 환경과 빌드 환경의 의존성 버전이 동일하게 유지되는 것이다.
npm run build로 만들어진 산출물(dist 디렉토리에 있는 js, css, html, 이미지 파일들)을 nginx 컨테이너를 만들어 거기에 복사한다.
위에서 작성한 Dockerfile을 가지고 컨테이너 이미지를 빌드한다.
docker build -f Dockerfile -t my_id/my_frontend .
my_id/my_frontend라는 이름의 이미지로 빌드한다. 단순히 docker를 이용해서 실행한다면 여기까지 작업해도 충분하다.
Kubernetes에 배포하려면 레지스트리(registry) 서버가 필요하다. K8s 애드온으로 레지스트리의 설치가 가능하다. 또는 Docker Hub에 공식적으로 publish할 수도 있다. 레지스트리 서버가 준비되어 있다고 가정한다.
레지스트리 서버에 push하기 위해 미리 태깅을 한다. 태깅을 한다는 의미는 버전이나 릴리스의 이름을 지정한다는 의미이다.
docker tag my_id/my_frontend:latest 레지스트리서버/my_id/my_frontend:latest
레지스트리에 push한다.
docker push 레지스트리서버/my_id/my_frontend:latest
빌드 절차는 여기까지이고, K8s 환경에서 구동시키려면 ingress/service/deployment를 위한 매니페스트(manifest) yaml 파일을 작성해서 kubectl로 apply하고, 재배포할 때는 kubectl로 rollout하면 된다.