도커와 CI 환경 - 5

지원·2024년 3월 16일
0

Docker

목록 보기
5/7
post-custom-banner

이번에는 저번에 만들었던 소스 코드를 Gihub 에 먼저 배포를 하고, Travis CI 라는 곳에서 소스를 가져간 후에 그 곳에서 소스 코드가 잘 돌아가는지 Test를 한 후 만약 성공한다면 AWS 에 보내서 배포까지 해보자.

Github 에 소스 코드 올리기

  • git repo 만들고 git init -> git add . -> git commit -> git remote add origin -> git push
  • 이렇게 소스 코드를 github 에 올릴 수 있고 이 소스가 잘 작성된 코드인지 Travis CI 라는 곳에서 확인해 주기 위해서 Travis CI 에서 가져가 줘야 한다.

Travis CI

  • Travis CI 는 Github 에서 진행되는 오픈소스 프로젝트를 위한 지속적인 통합(Continuous Integration) 서비스이다.
  • 원래는 Ruby 언어만 지원했지만 현재는 대부분의 개발 언어를 지원한다.
  • Travis CI 를 이용하면 Github Repository 에 있는 프로젝트를 특정 이벤트에 따라 자동으로 테스트 , 빌드하거나 배포할 수 있다.

흐름

Local git -> Github -> Travis CI -> AWS
1. Local Git 에 있는 소스를 Github 저장소에 Push
2. Github Main 저장소에 소스가 Push 되면 Travis CI 에게 소스가 Push 되었다고 전달
3. Travis CI 는 업데이터된 소스를 Github 에서 가지고 온다.
4. Github 에서 가져온 소스의 테스트 코드를 실행
5. 테스트 코드 실행 후 테스트가 성공하면 AWS 같은 호스팅 사이트로 보내서 배포

Travis CI 이용 순서

  • Travis CI 에서 소스를 가져가야 하기 때문에 Github 와 연결을 해야한다.
  • 연결하기 위해서는 Travis CI 사이트로 가서 Github 로 로그인을 한다.
  • Settings 페이지로 가서 활성화 시킬 저장소를 찾고 활성화를 시킨다.
  • 활성화를 시키게 되면 해당 저장소의 소스가 변경될 때 마다 소스를 가져와서 테스트하고 배포하라고 알려준다.

지금까지는 Travis 에 가입하고 어떤 저장소를 관리할 것인지를 설정해줬다.

이제는 Github 에서 Travis CI 로 소스를 어떻게 전달 시킬 것이며 전달 받은 것을 어떻게 Test 하며 그 테스트가 성공했을 때 어떻게 AWS에 전달해서 배포를 할 것인지를 설정해야한다.

  • travis.yml 작성

즉 Docker 에서는 Dockerfile , docker-compose.yml 에서 무엇을 할지를 작성했다면 Travis CI 에서는 travis.yml 파일에서 해준다.

.travis.yml 파일 작성하기 (테스트까지)

  • Travis CI 를 이용해서 테스트 코드를 실행하고 애플리케이션을 배포까지 해줘야 한다.
  • 그러기 위해서는 travis.yml 파일을 작성해야 한다.
  1. 테스트를 수행하기 위한 준비
  • 도커 환경에서 리액트 앱을 실행하고 있기 떄문에 Travis CI 에서도 도커 환경 구성
  • 구성된 도커 환경에서 도커 파일을 이용해 도커 이미지 생성
  1. 테스트 수행하기
  • 어떻게 테스트를 수행할 것인지 설정
  1. AWS 로 배포
  • 어떻게 AWS 소스 코드를 배포할 것인지 설정
# .travis.yml
sudo: required	# 관리자 권한 갖기
language: generic	# 언어(플랫폼) 을 선택
services:	# 도커 환경 구성
  - docker

before_install:	# 스크립트를 실행할 수 있는 환경 구성
  - echo "start creating an image with dockerfile"
  - docker build -t supportkim/docker-react-app -f Dockerfile.dev .

script:		# 실행할 스크립트 (테스트 실행)
  - docker run -e CI=true supportkim/docker-react-app npm run test -- --coverage

after_success:	# 테스트 성공 후 할일
  - echo "Test success"
  • script 부분이 테스트를 하는 부분인데, 테스트를 하기 전에 도커 파일을 이용해서 이미지를 생성해야 한다.
  • 그래서 before_install 에서 build 를 해준다.
  • sciprt 에서 -e CI=true 설정을 하지 않으면 에러가 발생하기 때문에 꼭 넣어줘야 한다.
  • -- --coverage 는 테스트 한 것을 상세하게 볼 수 있도록 하는 옵션이다.

