Skip to content

lcs07/nextjs-firebase-docker

Repository files navigation

Next.js + Firebase + Cloud Run

Deploy to Firebase Hosting on merge PROD




목차








참고 자료








CI/CD 설정

CI/CD 목표

  • git dev 브랜치에 push(PR merge) 이벤트 발생시 개발, 테스트 서버에 자동 배포
  • git main 브랜치에 push(PR merge) 이벤트 발생시 운영 서버에 자동 배포
  • Docker를 사용해서 Next.js 다국어 지원(next-i18next) 관련 오류 해결
  • Firebase FunctionsNext.js 사용시 서비스 제공에 오래 걸리는 문제 해결
  • Docker를 이용하기 위해 Firebase Hosting과 연동 가능한 Cloud Run 서비스 사용
  • 이미지 파일 등의 정적인 파일은 Firebase Hosting으로 제공
  • Next.js에서 처리되어야 하는 동적인 컨텐츠는 Cloud Run으로 제공
  • Next.js

    • Docker 이미지를 빌드하기 위해 Cloud Build 서비스 사용
    • 빌드 된 이미지를 저장하기 위해 Artifact Registry 서비스 사용
    • 빌드 된 이미지는 Cloud Run 서비스로 배포
    • Cloud Build에서 Cloud Run 까지 빌드 및 배포 자동화를 위해 Cloud Build의 빌드 구성 파일 설정
  • 정적 파일

    • 정적인 파일은 Firebase Hosting으로 제공하고 그외의 콘텐츠는 Cloud Run으로 연결
    • 정적인 파일은 빌드가 필요 없음
    • GitHub ActionsFirebase Hosting에 배포




프로젝트 정보

Project ID

  • 개발
    • Project ID : nextjs-2022-dev
    • Project Number : ``
  • 테스트, 운영
    • Project ID : nextjs-2022
    • Project Number : 28623504743

Project Alias

  • 프로젝트 별칭
  • 개발 : development
  • 테스트 : test
  • 운영 : production

Firebase Hosting site name

  • 개발 : nextjs-2022-dev
  • 테스트 : nextjs-2022-test
  • 운영 : nextjs-2022

GCP Cloud Run service name (Docker image name)

  • Cloud Run service name은 Docker image name과 동일하지 않아도 됨
  • 관리 편의를 위해 동일하게 처리
  • 개발 : docker-nextjs-dev
  • 테스트 : docker-nextjs-test
  • 운영 : docker-nextjs




Firebase CLI

  • 설치

    npm install -g firebase-tools
  • 계정 로그아웃

    firebase logout
  • 계정 로그인

    firebase login
  • 계정 추가

    firebase login:add
  • 계정 목록

    firebase login:list
  • 계정 전환

    firebase login:use {EMAIL}
  • 프로젝트 목록

    firebase use
  • 프로젝트 추가 및 별칭(alias) 생성

    • .firebaserc 파일 확인
    • 개발 프로젝트 별칭 : development
    • 테스트 프로젝트 별칭 : test
    • 운영 프로젝트 별칭 : production
    firebase use --add
  • 프로젝트 전환

    firebase use {PROJECT_ID | PROJECT_ALIAS}
    • 개발 프로젝트 전환

      firebase use development
    • 테스트 프로젝트 전환

      firebase use test
    • 운영 프로젝트 전환

      firebase use production




Google Cloud CLI

  • 설치

  • 계정 로그인

    gcloud auth login
  • 계정 목록

    gcloud auth list
  • 계정 전환

    gcloud config set account {EMAIL}
  • 프로젝트 목록

    gcloud projects list
  • 현재 프로젝트 확인

    gcloud config get-value project
  • 프로젝트 전환

    gcloud config set project {PROJECT_ID}
    • 개발 프로젝트 전환

      gcloud config set project nextjs-2022-dev
    • 테스트, 운영 프로젝트 전환

      gcloud config set project nextjs-2022




