치욕의 젠킨스와 s3, codedeploy, docker hub 같은 것들로 배포가 될 듯 말 듯해 끙끙앓았다.
😡이것 저것 해보며 내린 결론.
EC2 프리티어는 너무 느리고 나약하다.
그들은 나의 프로젝트를 감당할 자질이 없다고 판단, test용으로 방금 만든 따끈따끈한 react 프로젝트를 배포해봤다. 바로 성공.
물론 같은 방법으로 내가 공들여 만들어놓은 프로젝트를 배포했을 땐 브라우저에서 연결시간이 오래걸린다하고, ec2 가 또 먹통이 되었다.
나약한 놈... 그렇게 나약해선 순양을 가질 수 없다.
사용될 도구들 : nodejs 프로젝트
, AWS EC2 linux
, Github Actions
, Github Runners
, EC2 에 설치될 docker
전체 플로우는 Actions 에 짜고, Runner 가 EC2 와 연결되어 ghrc 에 있는 docker 파일을 돌릴 거다.
시작해봅시다.
AWS EC2 linux 만드시고,
ec2-user
로 접속해서,
sudo yum update
로 EC2 업데이트하고
sudo yum install docker
로 docker 설치하고
sudo usermod -aG docker $USER
로 docker 를 추가하고
exit
로 껐다가
다시 켜서
docker version
으로 docker 설치 확인하고
sudo systemctl start docker
로 docker 시작시키고
sudo systemctl status docker
docker 가 잘 켜졌나 확인하자.
일단 AWS EC2 의 준비는 끝
보고 오자 Dockerfile 만들기
이번에도 간단하게 진행해보자
프로젝트 최상위 폴더에 Dockerfile
을 만든다.
.dockerignore
도 만든다.
일단 .dockerignore
에 node_modules/
를 추가해놓는다.
Dockerfile
에 들어가는 게 중요하다. 위의 링크에도 있지만,
FROM node:18.10.0
// 나에게 맞는 node 버전을 적어준다.
RUN mkdir -p /app
WORKDIR /app
ADD . /app
// mkdir 로 /app 폴더를 만들어서
// 경로를 /app 으로 이동한 뒤에
// ADD 로 모든 파일을 /app 으로 복사한다
RUN npm install
// yarn 이면 yarn install 하면 되겠지? yarn build 인가?
// 이 명령어가 틀리면 Actions 가 돌아가다 에러가 발생하니 에러가 나면 에러부분을 확인해보면서 고쳐주면 된다.
ENV HOST 0.0.0.0
EXPOSE 3000
// 모든 ip 에서 접근 가능
// 3000 포트 개방 포트 여러개를 개방하려면, EXPOSE 3000 80 이렇게 띄워서 써주면 된다.
CMD ["npm", "start"]
// CMD 는 여러개 적을 수도 있지만 마지막에 작성된 CMD 만 작동한다.
// 컨테이너에서 작동될 명령을 입력한다. yarn 이면 yarn start 를 적어주면 됨
오케. 끝
Github token 을 만들어서 넣어줘야한다.
우리의 배포 친구들이 우리 github 계정으로 ghcr.io 에 접근해서 docker 이미지를 만들고 build하고 해야하니
Developer settings
Personal access tokens
에 Tokens(classic)
new token (classic)
감사합니다.
인사하고 애지중지 복사해놓자.settings
로 가자깔끔한 너구리의 솜사탕처럼 사라질 수도 있기 때문에 조심스럽지만 빠르게
Secrets
의 Actions
를 열어 New repository secret
을 열어 붙여넣어준다.
이름은 GHCR_TOKEN
으로 하자. 다른이름으로 해도 상관없고 소문자로써도 대문자가 된다.
Actions workflow yml script 에서 사용할 거기 때문에 귀찮게 왔다갔다 확인하기 싫으면 이름을 생각해놓자.
AWS EC2 에 Runners 를 설치해줄 거다.
1.Settings
- Actions
- Runners
Linux
Download
란의 코드를 차례로 복사해서 EC2 에 입력해 설치해준다. 세번째 Optional
은 안해도 된다.Configure
란의 첫번째를 복사해서 붙여넣으면./run.sh
는 하면 바로 끝날 텐데 우리는 백그라운드로 계속 실행시켜놓고 싶으므로nohup ./run.sh &
라고 하자Github repo 에서 Actions
을 클릭하고 workflow yourself
로 커스텀해보자.
코드를 적는다
name: Deploy with Docker
# 내가 만드는 이름이다 뭐든 상관없다
on:
push:
branches: [ main ]
# 무슨 브랜치가 업데이트 될 때 Actions 를 작동시킬지 적는다.
# develop 브랜치로 개발하며 완료되면 main 에 머지해 Actions 를 작동시키면 조금 더 안전하겠지.
# 여러개 적어도 된다.
env:
DOCKER_IMAGE: ghcr.io/${{ github.actor }}/chargingpot
VERSION: ${{ github.sha }}
NAME: superman
# Docker image 를 ghcr.io 에 올릴 때 우리의github이름/이미지이름 으로 저장한다. 이미지이름을 정해주면 된다.
# Docker image 의 이름을 superman 이라고 해놓은 것. 이름 뭐할지 정하면 된다.
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup 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 }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to ghcr
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_TOKEN }}
# 우리가 방금 복사해서 setting secrets 에 붙여줬던 token 이다. 이름을 기억해 넣어주자.
# 우리의 ghcr.io 에 접근하기 위함이다.
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: ${{ env.DOCKER_IMAGE }}:latest
deploy:
needs: build
name: Deploy
runs-on: [ self-hosted, label-superman ]
# label-superman 라는 이름으로 AWS EC2 가 Runner 를 작동시킬 때 사용했던 그 label
steps:
- name: Login to ghcr
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_TOKEN }}
- name: Docker run
run: |
docker stop ${{ env.NAME }} && docker rm ${{ env.NAME }} && docker rmi ${{ env.DOCKER_IMAGE }}:latest
docker run -d -p 3000:3000 --name superman --restart always ${{ env.DOCKER_IMAGE }}:latest
# 첫 줄
# 먼저 진행되고 있던 docker 를 stop(멈추고), rm 로 docker 컨테이너를 지우고, rmi 로 docker 이미지를 지운다.
# 새롭게 build 된 docker 를 사용하기 위함이다.
# 두번째 줄
# -d : 백그라운드로
# -p : 포트 번호 3000번에서 3000번으로 접근
# --name : docker 이미지 이름을 superman 로 할거다. 이게 나중에 위에 적은거랑 같아야하는데 왜냐면 첫 줄이랑 같아야 나중에 지워지니까. 확인하자.
yml 이 완성되면 commit 하자. 알아서 Actions 가 돌아가며
이렇게 완성될거다.
완성되면 우린 바로 접속해볼 수 있다. EC2 IP:3000
에 접속하면
물론 프로젝트가 무겁다면 곧바로
이GR하다가 뻗어버릴 수도 있다.
나약한 놈.
지금 우리가 만든 workflow 와 ec2 는 우리가 main 브랜치가 업데이트 할 때마다 새롭게 돌아가며 docker 이미지를 지우고 새롭게 만들어 다시 만들어 줄거다.
천천히 프로젝트를 완성시켜가보자.
내가 공들여 만들어 놓은 프로젝트를 배포할 수 없다면 이 방법 또한 뭔가 문제가 있는 거지.
새로운 방법을 끝까지 찾아내서 배포해버리고 만다.
다음달에 하자...ㅎ
안녕 2022년
안녕하세요!
글 아주 친절해서 너무 편하게 잘 봤습니다.
궁금한게 있는데요.
마지막 yml 파일에서 build and push 쪽에서
Error: buildx failed with: ERROR: failed to solve: failed to read dockerfile: open /tmp/buildkit-mount892762416/Dockerfile: no such file or directory
이런 에러가 나오거든여.
도커 파일을 못찾는것 같은데 builder의 ${{ steps.buildx.outputs.name }} 여기에 따로 어떤 값을 넣어야 하나요..?