[PreProject] [CI/CD] Github Action 사용할 때 Docker 환경변수 설정

NtoZ·2023년 8월 22일
1

PreProject

목록 보기
11/12

개요

환경 구성

  • EC2 환경에서 Docker를 이용하여 백그라운드에서 자바 컨테이너를 실행할 수 있다.
  • Pre-project 단계에서 우리는 다음과 같은 CI/CD 환경을 구성하였다.
    • Github Action, workflow
    • Docker
    • AWS EC2 (ubuntu)

Trouble

  • 문제는 AWS EC2 환경에서 환경변수를 여러 차례 설정해보았지만, 정작 docker에서 실행하는 jar 파일에 환경변수가 전달되지 않는 문제가 발생했다.

    • sudo vi /etc/environment : 환경변수 편집 프로그램 열기 (환경변수 작성)
    • source /etc/environment : 환경변수 적용
    • env : 현재 설정되어 있는 환경변수 확인
  • env정상적으로 저장되어 있는 환경변수를 ec2에서 확인했음에도 불구하고 docker 컨테이너 내부에서 환경변수가 설정되지 않았기 때문JWT_SECRET_KEY 누락 등으로 docker 컨테이너의 java .jar 파일이 정상적으로 실행되지 않았던 것이다.

  • 💡 Github Action에서 EC2 내부로 환경변수를 전달하기 위해 다음과 같은 과정을 거쳐야 한다.


Github Action

Github Secrets에 변수 등록

  • 환경 변수 등록

  • 파란색 변수는 github action workflows/server.yml 파일에서 uses 모듈을 사용하기 위해 필요한 변수들이다.

  • 또, 빨간색 변수는 application.yml에 등록되어 Docker 컨테이너에서 스프링 애플리케이션을 시작하기 위해 필요한 환경변수들로 Dockerfile로 전달해야하는 변수들이다.


Github Action

  • 프로젝트 최상단 디렉토리에 위치해 있는 Github 관련 파일들

  • workflows/server.yml

name: Server CI/CD

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

    env: #⭐ docker가 실행할 애플리케이션의 yml 설정 파일 환경변수를 env로 설정하며, 실제 값은 Github 레포 secrets에서 가져옴. 
      G_CLIENT_ID: ${{secrets.G_CLIENT_ID}}
      G_CLIENT_SECRET: ${{secrets.G_CLIENT_SECRET}}
      JWT_SECRET_KEY: ${{secrets.JWT_SECRET_KEY}}
      MYSQL_ID: ${{secrets.MYSQL_ID}}
      MYSQL_PASSWORD: ${{secrets.MYSQL_PASSWORD}}
      ADMIN_EMAIL: ${{secrets.ADMIN_EMAIL}}
      working-directory: ./be/stackoverflow-be

    steps:
      - uses: actions/checkout@v2
      - name: Set up JDK 11
        uses: actions/setup-java@v2
        with:
          java-version: '11'
          distribution: 'zulu'

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew
        working-directory: ${{ env.working-directory }}

      - name: Build with Gradle
        run: ./gradlew build
        working-directory: ${{ env.working-directory }}

      - name: Docker build
        run: |
          docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} -p ${{ secrets.DOCKER_HUB_PASSWORD }}
          docker build --build-arg G_CLIENT_ID="${{env.G_CLIENT_ID}}" \
          --build-arg G_CLIENT_SECRET="${{env.G_CLIENT_SECRET}}" \
          --build-arg JWT_SECRET_KEY="${{env.JWT_SECRET_KEY}}" \
          --build-arg MYSQL_ID="${{env.MYSQL_ID}}" \
          --build-arg MYSQL_PASSWORD="${{env.MYSQL_PASSWORD}}" \
          --build-arg ADMIN_EMAIL="${{env.ADMIN_EMAIL}}" \
          -t 7elenven-cicd . 
          docker tag 7elenven-cicd leest/7eleven-cicd:${GITHUB_SHA::7}
          docker push leest/7eleven-cicd:${GITHUB_SHA::7}
        working-directory: ${{ env.working-directory }}

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2

      - name: SSH Connection and Deploy to Server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.AWS_SSH_HOST }}  # ipv4
          username: ${{ secrets.AWS_SSH_USERNAME }} # ubuntu
          key: ${{ secrets.AWS_SSH_KEY }} #
