GithubAction 사용 정리
- 순서
- AWS EC2 서버 생성
- EC2 서버에서 프로그램 실행 환경 조성
- 깃허브 액션 파일 생성
- 실행
(1) AWS EC2 서버 생성
- 설정
- Ubuntu 선택
- t3.small 선택
- 키 페어(로그인) 설정
- 방화벽
- 인터넷에서 HTTPS 트래픽 허용
- 인터넷에서 HTTP 트래픽 허용
- 구매 옵션
- 스팟 인스턴스
- 인바운드 규칙 편집
- 8080 포트 열기
(2) EC2 서버에서 프로그램 실행 환경 조성
- 순서
- EC2 서버 접속
- EC2 서버에 도커 설치
- EC2 서버에 도커 DB(MySQL) 이미지 다운 및 컨테이너 실행
(2-1) EC2 서버 접속
(Ubuntu 환경에서 진행)
- EC2 서버를 열었던 키페어의 권한 설정
- ec2_test.pem으로 EC2 서버를 열었다
- 해당 파일을 읽을 수 있도록 읽기 권한을 허용한다
sudo chmod 400 ec2_test.pem
2. EC2 서버에 접속한다
- ec2-3-38-189-4.ap-northeast-2.compute.amazonaws.com로 연결하려고 한다
- 3-38-189-4만 사용하면 된다
//ec2_test.pem에 대한 열기 권한을 획득 했으므로 ec2_test.pem 읽기 가능
ssh -i ec2_test.pem ubuntu@3.38.189.4
(2-2) EC2 서버에 도커 설치
- 흐름
- 위의 과정에서 EC2 서버에 접속했다.
- 접속한 EC2 서버에 도커를 설치하려고 한다.
- 코드
- 참고 : https://dazzling-objective-ee3.notion.site/StrpingBoot-Docker-Docker-compose-cabfa1f5eb4845879d001403808e72e9
- (위에서부터 한 줄씩 실행하여, 도커 환경을 구성한다)
//관리자 권한 얻기 sudo su //업데이트 apt-get update apt-get upgrade //도커 설치 apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common curl -fsSL <https://download.docker.com/linux/ubuntu/gpg> | sudo apt-key add - add-apt-repository "deb [arch=amd64] <https://download.docker.com/linux/ubuntu> $(lsb_release -cs) stable" apt-get update apt-get install docker-ce docker-ce-cli containerd.io curl \\ -L "<https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$>(uname -s)-$(uname -m)" \\ -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
(2-3) EC2 서버에 도커 DB(MySQL) 이미지 다운 및 컨테이너 실행
- 목적
- 실행하고자 하는 프로그램(Spring)을 동작하기 위한 DB(MySQL)가 필요하다.
- 도커를 통해 DB 이미지를 만들고 컨테이너를 만든다.
- 코드
//관리자 권한 얻기
sudo su
//해당 프로그램이 mysql:8.0.32 버전을 사용함.
//따라서 8.0.32버전의 이미지 다운로드
docker pull mysql:8.0.32
//이미지 실행(컨테이너 제작)
//내 프로그램의 docker-compose.yml에 적은 그대로 이미지를 실행하면 된다.
docker run -d \\
--name mysqldb \\
-e MYSQL_ROOT_PASSWORD=root \\
-e MYSQL_DATABASE=yogoyogu \\
-p 3306:3306 \\
mysql:8.0.32
//DB 컨테이너에서 사용자 권한 등록
//DB 컨테이너 접속
docker exec -it MySQL컨테이너ID bash
mysql -u root -p //root 이름으로 접속
//mysql 데이터베이스에서 내가 사용할 계정이 있는지 확인
use mysql; //mysql 데이터베이스 접속
select host, user from user; //user 테이블에서 접근 권한자 목록 확인 가능
//내가 사용할 계정이 없다면 새로 추가
create user '이름'@'%' identified by '비밀번호'; // 이름 추가
flush privileges; // 저장
//내가 사용항 데이터베이스가 있는지 확인하고, 없으면 새로 추가
show databases; //전체 데이터베이스 목록 확인
create database 데이터베이스이름 // 없으면 데이터 베이스 추가
// 해당 이름의 사용자에게 데이터베이스가 얼마만큼의 권한을 주는지 확인
show grants for 이름@'%';
//사용할 데이터베이스에, 내 사용자명에 대한 권한 추가
//(이렇게 해야 해당 데이터베이스에 대한 CRUD 가능)
grant all on 데이터베이스이름.* to '이름'@'%'; //해당 데이터베이스에 대해서 모든 권한 획득
flush privileges; // 저장
※ DB 이미지 실행(컨테이너 제작) 시, 주의점
⇒ 내가 만든 프로그램의 docker-compose.yml의 DB와 동일하게 제작했는지 확인해야함
- 예시
- docker-compose.yml
- 해당 코드는 실행할 프로그램의 docker-compose.yml이다
- 해당 코드에서 실행할 DB에 대한 정보는 mysqldb 부분이다.
- DB가 갖춰야할 정보는 다음과 같다.
- 호스트명 : mysqldb
- 버전 : mysql:8.0.32
- 데이터베이스 이름 : yogoyogu
- 해당 DB를 사용하는 사용자의 비밀번호 : root
- 포트 번호 : 3306
services: //데이터베이스 **mysqldb**: image: mysql:8.0.32 restart: always environment: MYSQL_DATABASE: yogoyogu MYSQL_ROOT_PASSWORD: root ports: - 3306:3306 //실행할 프로그램 backend: build: . restart: always //어떤 컨테이너를 사용할지 정함 //또한, 해당 컨테이너를 어떤 사용자로 접속할지 등록 environment: SPRING_DATASOURCE_URL: **jdbc:mysql://mysqldb:3306/yogoyogu** SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: root ports: - 8080:8080 // 컨테이너 활성화 순서 정함 // backend는 mysqldb 컨테이너에 의존하고 있음 // 따라서, mysqldb 컨테이너 생성 후에 backend 컨테이너 실행 depends_on: - mysqldb
- docker-compose.yml
- DB 이미지에 반영하기
- 위에서 언급된 DB 내용들을 반영하여, 이미지를 컨테이너로 만든다.
docker run -d \\ //컨테이너 이름(호스트명이 없다면 컨테이너 이름이 호스트명이 됨) --name mysqldb \\ -e MYSQL_ROOT_PASSWORD=root \\ -e MYSQL_DATABASE=yogoyogu \\ -p 3306:3306 \\ mysql:8.0.32
※ 호스트명을 빠뜨리지 않는게 중요함
- backend 컨테이너는 jdbc:mysql://mysqldb:3306/yogoyogu 해당 주소의 컨테이너를 요청하고 있음
- 만일 DB를 mysqldb로 호스트명을 정하지 않으면 backend 컨테이너는 DB를 찾지 못함
//실행할 프로그램
backend:
build: .
restart: always
environment:
SPRING_DATASOURCE_URL: **jdbc:mysql://mysqldb:3306/yogoyogu**
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root
ports:
- 8080:8080
depends_on:
- mysqldb
(3) 깃허브 액션 파일 생성
- 순서
- 사용한 깃허브 액션 파일
- 깃허브 액션 설명
(3-1) 사용한 깃허브 액션 파일
- 내 프로젝트가 있는 깃허브 주소에 다음과 같은 파일을 생성했다.
- 경로 : .github/workflows/gradle.yml
name: Java CI with Gradle2
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
env:
DOCKER_IMAGE_NAME: testimage
EC2_HOST: ec2-3-38-186-97.ap-northeast-2.compute.amazonaws.com
EC2_SSH_USER: ec2-user
PRIVATE_KEY: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
jobs:
build-and-push-docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Set up application.yml
run: echo "${{ secrets.APPLICATION }}" > ./src/main/resources/application.yml
- name: Grant execute permission for gradlew
run: sudo chmod +x ./gradlew # gradlew에 실행 권한 부여
- name: Build with Gradle (Skip Tests)
run: ./gradlew build -x test
- name: Build the Docker image
run: docker build . --file Dockerfile --tag ${{ env.DOCKER_IMAGE_NAME }}:latest
- name: Login to Docker Hub using Access Token
run: echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u ${{ secrets.DOCKER_NAME }} --password-stdin
- name: Push the Docker image
run: |
docker image tag ${{ env.DOCKER_IMAGE_NAME }} ${{ secrets.DOCKER_NAME }}/${{ env.DOCKER_IMAGE_NAME }}
docker push ${{ secrets.DOCKER_NAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
- name: Deploy
uses: appleboy/ssh-action@master
with:
host: ec2-3-38-186-97.ap-northeast-2.compute.amazonaws.com # EC2 인스턴스 퍼블릭 DNS
username: ubuntu
key: ${{ secrets.EC2_SSH_PRIVATE_KEY }} # pem 키
# 도커 작업
script: |
sudo docker ps --filter "name=backend" --format "{{.Names}}" | xargs -r sudo docker stop
sudo docker ps --filter 'status=exited' -a -q | xargs -r sudo docker rm
sudo docker images --filter=reference='${{ secrets.DOCKER_NAME }}/${{ env.DOCKER_IMAGE_NAME }}*' -q | xargs -r sudo docker rmi
sudo docker login -u ${{ secrets.DOCKER_NAME }} -p ${{ secrets.DOCKER_HUB_TOKEN }}
sudo docker pull ${{ secrets.DOCKER_NAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
sudo docker run -d \\--name backend \\--link mysqldb \\-e SPRING_DATASOURCE_URL=jdbc:mysql://mysqldb:3306/yogoyogu \\-e SPRING_DATASOURCE_USERNAME=root \\-e SPRING_DATASOURCE_PASSWORD=root \\-p 8080:8080 \\${{ secrets.DOCKER_NAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
(3-2) 깃허브 액션 설명
- 깃허브 액션이란?
- 기능
- 자동 명령어 주입 기능
- 프로그램 배포 시에 반복되는 코드들이 많다
- 깃허브 파일 가져오기
- 도커 이미지 구성
- 컨테이너 실행 등
- 그러한 코드들을 깃허브 액션에 담아놓으면, 깃허브 파일이 수정될때마다 깃허브 액션 코드들이 실행되면서 자동 배포가 가능하다.
- 즉, 배포 과정에서 반복되는 코드들을 깃허브 액션에 담으면 된다.
- 프로그램 배포 시에 반복되는 코드들이 많다
- 자동 명령어 주입 기능
- 기능
- 깃허브 액션 파일 만들기
- 배포하려고 하는 깃허브 주소에서 Action 탭을 클릭한다.
2. java with gradle의 Configure을 클릭한다
- (배포할 프로그램은 Spring, gradle을 사용함)
3. 해당 파일에 깃허브 액션 코드를 담아서 저장하면 .github/workflows/gradle.yml로 파일이 만들어짐
- 깃허브 액션 작성법
- 가정
- 스프링, gradle, java를 사용한다.
- AWS EC2 배포가 목적이다.
- 도커를 사용한다.
- 과정
- 자바 환경 구축
- 배포 프로젝트를 도커 이미지로 생성 후, 온라인에 기록
- AWS EC2에 접속
- 온라인에 있는 배포 프로젝트를 도커 이미지로 받기
- 도커 이미지를 컨테이너로 만들어서 실행
- 가정
#해당 파일 이름(의미X)
name: Java CI with Gradle2
#on : 어떤 경우에 깃허브 액션을 실행할지 정함
#(아래는 push, pull_requeset 발생 시, 깃허브 액션을 수행. 즉, 아래 명령어들 실행)
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
# env : 변수 선언
# ex) DOCKER_IMAGE_NAME = testimage
env:
DOCKER_IMAGE_NAME: testimage
EC2_HOST: ec2-3-38-186-97.ap-northeast-2.compute.amazonaws.com
EC2_SSH_USER: ec2-user
# ${{secrets.~~}}의 값은 깃허브 settings 탭에 있는 private 코드다(보안을 위해서 사용)
PRIVATE_KEY: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
# jobs : 수행할 명령어
# jobs를 여러개 써도 됨
# (하지만 각 jobs는 독립적으로 수행되므로, Ajobs의 진행 상황이 Bjobs에는 반영 안됨)
jobs:
# jobs 이름
build-and-push-docker:
# 해당 jobs의 실행환경
# (현재는 ubuntu 환경에서 실행할 것임)
runs-on: ubuntu-latest
# jobs는 여러개의 step으로 구성됨
# 각각의 step에서 명령어를 넣으면 됨
steps:
# 해당 step의 이름(Checkout)
- name: Checkout
# 현재 리포지토리 코드 가져오기
uses: actions/checkout@v4
# 자바 JDK 설치
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
# 해당 Spring의 application.yml 파일 넣기
# .yml 파일은 보안상 리포지토리에 노출 할 수가 없음
# 따라서, 깃허브의 secrets에 application.yml 선언 후, 이를 가져옴
- name: Set up application.yml
run: echo "${{ secrets.APPLICATION }}" > ./src/main/resources/application.yml
# 해당 프로젝트의 gradlew 파일 실행 권한 획득
- name: Grant execute permission for gradlew
run: sudo chmod +x ./gradlew # gradlew에 실행 권한 부여
# gradlew 파일 실행
# .jar 파일을 만듦(아래에서 추가 설명)
- name: Build with Gradle (Skip Tests)
run: ./gradlew build -x test
# 해당 프로젝트를 도커 이미지로 만듦
- name: Build the Docker image
run: docker build . --file Dockerfile --tag ${{ env.DOCKER_IMAGE_NAME }}:latest
# 도커 허브에 접속
- name: Login to Docker Hub using Access Token
run: echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u ${{ secrets.DOCKER_NAME }} --password-stdin
# 도커 허브에 해당 도커 이미지 저장
- name: Push the Docker image
run: |
docker image tag ${{ env.DOCKER_IMAGE_NAME }} ${{ secrets.DOCKER_NAME }}/${{ env.DOCKER_IMAGE_NAME }}
docker push ${{ secrets.DOCKER_NAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
# 1. 내가 만든 AWS EC2에 접속
# 2. 이미 실행중인 해당 프로젝트의 도커 컨테이너와 이미지 삭제(DB 제외)
# 3. 도커 허브에서 저장한 이미지 가져옴
# 4. 이미지를 컨테이너로 만들어서 실행
- name: Deploy
uses: appleboy/ssh-action@master
with:
host: ec2-3-38-186-97.ap-northeast-2.compute.amazonaws.com # EC2 인스턴스 퍼블릭 DNS
username: ubuntu
key: ${{ secrets.EC2_SSH_PRIVATE_KEY }} # pem 키
# 도커 작업(scripts : uses 환경에서 실행할 명령어. 즉, 외부 환경에서 실행할 명령어)
# | 는 여러 개 명령어를 쓸때 사용하는 기호
script: |
# 호스트명이 backend인 컨테이너 중지(해당 프로젝트의 호스트명임)
sudo docker ps --filter "name=backend" --format "{{.Names}}" | xargs -r sudo docker stop
# 중지된 컨테이너들 전부 삭제
sudo docker ps --filter 'status=exited' -a -q | xargs -r sudo docker rm
# 해당 프로젝트 이름을 가진 이미지 전부 삭제
sudo docker images --filter=reference='${{ secrets.DOCKER_NAME }}/${{ env.DOCKER_IMAGE_NAME }}*' -q | xargs -r sudo docker rmi
# 도커 허브 접속
sudo docker login -u ${{ secrets.DOCKER_NAME }} -p ${{ secrets.DOCKER_HUB_TOKEN }}
# 도커 허브에 있는 내 이미지(실행할 프로젝트) 가져오기
sudo docker pull ${{ secrets.DOCKER_NAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
# 가져온 내 이미지 실행
# (mysqldb라는 호스트명을 가진 DB 컨테이너를 사용할 것이기 때문에 그에 대한 설정도 덧붙임)
sudo docker run -d \\--name backend \\--link mysqldb \\-e SPRING_DATASOURCE_URL=jdbc:mysql://mysqldb:3306/yogoyogu \\-e SPRING_DATASOURCE_USERNAME=root \\-e SPRING_DATASOURCE_PASSWORD=root \\-p 8080:8080 \\${{ secrets.DOCKER_NAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
QnA) 왜 아래 명령어를 실행하여 해당 프로젝트에 대한 .jar 파일을 만들어야 하나?
# gradlew 파일 실행
# .jar 파일을 만듦(아래에서 추가 설명)
- name: Build with Gradle (Skip Tests)
run: ./gradlew build -x test
- 이유
- 해당 .jar 파일로 도커 이미지를 만들 것이기 때문이다.
- gradle.yml
- 내 프로젝트에서 .jar 파일 생성에 대한 정의는 다음과 같이 표기했다.
- 즉, build/libs/myapp-0.0.1.jar로 .jar 파일을 생성한다
//gradle.yml // ./gradlew build 시, 아래 경로로 jar 파일 생성 // build/libs/myapp-0.0.1.jar group = 'org.springframework' version = '0.0.1' archivesBaseName = 'myapp'
- Dockerfile
- 위에서 만든 .jar 파일을 도커 이미지로 제작
FROM openjdk:21-jdk-slim //실행할 .jar 파일 지정(경로 + 파일 이름) ARG JAR_FILE=build/libs/myapp-0.0.1.jar // 위의 .jar 파일은 app.jar로 표기 COPY ${JAR_FILE} app.jar // app.jar를 이미지로 제작 ENTRYPOINT ["java","-jar","/app.jar"]
'팁' 카테고리의 다른 글
AWS에 배포하기(SpringBoot + MySQL + Docker) (0) | 2024.08.08 |
---|