
0. 왜 Github Actions을 사용했나?
사이드 프로젝트에서 기존에 사용해봤던 Github Actions 말고 Jenkins를 사용하려고 했는데, 예전에 기술적 의사결정을 해놓고서 깜빡했나보다. jenkins를 제대로 활용하기 위해서는 추가 EC2 인스턴스가 결국 필요했다. 때문에 Docker-Compose 써서 jenkins로 혼자 하루 온종일 시행착오를 겪으며 jenkins와 씨름했지만 서버비 등 상황 상 Github Actions를 다시 쓰기로 했다. Github Actions는 Github에서 인프라 서버를 제공해주는 방식이기 때문에 인프라용 인스턴스를 증설할 필요가 없기 때문이다. 갓 Github.
추가적으로 Docker를 쓰는 이유는 이미지, 컨테이너 방식으로 패키징하여 관리가 쉽고, docker hub라는 외부 repository로 push, pull 방식으로 github와 개발 서버 인스턴스간의 연결다리 역할로 매우 편리하여 이번에도 Docker를 사용하였다.
몇 달만에 다시 써보는 Github Actions이라 잠깐 기억이 안났는데, 다행히 몇번 만져보니 다시 기억났다. 전에 있던 글에는 좀 횡설수설 적은 것도 있고, 안까먹도록 다시 쓸때 꺼내보려고 확실하게 정리하려고 한다.
사이드프로젝트 초기 단계에서 편하게 개발하려고 CI/CD를 구현해놓은 것이라, 아직 굳이 무중단배포의 필요성은 느끼지 못해
이 글의 Github Actions 스크립트에는 무중단배포 방식은 구현되어있지 않다.
개발 환경
AWS EC2(Ubuntu), Spring Boot, Java17, Gradle, Mac(Intel)
1. Docker 설치
https://docs.docker.com/desktop/install/mac-install/
Install Docker Desktop on Mac
Install Docker for Mac to get started. This guide covers system requirements, where to download, and instructions on how to install and update.
docs.docker.com
본인의 OS와 칩셋에 맞게 설치를 진행한다.
저와 같은 OS 환경이라면 아래 명령어를 그대로 Ubuntu 서버에 입력하고 설치를 진행하자.
#1
sudo apt-get update
#2
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
#3
curl -fsSL https://download.docker.com/linux/ubuntu/gpg |
sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
#4
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
#5
sudo apt-get install docker-ce docker-ce-cli containerd.io
#6 잘 설치되었는지 확인
docker --version
2. Docker Hub Repository 생성
https://tttsss77.tistory.com/232
도커(Docker) : 도커 허브(Docker Hub) 가입 및 저장소 생성하기
개요 도커 허브(Docker Hub)에 가입하면, 클라우드 상에 저장소를 생성하여 도커 이미지를 저장해 둘 수 있고 필요 시 로컬 PC 상에 다운로드하여 사용할 수 있습니다. 본 글에서는 도커 허브에 가입
tttsss77.tistory.com
다른 블로그의 글로 대체한다! 쉬우니 그냥 도커 계정이 없으면 계정만들고 레포지토리 생성하면 된다.
3. Github Actions 스크립트

