[항해 99] ec2와 도커 허브 사용 cd 구축기

Featured image

프로젝트에서 cd역할을 맡아 Github Action을 사용한 docker를 사용해 ec2자동 배포를 하려고 한다.

기술 선택 이유

  1. 깃허브액션 깃허브 액션이란 깃허브에서 제공하는 CI/CD 파이프라인 자동화 플랫폼. 깃허브 액션은 2022년 개인 사용자가 가장 선호하는 툴로 선정.

  2. 도커 가상화 컨테이너 기술로 대부분의 기업에서 사용 환경의 통일화를 위해 사용

  3. EC2 aws의 가상 인스턴스

작동 순서

전제조건:깃허브 레포지토리의 메인에 푸시가 될때

  1. 워크플로우가 실행되는 러너의 파일 시스템에 현재 리포지토리의 코드를 복사
  2. 도커허브에 로그인
  3. 현재 도커파일과 env파일을 사용해 도커 이미지 빌드
  4. 빌드한 이미지 도커허브에 push
  5. pem키를 사용해 ec2에 접속
  6. ec2 레포지토리에 도커허브에서 pull받기
  7. 도커 런
  8. 사용하지 않는 컨테이너 지우기

설정

  1. 도커 레포지토리만들기 도커허브의 회원가입 후 로그인-> 레포지토리 만들기. 이때 사용했던 유저이름, 비밀번호 기억하기(나중에 깃액션에서 사용)

  2. Ec2인스턴스에 도커 설치하기 필요한 패키지 설치: ``` bash sudo apt-get update sudo apt-get install
    apt-transport-https
    ca-certificates
    curl
    software-properties-common

Docker의 공식 GPG 키 추가
``` bash
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

Docker 리포지토리 추가

sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"

Docker CE 설치

sudo apt-get update
sudo apt-get install docker-ce

Docker 설치 확인

docker --version

사용자에 도커 권한주기 참고

sudo groupadd docker
sudo usermod -aG docker $USER
sudo newgrp docker

한줄씩 치고 ec2나갔다가 다시 들어오기.

깃허브 시크릿

시크릿에 저장해야 할것 정리

  1. DATABASE_HOST
  2. DATABASE_NAME
  3. DATABASE_PASSWORD
  4. DATABASE_PORT
  5. DATABASE_URL
  6. DATABASE_USERNAME
  7. PORT
  8. JWT_SECRET .env파일에서 쓰는 값들 -> 도커 이미지를 만들어 push할때 사용!

9.DOCKER_REPO: 저장할 도커레포지토리 자신의 도커 허브 닉네임으로 하기 . 레포지토리 만들때 아마 자기 이름이 앞에 들어가고 뒤에 만든 이름 들어감 soi/trello 이렇게.

  1. DOCKER_TOKEN: 이름은 토큰이지만 도커 비밀번호 들어감
  2. DOCKER_USERNAME: 도커허브의 유저 네임
  3. EC2_HOST: ec2의 퍼블릭 ip 주소
  4. EC2_USERNAME: 인스턴스에서 whoami치면 알 수 있음 ubuntu의 기본값 ubuntu 14.REMOTE_PRIVATE_KEY: pem 파일의 값 aws의 ec2들어가서 왼쪽 보면 키페어 존재 키페어 들어가면 작업 누르면 키페어 가져오기 있음 여기가서 자기한테 있는 키페어 선택하면 값이 보임 처음부터 끝까지 전부 넣어야 함

도커 파일

각 명령어의 의미는 [이미지 명령어 정리] (https://velog.io/@soijeongg/Dockerfile-%EC%9D%B4%EB%AF%B8%EC%A7%80%EB%A7%8C%EB%93%A4%EA%B8%B0) 참고

# 부모 이미지 지정
FROM node:20.11.1
# app 디렉토리 생성

# ARG로 빌드 시점 변수를 선언
ARG DATABASE_URL
ARG PORT
ARG DATABASE_HOST
ARG DATABASE_PORT
ARG DATABASE_NAME
ARG DATABASE_USERNAME
ARG DATABASE_PASSWORD
ARG JWT_SECRET
# ENV로 런타임 환경 변수를 설정
ENV DATABASE_URL=$DATABASE_URL \
    PORT=$PORT \
    DATABASE_HOST=$DATABASE_HOST \
    DATABASE_PORT=$DATABASE_PORT \
    DATABASE_NAME=$DATABASE_NAME \
    DATABASE_USERNAME=$DATABASE_USERNAME \
    DATABASE_PASSWORD=$DATABASE_PASSWORD \
    JWT_SECRET=$JWT_SECRET

LABEL creator="no6@trello"
LABEL version="1.0.0"



#Docker 이미지 내부에서 RUN, CMD, ENTRYPOINT의 명령이 실행될 디렉터리를 설정합니다.

WORKDIR /app

# 외부 패키지 설치를 위해 package.json과 yarn.lock 파일 복사
COPY package.json .
COPY yarn.lock .

# 패키지 설치
RUN  yarn install

# 나머지 모두 복사
COPY . .
# 현재 디렉터리에 있는 파일들을 이미지 내부 /app 디렉터리에 추가함

ADD     . /app
RUN yarn prisma generate
# 하기 포트를 외부로 노출합니다.


CMD [ "yarn","dev" ]

git action 파일

name: Deploy to EC2

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Log in to Docker Hub
        uses: docker/login-action@v2
        with:
          username: $
          password: $
      - name: Build and push Docker image
        run: |
          docker build \
            --build-arg DATABASE_URL=$ \
            --build-arg PORT=$ \
            --build-arg DATABASE_HOST=$ \
            --build-arg DATABASE_PORT=$ \
            --build-arg DATABASE_NAME=$ \
            --build-arg DATABASE_USERNAME=$ \
            --build-arg DATABASE_PASSWORD=$ \
            --build-arg JWT_SECRET=$ \
            -t $/trello .
          docker push $/trello

      - name: SSH into EC2 instance and restart Docker container
        uses: appleboy/ssh-action@master

        with:
          key: $
          host: $
          username: $

          port: 22
          script: |
            sudo  docker stop trello
            sudo docker rm trello
            sudo docker pull $/trello
            docker run -d --name trello -p 3000:3000  --env-file .env $/trello
            docker system prune -a

에러

혹시 아무 문제 없는데 ssh에 timeout이 뜬다. 인스턴스 보고 cpu확인-> 너무 많이 차면 그냥 버리고 새로 만들어야 함.

ec2인증실패-> 호스트 아이피, rsa키 맞는지. 순서가 키, 호스트, 유저네임인지 확인.

참고

https://github.com/occidere/TIL/issues/116 https://haengsin.tistory.com/128