해당 소스 코드를 Github 에 다시 push 를 하면 Travis CI 가 yml 파일에 있는 것을 수행한다.

테스트는 성공했고, 이제 AWS 에 배포를 해보자.

AWS 알아보기

  • 리액트 앱을 배포하기 위해서 EC2 와 EB 를 사용할 것이다.

EC2 란?

  • Elastic Compute Cloud(EC2) 는 AWS 클라우드에서 확장식 컴퓨팅을 제공한다.
  • EC2 를 통해 원하는 만큼 가상 서버를 구축하고 보안 및 네트워크 구성과 스토리지 관리가 가능하다.
  • 요구 사항이나 갑작스러운 인기 증대 등 변동 사항에 따라 신속하게 규모를 확장하거나 축소할 수 있어 서버 트래픽 예측 필요성이 줄어든다.
  • 쉽게 말하면 한 대의 컴퓨터를 임대한다고 생각하면 되고, 그 컴퓨터에 OS 를 설치하고 웹 서비스를 위한 프로그램(웹서버 , DB) 을 설치해서 사용하면 된다.

EB 란?

  • Elastic BeanStalk(EB) 는 Apache , Nginx 같은 친숙한 서버에서 java , Node.js 및 Docker 와 함께 개발된 웹 응용 프로그램 및 서비스를 배포하고 확장하기 쉬운 서비스이다.
  • "환경" 을 구성하며 만들고 있는 소프트웨어를 업데이트할 때 마다 자동으로 이 환경을 관리해준다.
  • 즉 EC2 인스턴스들이나 데이터베이스 , Auto-Scaling Group , 로드 밸런서 , Security Group 와 같은 것들을 컨트롤을 한다.

원래는 그냥 EC2 에만 배포를 해도 되지만 이번에는 EB 라는 것도 이용해보자.

Elastic BeanStalk 환경 구성하기

  • Elastic BeanStalk 에서 애플리케이션 만들기

AWS 에서 EB Dashboard 에 들어가고 애플리케이션 이름을 적어주고 플랫폼에 현재 Docker 를 사용할 것 이기 때문에 Docker 를 지정하고 플랫폼 브랜치는 일반 Linux 로 하고 애플리케이션을 만들면 된다.

현재까지의 상황

  • 브라우저에서 요청이 들어오면 EB 안에 로드 밸런서가 해당 요청을 받고 EC2 인스턴스에 접근할 수 있도록 해준다.
  • 만약 트래픽이 많아진다면 EC2 인스턴스를 동적으로 몇 개 더 만들어주는데, 이런걸 자동으로 해주는게 EB 이다.

.travis.yml 파일 작성하기 (배포 부분)

  • 현재 travis.yml 에는 도커 이미지를 생성하고 어플을 실행하여 테스트 하는 부분만 있다.
  • 이제는 테스트에 성공한 소스를 AWS Elastic Beanstalk 에 자동으로 배포하는 부분을 travis 파일에 넣어주면 된다.
deploy: # 배포 관련된 설정
  provider: elasticbeanstalk 	# 외부 서비스 표시(s3,eb,firebase 등)
  
  region: ap-northeast-2		# 현재 사용하고 있는 AWS 의 물리적 장소
  
  app: docker-react-app			# 생성한 애플리케이션의 이름
  
  env: "DockerReactApp-env"		# eb 에 명시된 env 명
  
  bucket_name: "S3 bucket 이름"	# 해당 EB 을 위한 S3 버킷 이름
  
  bucket_path: "docker-react-app"	# 애플리케이션의 이름과 동일
  
  on:	# 어떤 브랜치에 푸시할 때 AWS 에 배포할 것인지를 설정
    branch: main
  • travis CI 의 내용이 바로 Elastic Beanstalk 에 가는게 아니라 travis CI 에서 파일을 압축하고 S3 에 보낸다.
  • 그렇기 떄문에 bucket_name 이 필요하다.
  • 하지만 우리는 S3 를 따로 생성한적이 없지만, Elastic Beanstalk 를 생성하면 S3 Bucket 도 자동적으로 생성된다.
  • 그래서 S3 Dashboard 에서 자동으로 생성된 버킷 이름을 가져오면 된다.

하지만 이렇게 아무런 인증 없이 Travis CI 에서 마음대로 AWS 에 파일을 전송할 수 없다.

이제는 Travis CI 가 AWS 에 접근할 수 있도록 하는 방법을 알아보자.