Docker

  • 로컬에서 Docker 이미지 실행 확인 방법
  • Dockerfile 파일 생성

    # Install dependencies only when needed
    FROM node:16-alpine AS deps
    # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
    RUN apk add --no-cache libc6-compat
    WORKDIR /app
    COPY package.json yarn.lock ./
    RUN yarn install --frozen-lockfile
    
    # If using npm with a `package-lock.json` comment out above and use below instead
    # COPY package.json package-lock.json ./ 
    # RUN npm ci
    
    # Rebuild the source code only when needed
    FROM node:16-alpine AS builder
    WORKDIR /app
    COPY --from=deps /app/node_modules ./node_modules
    COPY . .
    
    # Next.js collects completely anonymous telemetry data about general usage.
    # Learn more here: https://nextjs.org/telemetry
    # Uncomment the following line in case you want to disable telemetry during the build.
    # ENV NEXT_TELEMETRY_DISABLED 1
    
    # $ docker build -t docker-nextjs-dev --build-arg BUILD_TARGET=dev .
    # $ docker build -t docker-nextjs-test --build-arg BUILD_TARGET=test .
    # $ docker build -t docker-nextjs --build-arg BUILD_TARGET=prod .
    ARG BUILD_TARGET
    RUN echo "BUILD_TARGET: $BUILD_TARGET"
    
    # RUN yarn build:$BUILD_TARGET
    RUN yarn env:$BUILD_TARGET yarn next:build
    
    # If using npm comment out above and use below instead
    # RUN npm run build
    
    # Production image, copy all the files and run next
    FROM node:16-alpine AS runner
    WORKDIR /app
    
    ENV NODE_ENV production
    # Uncomment the following line in case you want to disable telemetry during runtime.
    # ENV NEXT_TELEMETRY_DISABLED 1
    
    RUN addgroup --system --gid 1001 nodejs
    RUN adduser --system --uid 1001 nextjs
    
    # You only need to copy next.config.js if you are NOT using the default configuration
    COPY --from=builder /app/next.config.js ./
    # COPY --from=builder /app/public ./public
    COPY --from=builder /app/public/locales ./public/locales
    COPY --from=builder /app/package.json ./package.json
    
    # Automatically leverage output traces to reduce image size 
    # https://nextjs.org/docs/advanced-features/output-file-tracing
    COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
    COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
    
    USER nextjs
    
    EXPOSE 3000
    
    ENV PORT 3000
    
    CMD ["node", "server.js"]
  • Docker 이미지 생성

    docker build --build-arg BUILD_TARGET={PROJECT_ALIAS} -t {IMAGE_NAME} .
    • 개발

      docker build --build-arg BUILD_TARGET=dev -t docker-nextjs-dev .
    • 테스트

      docker build --build-arg BUILD_TARGET=test -t docker-nextjs-test .
    • 운영

      docker build --build-arg BUILD_TARGET=prod -t docker-nextjs .
  • Docker 실행

    docker run -p 3000:3000 {IMAGE_NAME}
    • 개발

      docker run -p 3000:3000 docker-nextjs-dev
    • 테스트

      docker run -p 3000:3000 docker-nextjs-test
    • 운영

      docker run -p 3000:3000 docker-nextjs
  • Docker 실행 확인




GCP Artifact Registry

  • 저장소 생성

    gcloud artifacts repositories create {REPOSITORY_NAME} --repository-format=docker --location={REGION_NAME} --description="Docker repository"
    • 각 프로젝트 마다 실행
      gcloud artifacts repositories create docker-repo --repository-format=docker --location=asia-northeast3 --description="Docker repository"
  • 저장소 목록 확인

    gcloud artifacts repositories list
  • Docker 인증 파일 생성

    gcloud auth configure-docker {REGION_NAME}-docker.pkg.dev
    • 각 프로젝트 마다 실행
      gcloud auth configure-docker asia-northeast3-docker.pkg.dev
  • Docker 이미지 주소 형식

    {REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME}
    
    • 개발

      asia-northeast3-docker.pkg.dev/nextjs-2022-dev/docker-repo/docker-nextjs-dev
      
    • 테스트

      asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs-test
      
    • 운영

      asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs
      
  • 태그 생성

    docker tag {IMAGE_NAME} {REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME}
    • 개발

      docker tag docker-nextjs-dev asia-northeast3-docker.pkg.dev/nextjs-2022-dev/docker-repo/docker-nextjs-dev
    • 테스트

      docker tag docker-nextjs-test asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs-test
    • 운영

      docker tag docker-nextjs asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs
  • 이미지 업로드

    docker push {REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME}
    • 개발

      docker push asia-northeast3-docker.pkg.dev/nextjs-2022-dev/docker-repo/docker-nextjs-dev
    • 테스트

      docker push asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs-test
    • 운영

      docker push asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs




