2024. 11. 29. 10:56ㆍServer
이때 동안 AWS EC2에 배포를 진행 할때 Gradle로 빌드를 진행 한 뒤
Docker Image로 만들고
그걸 Dokcer Hub에 올린 뒤
AWS EC2 인스턴스에서 Docker Hub에서 Image Pull 받은 뒤 배포하는 방식으로
수작업을 통해서 배포를 진행했다.
그런데 이렇게 수작업으로 진행하니 귀찮아서 점점 주기가 늘어나 이제는 자동화를 할 때라고 생각하게 되었다.
그래서 어떻게 자동화를 하나 알아보니
무료 툴은 Github Action과 Jenkins이 많이 보였고
그 중 클라우드에서 동작해서 호스팅을 따로 해줄 필요가 없는 Github Action을 선택하게 되었다.
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
name: Java CI with Gradle
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name : Make application.properties
run: |
cd ./src/main/resources
touch ./application.properties
touch ./jwt.properties
echo "${{ secrets.PROPERTIES }}" > ./application.properties
echo "${{ secrets.JWT_KEY }}" > ./jwt.properties
shell: bash
- name: Decode and create keystore.p12
env:
KEY_P12_BASE64: ${{ secrets.SSL_KEY }}
run: |
cd ./src/main/resources
touch ./keystore.p12
echo -n "$KEY_P12_BASE64" | base64 --decode > ./keystore.p12
shell : bash
- name: give permission
run : chmod +x ./gradlew
- name: Build with Gradle Wrapper
run: ./gradlew build
- name: docker image build
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/server:springmvc .
- name: docker login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERID }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: docker Hub push
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/server:springmvc
# GitHub Actions VM 환경의 IP를 받아온다.
- name: Get Public IP
id: ip
uses: haythem/public-ip@v1.3
# AWS 인증 관련 옵션을 추가한다.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: 'ap-northeast-2'
# GitHub Actions VM 환경의 IP를 인바운드 규칙에 추가한다.
- name: Add GitHub Actions IP
run: |
aws ec2 authorize-security-group-ingress \
--group-id ${{ secrets.SECURITY_GROUP_ID }} \
--protocol tcp \
--port 22 \
--cidr ${{ steps.ip.outputs.ipv4 }}/32
- name: Deploy to EC2
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_SSH_USER }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
script: |
CONTAINER_ID=$(sudo docker ps -q --filter "publish=8080-8080")
if [ ! -z "$CONTAINER_ID" ]; then
sudo docker stop mvccon
sudo docker rm $CONTAINER_ID
fi
sudo docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }}
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/server:springmvc
sudo docker run --name mvccon -d -p 8080:8080 -e TZ=Asia/Seoul --add-host host.docker.internal:host-gateway ${{ secrets.DOCKERHUB_USERNAME }}/server:springmvc
# GitHub Actions VM 환경의 IP를 인바운드 규칙에서 제거한다.
- name: Remove GitHub Actions IP
run: |
aws ec2 revoke-security-group-ingress \
--group-id ${{ secrets.SECURITY_GROUP_ID }} \
--protocol tcp \
--port 22 \
--cidr ${{ steps.ip.outputs.ipv4 }}/32
하나 하나 알아보도록 하겠다.
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
해당 구문은 Github Action의 동작 조건을 설정하는 것이다.
위 구문은 main 브랜치에 push나 pull request가 일어날 때 동작하도록 했다.
runs-on: ubuntu-latest
permissions:
contents: write
최신 우분투에서 돌아가고 권한은 쓰기 권한을 주었다 기본적으로 쓰기 권한은 읽기 권한을 포함하고 있기 때문에 읽기 권한은 따로 설정하지 않아도 된다
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
현재 작업 공간으로 데이터를 복사해오고 자바를 설치해준다
- name : Make application.properties
run: |
cd ./src/main/resources
touch ./application.properties
touch ./jwt.properties
echo "${{ secrets.PROPERTIES }}" > ./application.properties
echo "${{ secrets.JWT_KEY }}" > ./jwt.properties
shell: bash
application.properties파일을 만들어 준다
기본적으로 해당 파일에는 노출되면 안 되는 비밀 번호 등이 있어서 .gitignore파일에 등록해두었다.
따라서 git의 관리를 받고 있지 않고 빌드할때 포함되지 않았다.
그래서 따로 만들어주어야 하는데 이때 쓰는 것이 Secrets이다.
Setting에 들어가면 비밀로 하지만 사용해야 하는 데이터를 이렇게 등록해서 사용할 수 있다