Travis CI 의 AWS 접근을 위한 API 생성

  • 현재까지는 travis CI 에서 AWS 에 어떤 파일을 전해줄것이며, AWS 에서 어떤 서비스를 이용할 것이며, 부수적인 설정들을 적어줬다.
  • 하지만 Travis CI 와 AWS 가 실질적으로 소통을 할 수 있게 인증하는 부분은 없다.
  • 그 인증 하는 부분을 알아보자.

소스 파일을 전달하기 위한 접근 요건

  • Github -> Travis CI -> AWS
  • Github -> Travis CI 부분은 Travis CI 로그인을 Github 으로 했기 때문에 연동이 됐다.
  • Travis CI -> AWS 는 AWS 에서 제공하는 액세스 키와 비밀 액세스 키를 travis.yml 파일에다가 적어주면 된다.

인증을 위해서는 API Key 가 필요한데, 어떻게 API Key 를 얻을 수 있을까?

  1. IAM(Identity and Access Management) USER 생성
  • IAM 은 AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 서비스
  • IAM을 사용하여 리소스를 사용하도록 인증 및 권한 부여된 대상을 제어한다.
  • 우리가 사용하고 있는 AWS 계정은 ROOT 사용자로 서비스 및 리소스에 대한 모든 접근 권한이 있는데, ROOT 사용자를 사용하는 방법은 보안적으로 바람직 하지 않기 떄문에 IAM 유저를 사용해야 한다.
  • IAM 사용자는 ROOT 사용자가 부여한 권한만 가지고 있을 수 있다.
  • IAM Dashboard 에 가서 IAM 을 만들 때 AdministatorAccess-AWSElasticBeanstalk 권한 추가한다.
  1. API 키를 Travis yml 파일에 적어주기
  • 1번 과정을 하게 되면 액세스 키 ID , 비밀 액세스 키가 주어진다.
  • 이때 직접 API 키를 travis.yml 파일에 넣게되면 문제가 된다.
  • travis.yml 은 github 에 올라가기 때문에 다른 사람들에게 유출될 수 있어서 travis.yml 에다가 올리면 안 되고 다른 곳에 적고 그것을 가져오는 형식으로 해야한다.
  • 위에서 말한 다른 곳은 Travis 웹사이트 해당 저장소 대쉬보드에 가면 more options -> settings 에서 아래를 보면 Environment Variables 에다가 넣어주면 된다.
  • NAME : AWS_ACCESS_KEY VALUE : 액세스 키 ID 넣고 ADD 버튼
  • NAME : AWS_SECRET_ACCESS_KEY VALUE : 비밀 액세스 키 넣고 ADD 버튼
deploy:
  provider: elasticbeanstalk
  region: ap-northeast-2
  app: docker-react-app
  env: "DockerReactApp-env"
  bucket_name: "S3 bucket 이름"
  bucket_path: "docker-react-app"
  on:
    branch: main
  access_key_id: $AWS_ACCESS_KEY
  secret_access_key: $AWS_SECRET_ACCESS_KEY
  • 위와 같이 적어주면 된다.

이렇게 Travis CI 가 AWS 에 접근할 수 있도록 만들어줬다.

git add . -> git commit -> git push 를 하게 되면 Travis CI 대시보드를 가보면 현재 push 한 소스 코드를 가지고 실행을 한다.

  • 그런후 EB 에 들어가보면 새로운 소스가 왔기 때문에 그 소스를 가지고 컨테이너를 실행하고 어플리케이션을 실행한다.

하지만 에러가 발생한다..

포트 맵핑을 하지 않아서 발생한 에러이다.

  • nginx 는 80 포트번호에서 실행되는데 80 번에 포트 맵핑이 되지 않아서 에러가 발생한다.
  • Github 에 Main branch 에 소스를 push 하면 자동으로 AWS 에 배포할 수 있게 하는것에 있어서 마지막 포트 매핑을 해야한다.
  • Dockerfile 에 EXPOSE 80 을 넣어줘서 포트 매핑 문제를 해결할 수 있다.
  • 완벽하게 배포가 되기 위해서 약간의 시간이 소요된다.

이제는 Github 에 Main 브랜치에 푸시를 하면 모든 프로세스가 한 번에 돌아가고 앱이 배포가 된다.

작업에서 환경 종료를 눌러야 과금이 생기지 않는다..!

Travis CI 에서 Github Action 으로 교체하기 (처음부터 끝까지)

  • Github Action 으로 CI/CD 를 구축해보자.
  1. npx create-react-app ./
  2. 필요한 Dockerfile 작성
# .dockerignore
package-lock.json
node_modules

# Dockerfile.dev
FROM node:16-alpine

WORKDIR '/app'

COPY package.json .
RUN npm install

COPY . .

CMD ["npm" , "run" , "start"]