GCP Cloud Build

  • 빌드 생성

    gcloud builds submit --tag {REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME} --project {PROJECT_ID}
    • 개발

      gcloud builds submit --tag asia-northeast3-docker.pkg.dev/nextjs-2022-dev/docker-repo/docker-nextjs-dev --project nextjs-2022-dev
    • 테스트

      gcloud builds submit --tag asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs-test --project nextjs-2022
    • 운영

      gcloud builds submit --tag asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs --project nextjs-2022
  • 빌드 배포 서비스 계정 권한

  • 빌드 구성 파일 설정

    • Docker 이미지 생성 구성

      • [권장] 방법 1
        steps:
        # Build the container image
        - name: 'gcr.io/cloud-builders/docker'
          args: ['build', '-t', '{REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME}', '.', '--build-arg', 'BUILD_TARGET={PROJECT_ALIAS}', '--no-cache']
      • 방법 2
        steps:
        # Build the container image
        - name: 'gcr.io/cloud-builders/docker'
          entrypoint: 'bash'
          args: ['-c', 'docker build -t {REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME} . --build-arg BUILD_TARGET={PROJECT_ALIAS} --no-cache']
    • Docker 이미지 생성 + Artifact Registry에 이미지 업로드 + Cloud Run 배포

      • 샘플 파일명 : cloudbuild.yaml
      steps:
      # Build the container image
      - name: 'gcr.io/cloud-builders/docker'
        args: ['build', '-t', '{REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME}', '.', '--build-arg', 'BUILD_TARGET={PROJECT_ALIAS}', '--no-cache']
      # Push the container image to Artifact Registry
      - name: 'gcr.io/cloud-builders/docker'
        args: ['push', '{REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME}']
      # Deploy container image to Cloud Run
      - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
        entrypoint: gcloud
        args: ['run', 'deploy', '{IMAGE_NAME}', '--image', '{REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME}', '--platform', 'managed', '--region', '{REGION_NAME}', '--allow-unauthenticated', '--memory', '512Mi', '--min-instances', '0']
      images:
      - {REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME}
      timeout: 1800s
      • 개발 구성 파일

        • 파일명 : cloudbuild.dev.yaml
      • 테스트 구성 파일

        • 파일명 : cloudbuild.test.yaml
      • 운영 구성 파일

        • 파일명 : cloudbuild.prod.yaml
        steps:
        # Build the container image
        - name: 'gcr.io/cloud-builders/docker'
          args: ['build', '-t', 'asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs', '.', '--build-arg', 'BUILD_TARGET=prod', '--no-cache']
        # Push the container image to Artifact Registry
        - name: 'gcr.io/cloud-builders/docker'
          args: ['push', 'asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs']
        # Deploy container image to Cloud Run
        - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
          entrypoint: gcloud
          args: ['run', 'deploy', 'docker-nextjs', '--image', 'asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs', '--platform', 'managed', '--region', 'asia-northeast3', '--allow-unauthenticated', '--memory', '512Mi', '--min-instances', '0']
        images:
        - asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs
        timeout: 1800s
  • 빌드 구성 실행

    gcloud builds submit --config {BUILD_CONFIG_FILE} {SOURCE_DIRECTORY}
    • 개발

      gcloud builds submit --config cloudbuild.dev.yaml .
    • 테스트

      gcloud builds submit --config cloudbuild.test.yaml .
    • 운영

      gcloud builds submit --config cloudbuild.prod.yaml .




GCP Cloud Run

  • 배포

    gcloud run deploy SERVICE --image REPO-LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE \
    [--platform managed --region RUN-REGION]
    gcloud run deploy {SERVICE_NAME} --image {REGION_NAME}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY_NAME}/{IMAGE_NAME} --project {PROJECT_ID} --platform managed --region {REGION_NAME} --allow-unauthenticated --memory 512Mi --min-instances 0
    • 개발

      gcloud run deploy docker-nextjs-dev --image asia-northeast3-docker.pkg.dev/nextjs-2022-dev/docker-repo/docker-nextjs-dev --project nextjs-2022-dev --platform managed --region asia-northeast3 --allow-unauthenticated --memory 512Mi --min-instances 0
    • 테스트

      gcloud run deploy docker-nextjs-test --image asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs-test --project nextjs-2022 --platform managed --region asia-northeast3 --allow-unauthenticated --memory 512Mi --min-instances 0
    • 운영

      gcloud run deploy docker-nextjs --image asia-northeast3-docker.pkg.dev/nextjs-2022/docker-repo/docker-nextjs --project nextjs-2022 --platform managed --region asia-northeast3 --allow-unauthenticated --memory 512Mi --min-instances 0




GitHub + GCP Cloud Build

GCP Cloud Build Dashboard

  • 트리거 생성
    • Cloud Build 콘솔에서 트리거 생성
    • Cloud Build GitHub 앱 연동
      • GitHub 저장소 접근 권한 설정




GitHub Actions + Firebase Hosting