개발하고 있는(배포할) 프로젝트의 루트 디렉토리에
.github - workflows안에 github-actions.yml 파일 생성
# github repository actions 페이지에 나타날 이름
name: CI/CD using github actions & docker
# event trigger
# main | develop 브랜치에 push 되었을 때 실행
on:
push:
branches: [ main, develop ]
permissions:
contents: read
jobs:
CI-CD:
runs-on: ubuntu-latest
steps:
# JDK Setting
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
# gradle caching
- name: Gradle Caching
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
# yml 파일 Setting - application.yml
- name: make application.yml
if: |
contains(github.ref, 'main') ||
contains(github.ref, 'develop')
run: |
cd ./src/main/resources
touch ./application.yml
echo "${{ secrets.YML }}" > ./application.yml
shell: bash
# gradle build
- name: Build with Gradle
run: ./gradlew build -x test
# docker build & push
- name: Docker build & push to dev
if: |
contains(github.ref, 'main') ||
contains(github.ref, 'develop')
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t ${{ secrets.DOCKER_USERNAME }}/{dockerhub repository name} .
docker push ${{ secrets.DOCKER_USERNAME }}/{dockerhub repository name}
# deploy to develop
- name: deploy to develop
uses: appleboy/ssh-action@master
id: deploy-dev
if: |
contains(github.ref, 'main') ||
contains(github.ref, 'develop')
with:
host: ${{ secrets.HOST_DEV }} # EC2 퍼블릭 IPv4 DNS
username: ${{ secrets.USERNAME }} # ubuntu
port: 22
key: ${{ secrets.PRIVATE_KEY }}
envs: GITHUB_SHA
script: |
sudo docker ps
sudo docker stop $(docker ps -a -q) || true
sudo rm $(docker ps -a -q) || true
sudo docker pull ${{ secrets.DOCKER_USERNAME }}/{dockerhub repository name}
sudo docker run -d -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/{dockerhub repository name}
sudo docker image prune -f
구현하고자 하는 CI/CD 파이프라인은 Github -> Docker Hub -> EC2(Ubuntu)이다.
스크립트의 내용 순서는 다음과 같다.
main 또는 develop branch에 push가 발생
-> jdk setting
-> gradle caching
-> yml 파일 생성
-> gradle로 build
-> build된 파일을 docker image로 빌드
-> docker hub로 push
-> github actions가 22번 포트로 ubuntu ssh 접근
-> docker hub에서 이미지를 pull 받아서 8080:8080 포트로 실행
여기에 {dockerhub repository name}은 본인이 만든 docker hub repository명을 입력하면 되고,
다른 ${{ }} 의 내용들은 외부에서 알 수 없도록 Github Secrets에 전역변수로 등록해놓은 것이다.
* yml 파일을 생성하는 이유는 보통 프로젝트 파일을 Github Repository에 올릴 때 민감한 정보가 들어있는 application.yml은 gitignore 시키니까, 서비스 구동에 필요하기 때문에 생성해준다.
** application.yml이 원래 gitignore에 등록되어 repository에 보통 resources 폴더가 생성되어있지 않은 상태일거다. 그래서 나는 그냥 templates 폴더에 더미용 html 하나 만들어서 resources 폴더가 인식될 수 있도록 해주었다.
4. Github Actions Secrets 등록
Github Repository - Setting - Security - Secrets and variables - Actions 순으로 들어가면

이렇게 Secrets을 설정할 수 있는데, 위 사진에는 이미 등록이 되어있어 저렇게 나오지만 아무것도 등록이 되어있지 않은 상태라면 New repository secret을 눌러 Secret을 등록해주면 된다.
여기에 등록된 정보는 한번 등록되면 암호화되어 등록한 사람도 다시 확인할 수 없다.
단 기존의 내용은 확인하지 못하지만, 수정은 가능하다.
입력해야할 내용은 위의 목록과 같은데, 주의할 점은 PRIVATE_KEY는 ubuntu의 pem key를 입력해주면 되는데, pem key의 내용 전부 다 넣어야한다. --- 이런것도 전부 다.
4. 결과 확인
프로젝트를 main이나 develop에 push 하고 실패없이 빌드, 배포되는지 확인해보자.
ubuntu에서 docker ps를 입력해서 docker 컨테이너가 잘 실행되었는지 확인해보자.

마지막으로 {IP}:8080 으로 접속해서 위 사진처럼 나오면 잘 배포된 것
5. 주의점
- 글 앞에도 적어뒀지만 무중단배포 방식이 아니라 CI/CD 중에 서버가 잠시 중단되는 downtime이 발생한다.
(가볍게 구현한 임시방편에 가까움)
- AWS EC2 보안그룹 인바운드 규칙 편집에서 8080, 22(ssh), 80(HTTP) 포트를 열어줘야 한다.
'DevOps > Infra' 카테고리의 다른 글
| [k8s] 1. 쿠버네티스란 무엇인고? (0) | 2025.05.19 |
|---|---|
| Nginx, Let's Encrypt로 HTTPS 적용, 프론트 도메인 연결 방법 (AWS Route53 X) (1) | 2024.05.28 |
| Docker란? (도커 이미지, 컨테이너, 일관성) (0) | 2024.03.08 |
| 블루그린으로 무중단배포를 구현할때 Docker Compose를 왜 사용했나요? (2) | 2024.02.20 |
| Docker를 왜 사용하나요? (1) | 2024.02.20 |