# Dockerfile
FROM node:16-alpine as builder

WORKDIR '/app'

COPY package.json .
RUN npm install
COPY . .
RUN npm run build

FROM nginx
COPY --from=builder /app/build /usr/share/nginx/html
# docker-compose-dev.yml
version: '3' # 도커 컴포즈 버전
services:   # 이곳에 실행하려는 컨테이너들을 정의
  react:    # 컨테이너 이름
    build:  # 현 디렉토리에 있는 Dockerfile 사용
      context: . # 도커 이미지를 구성하기 위한 파일과 폴더들이 있는 위치 (현재는 Dockerfile.dev 와 같은 경로에 있기 때문에 . 으로 명시)
      dockerfile: Dockerfile.dev # 도커 파일 어떤 것인지 지정
    ports: # 포트 매핑 -> 로컬 포트 : 컨테이너 포트
    - "3000:3000"
    volumes: # 로컬 머신에 있는 파일들 맵핑
      - /usr/src/app/node_modules
      - ./:/usr/src/app
    stdin_open: true # 리액트 앱을 끌때 필요 (버그 수정)
  tests:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - /usr/src/app/node_modules
      - ./:/usr/src/app
    command: ["npm" , "run" , "test"]

# docker-compose.yml
version: "3"
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "80:80"
  1. IAM 설정
    AWSElasticBeanstalkMulticontainerDocker
    AWSElasticBeanstalkWebTier
    AWSElasticBeanstalkWorkerTier

  2. ElasticBeanstalk 환경 만들기

  • 플랫폼에서 Docker , 브랜치는 Linux2
  • 서비스 액세스에서 새 서비스 역할 생성 및 사용으로 하고 EC2 인스턴스 프로파일에서 3번에서 설정한 역할로 지정해주면 된다.
  1. IAM 유저 생성
  • 직접 정책 연결 선택
  • AdministratorAccess-AWSElasticBeanstalk 권한 정책 선택후 유저 생성
  • 생성한 유저에 들어가서 아래로 내리다 보면 액세스 키가 있고 여기서 액세스 키를 만들면 된다. (보안 자격 증명 , 사용 사례는 CLI)
  • 액세스 키와 시크릿 키 보관

react 앱을 github 에 올려서 자동으로 테스트를 하고 EB 를 통해 배포를 하도록 한다.

  1. Github 저장소 생성
  • git init -> git add -> git commit -> git remote add origin -> git push
  1. Travis CI 가 아닌 Github Action 사용
  • react 앱 안에 .github/workflows/deploy.yaml 파일을 만들고 아래와 같이 작성
name: Deploy Frontend
# Main 브랜치에 push 를 했을때만 아래에 있든 task 를 실행
on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      # docker Login
      - run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
      # Dockerfile.dev 로 build
      - run: docker build -t supportkim/react-test -f Dockerfile.dev .
      
      # 위에서 만든 image 로 run (test)
      - run: docker run -e CI=true supportkim/react-test npm test
      - name: Generate deployment package
        run: zip -r deploy.zip . -x '*.git*'

		# EB 에 배포
      - name: Deploy to EB
        uses: einaregilsson/beanstalk-deploy@v18
        # 필요한 accessKey , secretKey 넣어주기
        with:  
          aws_access_key: ${{ secrets.AWS_ACCESS_KEY }}
          aws_secret_key: ${{ secrets.AWS_SECRET_KEY }}
          application_name: react-docker-gh-test
          environment_name: React-docker-gh-test-env 
          existing_bucket_name: elasticbeanstalk-ap-northeast-2-637423586273
          region: ap-northeast-2
          version_label: ${{ github.sha }}
          deployment_package: deploy.zip
  • Docker 의 정보와 AWS_KEY 에 대한 정보를 넣어줘야 한다.
  • Github 에서 해당 저장소에서 Settings -> Security -> Secrets and Variables -> Actions -> New Repository Secret 에다가 하나씩 넣어주면 된다.
  • DOCKER_USERNAME , DOCKER_PASSWORD , AWS_ACCESS_KEY , AWS_SECRET_KEY

이렇게 설정하고 나고 push 를 하면 github 에 올라가게 되고 바로 Github Action 을 통해서 테스트와 배포가 자동으로 이루어진다.

  • 저장소에서 Action 에 들어가보면 진행 과정도 볼 수 있다.

모든 과정이 끝나고 나면 AWS 의 Elastic Beanstalk Dashboard 가보면 환경을 업데이트가 된다.

이제는 Main 브랜치에 push 하기만 하면 알아서 테스트 후 배포까지 된다.

참고자료

profile
덕업일치
post-custom-banner

0개의 댓글