이 글은
DolphaGo 님 블로그 글
soosungp33 님 벨로그 글
을 직접 제가 작성하며 겪은 시행착오를 바탕으로 재구성한 글입니다.
Continuous Integration / Continuous Deploy 의 약어로
이 글은 devOps 개발자분들 처럼 AWESOME
하신 분들을 위한 글이 아닌,
이제 막 Vue 또는 React 를 통해 프로젝트를 완성하신 프론트엔드 개발자분들이 배포를 쉽게 하기 위한 글입니다.
S3 또는 github page를 이용해서 배포하는 방법이 아닌,
Dockerfile를 직접 작성해서
Front Container를 띄우는 작업을
Github Action을 사용해 자동화 하는 일련의 과정을 글로 담아보려 합니다.
😥 왜 S3 와 github page를 통해 배포하시지 않나요?
프론트 코드를 빌드해 배포하는 것이 주된 목적이 아닌,
원격 서버에 front 컨테이너를 띄우는 일련의 작업을
CI/CD 구축하는 방법론에 대한 글이라고 보시면 더 좋을 것 같습니다!
사실 위 작업은 Jenkins 라는 툴을 사용하면 훨씬 더 빠르고 편하게 작업 할 수 있습니다.
하지만 제가 느끼기에는 Jenkins는 진입장벽이 그렇게 낮은 편이 아니라 생각하기도 하고(저의 견해입니다.)
Github Action은 쓰면 쓸 수록 편하다는 생각이 들어서
이번에 프론트 컨테이너 자동 빌드 과정 구축을 Github Aciton 을 통해 작업해 보았습니다.
🔥 지금 시작합니다!
github 에서 먼저 작업해주셔야 하는 것들이 있습니다.
https://github.com/settings/tokens 접속하셔서
위 사진에서 보이는
Generate new token 버튼을 눌러줍니다.
Expiration 을 No expiration
으로 설정해주면 평생 만료가 안 된다고 경고 한 번 해줍니다.
저는 귀찮아서
No expiration
으로 설정한 것이지 필수 사항은 아닙니다!
그 다음
repo, workflow, write:packages, delete:packages 들을 모두 체크해줍니다.
화면 하단에 Generate Token
버튼을 누르면
이런 화면이 뜨는데 저 토큰은 한 번만 조회가 가능해서 바로 복사해서 메모장이나 다른 곳에 옮겨 놓는 것이 좋습니다.
https://github.com/{your-github-user-name}/{your-repository-name}/settings/secrets/actions
접속하시면
New repository secret
버튼이 있을겁니다.
💡 Secret ?
Github에서 타인에게 노출되어선 안 되는 환경변수들을 안전하게 보관하는 방법입니다.
대게 API Key 나 Token 같은 정보를 담아 사용합니다.
시크릿_이름
을 잘 기억해주시고
Add secret 을 해주시면 당장의 Github Setting 은 끝입니다!
지금 저는 막 만든 따끈따끈한 Vue 프로젝트가 있습니다.
폴더 구조가 어떤 식으로 되어 있는지 한 번 보시죠
다른 폴더 구조는 신경 쓰지 않으셔도 됩니다.
가장 중요한 것은
위 파일들을 직접 만들어가면서
우선 .github 폴더를 최상위 경로에 만들어줍니다.
💡 .github 폴더가 뭐죠?
깃허브에서 사용되는 일련의 작업들을 모아놓은 폴더입니다.
예를 들면 ISSUE_TEMPLATE/ 폴더 안에 있는 md 파일은
해당 repository 에 issue 를 작성 할 때 자동으로 템플릿을 만들어줍니다.
Github Action에 사용되는 파일은
workflows 라는 폴더 안에 .yml
확장자를 이용해 작성해주시면 됩니다.
.yml
확장자는 띄어쓰기를 통해 계층 구조가 나뉘기 때문에 이 점을 유념하셔야 합니다.
또한 이 글에서는 Github Action 이 어떻게 돌아가는지,
workflow yml 파일을 어떻게 작성하는지를 깊게 다루지 않습니다.
name: CI/CD Docker # 아무렇게나 지으셔도 됩니다. Action의 역할에 맞는 이름을 지어주시면 됩니다.
on:
push:
branches: [master] # master branch 에 push 될 때마다 라는 뜻입니다.
env:
DOCKER_IMAGE: ghcr.io/${{ github.actor }}/t-our-data-client # ${{}} 은 변수입니다. 본인의 user-name 이 들어갑니다.
VERSION: ${{ github.sha }} # 정확히 뭔 값인지 모르는데 매번 다른 값이 들어가는 걸로 이해했습니다.
NAME: tour_cicd # 제가 임의로 지은 환경변수 이름입니다. 어디서 사용되는지는 모르겠습니다...
jobs:
build: # build 라는 작업을 할거고
name: Build # 이름은 Build 야
runs-on: ubuntu-latest # 우분투 최신 버전에서 돌아가게 해줘
steps: # 다음과 같은 순서로 작업해줘
- name: Check out source code
uses: actions/checkout@v2 # 내 repo 에서 코드 다 가져와
- name: Set up docker buildx
id: buildx
uses: docker/setup-buildx-action@v1
- name: Cache docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ env.VERSION }} # runner 설정에서 읽어들일거에요.
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to ghcr
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.아까적은_Seceret_이름 }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
builder: ${{ steps.buildx.outputs.name }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ env.DOCKER_IMAGE }}:${{ env.VERSION }}
deploy:
needs: build
name: Deploy
runs-on: self-hosted # 이렇게 적어줘야 되더라구요
steps:
- name: Login to ghcr
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.아까적은_Seceret_이름 }}
- name: Docker run
run: |
docker ps -q --filter "name=t-our-data-client" | grep -q . && docker stop t-our-data-client && docker rm -fv t-our-data-client
docker run -itd -p 8081:8081 --name data-client --restart always ${{ env.DOCKER_IMAGE }}:${{ env.VERSION }}
저도 위 코드 이해하는 데 시간이 많이 걸렸습니다... 하하... 😂
사실 그대로 복사 붙여넣기 하고 몇 줄만 바꿔주시면 돌아는 갈 겁니다.
제목 그대로 아까 작성한 아까적은 Seceret 이름 을 그대로 적어주시면 됩니다.
💡 ghcr.io 를 직접 들어가서 둘러보시면 약간 뭐하는 곳인지 감이 오실 수 있으실텐데
쉽게 설명하면 약간 패키지 배포하는 곳이라고 보면 될 것 같다.docker image 를 커스텀해서 배포하는 곳이 docker 에게 docker hub 라면
github 는 npm이든 Maven 이든 Docker 든 패키지 들을 여기에 업로드 해서 관리할 수 있게 해주는 솔루션이다.개인이 사용하기엔 무료 플랜으로 충분해보이는 듯하다.
env:
DOCKER_IMAGE: ghcr.io/${{ github.actor }}/image-name
따라서 이 코드는 ghcr.io 에 업로드 될 나만의 커스텀 도커 이미지의 이름을 적는 곳이라고 보면 됩니다.
💡 github.actor 변수는 action을 동작시킨 user의 user-name이 들어갑니다.
제 예전 user-name 은Minsoo-web
이었습니다.
도커 이미지 네이밍 규칙에 대문자는 사용 할 수 없기에
제 user-name 을 변경했습니다..................... R.I.P🙏
run: |
docker ps -q --filter "name=컨테이너_이름" | grep -q . && docker stop 컨테이너_이름 && docker rm -fv 컨테이너_이름
docker run -itd -p 8081:8081 --name 컨테이너_이름 --restart always ${{ env.DOCKER_IMAGE }}:${{ env.VERSION }}
우선 |
은 줄바꿈 처리입니다.
run 블록 안의 코드들은 모두 실행 명령문들입니다.
윗 줄부터 차례대로 실행되며 실행도중 error 가 발생하게 되면
action flow 전체가 멈추게 됩니다.
컨테이너_이름
이라고 되어있는 부분을 본인이 만들고자 하는 컨테이너 이름으로 지어주시면 됩니다.
코드의 내용은
컨테이너_이름
이란 이름으로 돌아가고 있는 컨테이너가 있으면 멈추고, 삭제시켜그리고 환경변수에 등록된 도커 이미지를 가지고 8081 포트를 포워딩해서
백그라운드로 돌아가는 컨테이너를 띄워 그 컨테이너 이름은
컨테이너_이름
이야.
도커를 잘 모르시는 분들은 이게 뭐지 싶어서 이쯤 그만 두고 싶다는 생각이 드실 것 같습니다.
도커 명령어는 다음 포스팅에 조금 더 자세히 설명하는 것으로 이어가겠습니다.
🙇♂️질문과 오타 수정 및 지적은 언제나 열려있습니다!🙇♂️
감사합니다.