GitHub Actions

  • GitHub 연동 설정

    firebase use {PROJECT_ID | PROJECT_ALIAS}
    firebase target:apply hosting {HOSTING_TARGET_NAME} {HOSTING_SITE_NAME}
    firebase init hosting:github
    • 개발

      firebase use development
      firebase target:apply hosting development nextjs-2022-dev
      firebase init hosting:github
      • GitHub workflow 파일명 변경
        • 기존 : .github/workflows/firebase-hosting-merge.yml
        • 변경 : .github/workflows/firebase-hosting-merge-dev.yml
    • 테스트

      firebase use test
      firebase target:apply hosting test nextjs-2022-test
      firebase init hosting:github
      • GitHub workflow 파일명 변경
        • 기존 : .github/workflows/firebase-hosting-merge.yml
        • 변경 : .github/workflows/firebase-hosting-merge-test.yml
    • 운영

      firebase use production
      firebase target:apply hosting production nextjs-2022
      firebase init hosting:github
      • GitHub workflow 파일명 변경
        • 기존 : .github/workflows/firebase-hosting-merge.yml
        • 변경 : .github/workflows/firebase-hosting-merge-prod.yml
  • .firebaserc 파일 내용 확인

    {
      "projects": {
        "default": "nextjs-2022-dev",
        "development": "nextjs-2022-dev",
        "test": "nextjs-2022",
        "production": "nextjs-2022"
      },
      "targets": {
        "nextjs-2022-dev": {
          "hosting": {
            "development": [
              "nextjs-2022-dev"
            ]
          }
        },
        "nextjs-2022": {
          "hosting": {
            "test": [
              "nextjs-2022-test"
            ],
            "production": [
              "nextjs-2022"
            ]
          }
        }
      }
    }
  • GitHub workflow 파일 수정

    • 개발 .github/workflows/firebase-hosting-merge-dev.yml 파일 수정

      • workflow_dispatch: 추가 - 수동으로 workflow를 실행 할 수 있는 이벤트
      • target: development 추가 - Firebase Hosting 배포 대상 지정
    • 테스트 .github/workflows/firebase-hosting-merge-test.yml 파일 수정

      • workflow_dispatch: 추가 - 수동으로 workflow를 실행 할 수 있는 이벤트
      • target: test 추가 - Firebase Hosting 배포 대상 지정
    • 운영 .github/workflows/firebase-hosting-merge-prod.yml 파일 수정

      • workflow_dispatch: 추가 - 수동으로 workflow를 실행 할 수 있는 이벤트
      • target: production 추가 - Firebase Hosting 배포 대상 지정
      # This file was auto-generated by the Firebase CLI
      # https://github.com/firebase/firebase-tools
      
      name: Deploy to Firebase Hosting on merge PROD
      'on':
        push:
          branches:
            - main
        workflow_dispatch:
      jobs:
        build_and_deploy:
          runs-on: ubuntu-latest
          steps:
            - uses: actions/checkout@v2
            # - run: yarn && yarn build
            - uses: FirebaseExtended/action-hosting-deploy@v0
              with:
                repoToken: '${{ secrets.GITHUB_TOKEN }}'
                firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_NEXTJS_2022 }}'
                channelId: live
                projectId: nextjs-2022
                target: production








수동 배포

  • [주의] Cloud Run이 배포 완료 된 후 Firebase Hosting 배포를 진행해야 함
  • 최초 배포시 Cloud Run 생성이 안되어 있으면 Firebase Hosting 배포시 오류 발생

WEB에서 직접 배포

  • GCP Cloud Run 배포

    GCP Cloud Build Trigger

    • 개발

      • 트리거 : build-github-trigger-dev
    • 테스트

      • 트리거 : build-github-trigger-test
    • 운영

      • 트리거 : build-github-trigger-prod
  • Firebase Hosting 배포

    GitHub Actions Workflow

    • 개발

      • workflow : Deploy to Firebase Hosting on merge DEV
    • 테스트

      • workflow : Deploy to Firebase Hosting on merge TEST
    • 운영

      • workflow : Deploy to Firebase Hosting on merge PROD

개발자 PC에서 직접 배포

  • GCP Cloud Run 배포

    • 개발

      yarn cloudbuild:submit:dev
    • 테스트

      yarn cloudbuild:submit:test
    • 운영

      yarn cloudbuild:submit:prod
  • Firebase Hosting 배포

    • [주의] Cloud Run 배포 완료 되었는지 확인 후 진행
    • 개발

      yarn firebase:deploy:dev
    • 테스트

      yarn firebase:deploy:test
    • 운영

      yarn firebase:deploy:prod








About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published