- name: Decode and create keystore.p12
env:
KEY_P12_BASE64: ${{ secrets.SSL_KEY }}
run: |
cd ./src/main/resources
touch ./keystore.p12
echo -n "$KEY_P12_BASE64" | base64 --decode > ./keystore.p12
shell : bash
마찬가지로 가지고 있는 SSH 인증서도 base64로 인코딩해서 Secrets에 저장한 다음 decode해서 인증서를 생성해 주었다.
- name: give permission
run : chmod +x ./gradlew
- name: Build with Gradle Wrapper
run: ./gradlew build
이제 Gradle을 이용해서 Spring Boot 프로젝트를 빌드해준다.
- name: docker image build
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/server:springmvc .
그걸 원하는 태크를 가진 Docker Image로 빌드하고
- name: docker login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERID }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
Docker에 로그인한 뒤
- name: docker Hub push
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/server:springmvc
Docker Hub에 Push한다
- name: Get Public IP
id: ip
uses: haythem/public-ip@v1.3
그 후 현재 Public Ip를 받아왔는데 이는 AWS EC2의 보안 설정 때문이다.
AWS EC2에 SSH로 접속하기 위해서는
기본적으로 보안 그룹을 통해 IP를 등록해주어야 하는데
Github Action은 고정 IP에서 동작하지 않기 때문에
아예 모든 접속에 대해서 SSH 포트를 열어주거나
그 때마다 등록을 해주어야 한다.
당연히 모든 접속에 대해서 열면 보안성이 떨어지므로 동작 할 때마다 IP를 등록하고 삭제하도록 설정했다.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: 'ap-northeast-2'
EC2에 접속하기 위해서는 AWS에 EC2 접속용 User를 만든다


권한은 EC2 Full Access하나만 준다

그 후 액세스 키를 만든다

이제 이 액세스 키를 Secrets에 등록해서 Github Action에서 AWS EC2에 접속할 수 있다.
- name: Add GitHub Actions IP
run: |
aws ec2 authorize-security-group-ingress \
--group-id ${{ secrets.SECURITY_GROUP_ID }} \
--protocol tcp \
--port 22 \
--cidr ${{ steps.ip.outputs.ipv4 }}/32
보안 그룹에 아까 얻은 IP를 22번 포트에서 허가한다.
- name: Deploy to EC2
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_SSH_USER }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
script: |
CONTAINER_ID=$(sudo docker ps -q --filter "publish=8080-8080")
if [ ! -z "$CONTAINER_ID" ]; then
sudo docker stop mvccon
sudo docker rm $CONTAINER_ID
fi
sudo docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }}
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/server:springmvc
sudo docker run --name mvccon -d -p 8080:8080 -e TZ=Asia/Seoul --add-host host.docker.internal:host-gateway ${{ secrets.DOCKERHUB_USERNAME }}/server:springmvc
이제는 SSH를 통해 AWS EC2 Instance에 접속할 수 있기 때문에
SSH로 접속하고 기존 실행중인 컨테이너를 멈추고 삭제 한 뒤
Docker Hub에 로그인 한 뒤
아까 올린 이미지를 Pull하고
실행시켜준다.
- name: Remove GitHub Actions IP
run: |
aws ec2 revoke-security-group-ingress \
--group-id ${{ secrets.SECURITY_GROUP_ID }} \
--protocol tcp \
--port 22 \
--cidr ${{ steps.ip.outputs.ipv4 }}/32
이제 마지막으로 아까 보안 그룹에 등록한 IP를 삭제해주고 끝이다.
'Server' 카테고리의 다른 글
| Nginx Load Balancing (0) | 2024.03.12 |
|---|---|
| JWT (0) | 2024.01.13 |
| Http의 한계와 WebSocket (0) | 2023.08.16 |
| Session, Cookie, Token (0) | 2023.08.16 |
| Winsock2.h를 이용한 TCP 통신 (0) | 2023.08.11 |