#          port: ${{ secrets.AWS_SSH_PORT }} #
          envs: GITHUB_SHA
          script: |
            sudo docker rm -f server
            sudo docker pull leest/7eleven-cicd:${GITHUB_SHA::7}
            sudo docker tag leest/7eleven-cicd:${GITHUB_SHA::7} 7eleven-cicd
            # ⭐ 타임존을 서울로 설정해서 run하지 않으면 docker 자체 시간으로 애플리케이션을 구동함
            sudo docker run -d --name server -e TZ=Asia/Seoul -p 8080:8080 7eleven-cicd

❗❗❗오류 주의

yml 여러 줄을 동시에 사용할 때는 중간에 # 주석을 넣지 않아야 한다.

  • ⭐⭐⭐ 단, yml 에서 | , \ 등으로 여러 줄을 동시에 사용할 때는 그 사이에 주석을 넣지 않아야 한다. 아예 workflow 동작이 시작하기도 전에 구문 오류를 맛 볼 것이다.
          docker build --build-arg G_CLIENT_ID="${{env.G_CLIENT_ID}}" \
          --build-arg G_CLIENT_SECRET="${{env.G_CLIENT_SECRET}}" \
          --build-arg JWT_SECRET_KEY="${{env.JWT_SECRET_KEY}}" \
#          --build-arg MYSQL_ID="${{env.MYSQL_ID}}" \ # ⭐⭐ 오류발생!!
          --build-arg MYSQL_PASSWORD="${{env.MYSQL_PASSWORD}}" \
          --build-arg ADMIN_EMAIL="${{env.ADMIN_EMAIL}}" \

build 파일 자체를 .gitignore에 넣지 않는다!

  • ⭐⭐⭐ 또한, build 설정폴더 자체를 gitignore하지 않아야 한다. 해당 설정 파일이 없으면 깃허브 액션에서 CI/CD 호스팅을 할 때 build 설정을 인식하지 못하기 때문에 gradlew 명령어를 인식하지 못한다.

Dockerfile

  • 실제 be 프로젝트 환경 안에 존재하는 Dockerfile 위치

  • Dockerfile

# (1) base-image
FROM openjdk:11

# ⭐ 'ARG' 예약어를 통해 인자로 전달 받아야 한다.
ARG G_CLIENT_ID \
    G_CLIENT_SECRET \
    JWT_SECRET_KEY \
    MYSQL_ID \
    MYSQL_PASSWORD \
    ADMIN_EMAIL

# ⭐ 'ENV' 예약어를 통해 전달받은 값을 실제 값과 매칭시켜야 한다.
ENV G_CLIENT_ID=${G_CLIENT_ID} \
    G_CLIENT_SECRET=${G_CLIENT_SECRET} \
    JWT_SECRET_KEY=${JWT_SECRET_KEY} \
    MYSQL_ID=${MYSQL_ID} \
    MYSQL_PASSWORD=${MYSQL_PASSWORD} \
    ADMIN_EMAIL=${ADMIN_EMAIL}

# (2) COPY에서 사용될 경로 변수
ARG JAR_FILE=build/libs/*-SNAPSHOT.jar

# (3) jar 빌드 파일을 도커 컨테이너로 복사
COPY ${JAR_FILE} app.jar

# (4) jar 파일 실행
ENTRYPOINT ["java","-jar","/app.jar"]

결과

  • 구동이 잘 되는 모습을 볼 수 있다.
profile
9에서 0으로, 백엔드 개발블로그

0개의 댓글