์ฌ์ค ํ๋ฒ์ ๋๋ ์ค ์๊ณ dev ๋ธ๋์น์ ๋ฐ๋ก ํ ์คํธ๋ฅผ ํ๋ค. ๊ทธ ๊ฒฐ๊ณผ ์์ง ์ ๋๋ก ์์๋ ์ํ๋๋ฐ ์ปค๋ฐ์ด 100๊ฐ๊ฐ ๋์ด๊ฐ๋ ๋ถ์์ฌ๊ฐ ์๊ฒผ๋ค. ์ด์จ๋ ๋ชจ๋ ธ๋ ํฌ ์๋ฆฌ์ฆ ๋ง์ง๋ง์ Docker์ Github Actions๋ฅผ ์ด์ฉํ CI/CD ๊ตฌ์ถ ์ฝ์ง๊ธฐ. ๋ณ๋ก ์ด๋ ค์ด ๋ด์ฉ์ด ์๋๊ณ , ๊ทธ๋ ๊ธฐ์ ๊ฑฐ์ฐฝํ ์ ๋ณด ๊ณต์ ๋ชฉ์ ์ ๊ฒฐ์ฝ ์๋๋ค. ํ์ง๋ง ๋์ฒ๋ผ ์ฉํ ์ฒ์ ๋ชจ๋ ธ๋ ํฌ๋ฅผ ์๋ํด๋ณด๋ ์ฌ๋๋ค์ด ์ฝ๊ฒ ์ฐธ๊ณ ํ ์ ์์๋งํ ๊ธ์ด ๋ณ๋ก ์์ด ํ๋ค์๊ธฐ ๋๋ฌธ์ ๊พธ์ญ๊พธ์ญ ์ฐ๋ ๊ธ.
๊ธฐ๋ณธ์ ์ผ๋ก ์ด์ ์ ๊ตฌ์ถํด ์ฌ์ฉํ๋ ์ธํ ์ ๋ฐํ์ผ๋ก ํ๊ณ ์๋ค. (1ํธ, 2ํธ) ํฌ๊ฒ ๋ค๋ฅผ๊ฑด ์์ง๋ง, ๊ฑฐ๊ธฐ์๋ถํฐ ํ์คํ์ค์ฉ ๋ฐ๊ฟ๊ฐ๋ ๊ณผ์ ์ด๋ผ๊ณ ๋ณด๋ฉด ๋ ๊ฒ ๊ฐ์. ๋ฐ์ง๊ณ ๋ณด๋ฉด ํ์คํ์ค์ฉ ๊ณ ์ณ๋๊ฐ๋ ๊ณผ์ ..
"scripts": {
// ...
"admin:build": "yarn workspace admin build",
"ticket:build": "yarn workspace ticket build",
"ticket:start": "yarn workspace ticket start",
},
๋จผ์ ๋ฃจํธ์ package.json์์ ์์ ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํ๋ค. ์ํฌ์คํ์ด์ค์ ์๋ ํ app์ package.json์ ์๋ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ ์ ์๋ค.
Dockerfile.admin
FROM node:16 AS builder
# set working directory
WORKDIR /app
# install app dependencies
COPY package.json ./
COPY yarn.lock ./
# Installs all node packages
RUN npm install yarn --global --force
RUN yarn install --immutable --immutable-cache --check-cache
# Copies everything over to Docker environment
COPY . ./
RUN yarn install --immutable
RUN yarn admin:build
#Stage 2
#######################################
#pull the official nginx:1.19.0 base image
FROM nginx:1.19.0
COPY ./nginx/admin.conf /etc/nginx/conf.d/default.conf
# Remove default nginx static resources
RUN rm -rf ./usr/share/nginx/html/*
# Copies static resources from builder stage
COPY --from=builder /app/apps/admin/dist /usr/share/nginx/html/
EXPOSE 3100
ENTRYPOINT ["nginx", "-g", "daemon off;"]
์ด๋๋ฏผ ๋ ํฌ์งํ ๋ฆฌ์ ๋ํ ๋์ปคํ์ผ์ด๋ค. ๊ธฐ์กด 9์๊ณต์ฐ ์๋น์ค์์ ์ฐ๋๊ฑธ ํ ๋๋ก ๋ฐ๊พธ๋ค ๋ณด๋ yarn install
์ ๋๋ฒ์ ๋๋์ด์ ํ๊ฒ ๋์๋๋ฐ, ์ง๊ธ ์๊ฐํ๋๊น ๊ทธ๋ด ํ์๊ฐ ์์๋ค.
yarn์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ npm์์ ๋จผ์ yarn์ ์ค์นํ ํ์ ์์กด์ฑ ํจํค์ง๋ค์ ์ค์นํด์ค๋ค. CI ํ๊ฒฝ์์๋ yarn.lockํ์ผ์ ์์ฑํ์ง ์๊ณ ์
๋ฐ์ดํธ๊ฐ ํ์ํ ๊ฒฝ์ฐ ์คํจํ๋๋ก ํด์ฃผ๋๊ฒ ์์ ํ๋ค ํ๋ค. --frozen-lockfile
์ต์
์ผ๋ก ์ฌ์ฉํ ์ ์์๋ค. ์ด์ ๋ ๊ทธ๋ณด๋ค --immutable
์ต์
์ ์ฌ์ฉํ๋ผ๊ณ ๊ถ์ฅํ๊ณ ์๋ค. --immutable-cache
์ --check-cache
์ต์
์ zero-install ํ๊ฒฝ์์ ์ฌ์ฉํ๋ค๊ณ ํ๋๋ฐ,, ์ง๊ธ์ zero-install์ ์ฌ์ฉํ์ง ์๊ณ ์์ผ๋๊น ์์ ํด์ผ๊ฒ ๋ค.
์์กด์ฑ ์ค์น ํ์๋ ์์ ์คํฌ๋ฆฝํธ์ ์์ฑํด๋์๋ yarn admin:build
๋ช
๋ น์ผ๋ก ์ด๋๋ฏผ ํ๋ก์ ํธ๋ฅผ ๋น๋ํ๋ค. ๊ทธ ๋ค๋ก nginx ์ค์ ํ์ผ์ ๊ฒฝ๋ก ์ธ์๋ ๋ณ๊ฒฝ์ฌํญ์ด ์๋ค.
Dockerfile.ticket
๋ค์์ Next ํ๋ก์ ํธ ๊ด๋ จ ๋์ปคํ์ผ์ด๋ค. ๋ฅ์คํธ๋ฅผ ์ฐ๋ ํ๋ก์ ํธ๊ฐ ์ฒ์์ด๋ผ ๋น๊ต์ ์ฝ์ง์ด ๋ง์๋ค.
FROM node:16-alpine AS builder
# set working directory
WORKDIR /app
# install app dependencies
COPY package.json ./
COPY yarn.lock ./
# Installs all node packages
RUN npm install yarn --global --force
RUN yarn install --immutable --immutable-cache --check-cache
# Copies everything over to Docker environment
COPY . ./
RUN rm -rf apps/admin
RUN yarn install
RUN yarn ticket:build
RUN rm -rf apps/ticket/.next/cache
#Stage 2
EXPOSE 3000
CMD ["yarn", "ticket:start"]
๋ฆฌ์กํธ ํ๋ก์ ํธ ๋ฐฐํฌํ ๋์ ํฌ๊ฒ ๋ค๋ฅธ๊ฑด ์๋ค. ๋ค๋ง Nginx๋ฅผ ์ฌ์ฉํ์ง ์๊ณ Next ์๋ฒ๋ฅผ ์คํ์์ผ ์ฌ์ฉํ๋ค. ๋ชจ๋
ธ๋ ํฌ ๊ด๋ จ ์ธํ
์ฝ์ง์ ํ๋ฉด์ ์ด๋๊ฐ ๊ผฌ์๋์ง, yarn install
์ --immutable
์ต์
์ ์ฃผ๋ฉด yarn.lock์ด ๋ณ๊ฒฝ๋ ์ ์๋ค๊ณ ์ค๋ฅ๋ด๊ณ ๋๋ด๋ฒ๋ฆฌ๋๋ผ. ์ต์
์ ์ ๊ฑฐํด์ฃผ์ด๋ ์ผ๋จ ๋น๋ ์๋๊ณ ๋ฐฐํฌ๋ ์ ๋๋๊ฒ์ ๋ณด๊ณ ... ์ผ๋จ์ ๊ทธ๋ ๊ฒ ํ๋ค. ๋ชจ๋ ์์ ๊ฑด๋ฌผ์ ์ง๋ ๋๋์ด๋ค.
์ฒ์ ๋ฑ ๋์ปค ์ด๋ฏธ์ง๋ฅผ ํ๋ธ์ ์ฌ๋ ธ๋๋ ๋ฌด๋ ค 750MB์ ์ฉ๋์ ๊ฐ๊ณ ์์๋ค. ์ด๊ฒ ๋ง์ด ๋๋?? ์ต๋ํ ์ด๋ฏธ์ง์ ํฌ๊ธฐ๋ฅผ ์ค์ฌ๋ณด๋ ค๊ณ ํ๋ค.
node ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ฌ ๋ ์ฉ๋์ด ๊ฐ์ฅ ์์ alpine ๋ฒ์ ์ ์ฌ์ฉํ๋๋ก ๋ฐ๊ฟจ๋ค. ์ด๊ฒ ํ๋๋ง์ผ๋ก ๊ฑฐ์ 200MB ๊ฐ๊น์ด ์ค์ด๋ค์๋ค. ์ถ๊ฐ๋ก ์ด๋๋ฏผ ๊ด๋ จ ๋๋ ํ ๋ฆฌ๋ฅผ ์ง์ ๊ณ , ๋น๋ ํ ๋์จ .next์ cache ํ์ผ๋ค๋ ์ญ์ ํ๋๋ก ํ๋ค. ๊ทธ ๊ฒฐ๊ณผ 450MB์ ๋๋ก ์ค์ผ ์ ์์๋ค. ํ์ง๋ง ์ฌ์ ํ ํฌ๋ค..! ์๋ ์ด๋ฐ๊ฑด๊ฐ.
GitHub Actions
์ก์ ์ํฌํ๋ก์ฐ ํ์ผ์ ํฐ์ผ๊ณผ ์ด๋๋ฏผ์ด ๊ฑฐ์ ๋์ผํ๋ค. ์ค์ํ๊ฒ ๋ณผ ๋ถ๋ถ์ ํ๊ทธ ๋ถ๋ถ์ด๋ค.
๊นํ๋ธ์์ ์๋ก์ด ํ๊ทธ๋ฅผ ๋ฌ๊ณ ๋ฆด๋ฆฌ์ฆ๋ฅผ ํ๋ฉด ์ก์
์ด ํธ๋ฆฌ๊ฑฐ๋๊ณ ๋์ปค ์ด๋ฏธ์ง๊ฐ ํ๋ธ๋ก ์ฌ๋ผ๊ฐ๋๋ก ํ๋, ๊ทธ๋ฐ ํ๋ฆ์ ๊ฐ๊ณ ์๋ค. ํฐ์ผ๊ณผ ์ด๋๋ฏผ ๋ ํฌ ๊ฐ๊ฐ ๋ณ๊ฐ๋ก ์คํ๋์ด์ผ ํ๋ค. ๋ฆด๋ฆฌ์ฆ๋ฅผ ํ ๋ ํ๊ทธ๋ช
์ 'Ticket-\*'
, 'Admin-\*'
๊ณผ ๊ฐ์ด ์์ ๋ ํฌ๋ช
์ ๋ถ์ฌ์ ์ฌ๋ฆฐ๋ค. ๊ทธ๋ผ ๊ทธ ํ๊ทธ ๋ช
์ ๋ง๋ ์ก์
์ด ์คํ๋๋๋ก ํ๋ค.
name: Build & Docker Push - Ticket
on:
push:
# branches: [dev]
# paths: ['apps/ticket/pages/**']
# Publish semver tags as releases.
tags:
- Ticket-v*.*.*
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# ๋์ปค ์ด๋ฏธ์ง์ env ํ์ผ ํฌํจ
- name: Create .env file
run: |
touch .env
echo "${{ secrets.ENV_VARS_TICKET }}" >> .env
# ๋์ปค ์ด๋ฏธ์ง ๋ฒ์ ๊ฐ์ ธ์ค๊ธฐ
- name: Get the version
id: get_version
run: |
RELEASE_VERSION_WITHOUT_V="$(cut -d'v' -f2 <<< ${GITHUB_REF#refs/*/})"
echo ::set-output name=VERSION::$RELEASE_VERSION_WITHOUT_V
# ๋์ปค ๋น๋ ๊ด๋ จ ์
์
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
# ๋ด ๋์ปคํ๋ธ ๋ก๊ทธ์ธ
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# ๋์ปค์ด๋ฏธ์ง ๋น๋ํ๊ณ ํ๋ธ๋ก ํธ์ฌ
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile.ticket
platforms: linux/amd64
push: true
tags: david0218/dudoong-ticket:${{ steps.get_version.outputs.VERSION }}
์ค์ํ ๋ถ๋ถ์ ๊นํ๋ธ์์ ๋ฆด๋ฆฌ์ฆ๋ ๋ฒ์ ์ ๊ฐ์ ธ์ค๊ณ , 'v'์์ ๋ด์ฉ์ ๋ผ์ ๋ฑ 'x.x.x' ๋ถ๋ถ๋ง ํ๊ทธ๋ก ๋ฌ์์ค๋ค๋ ๊ฒ. ๋ฐฑ์๋ ํ์ฅ์น๊ตฌ์ ์ฝ๋์ด๋ค!! (์ด๊ฑฐ ์์ฐ๋ฉด ๋ถ๋ช ๋ญ๋ผํ ๊ฒ๊ฐ์ใ ใ )
๋์ปค ํ๋ธ์ ๋ฑ ์ํ๋ ํ๊ทธ๋ก ๋ฌ๋ ค์ ์ฌ๋ผ๊ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ์ปดํฌ์ฆ์์ ์ํ๋ ํ๊ทธ๋ก ๊ฐ์ ธ์์ ๋ฐฐํฌํ๋๋ก ํ ์ ์๋ค.
๋ถ๋ช ํ ์ฝ์ง์ ๋ ๋ง์ด ํ๋ ๊ฒ ๊ฐ์๋ฐ, ๋์ค์ ๊ธฐ์ต ๋์ง์ด์ ์ฐ๋ ค๋๊น ๋น ์ง ๋ถ๋ถ์ด ๋ง์ ๊ฒ ๊ฐ๋ค. ํ์ธ.