목차
1. EC2 생성
2. RDS 생성
3. Dockerfile 작성
4. github secrets에 환경변수 선언
5. github-actions.yml 코드 작성
EC2 생성과 RDS 생성은 자료들이 많을 것이라고 생성한다.
주의할 점은 같은 VPC 안에서 생성되어야하기 때문에 RDS 생성 시 기존에 생성해두었던 EC2를 지정해주어야 한다.
같은 VPC안에 있어야 서버에서 RDS를 찾아 생성할 수 있다.
프로젝트의 루트 디렉토리 내에 생성하면 된다.

# 베이스 이미지: Java 17 (필요에 따라 Java 버전 변경 가능)
FROM openjdk:17-jdk-slim
# 컨테이너 내부의 작업 디렉토리 설정
WORKDIR /app
# 빌드된 JAR 파일을 컨테이너로 복사
COPY ./build/libs/*.jar app.jar
# 컨테이너에서 열릴 포트
EXPOSE 8080
# 애플리케이션 실행 명령어
ENTRYPOINT ["java", "-jar", "app.jar"]
github actions를 이용할건데, github에 개인정보는 올리면 안되니까 환경변수를 이용한다.
아래의 github-actions.yml 코드 내부에 이용되는 것들을 환경변수로 미리 선언하는 것이다.
YML
spring:
application:
name: forest
profiles:
group:
dev: dev, local
deploy: deploy
active: dev
spring:
datasource:
url: jdbc:mysql://<엔드포인트>:<포트번호>/<DB인스턴스식별자이름>
username: <rds 생성 시 지정한 마스터사용자 이름>
password: <rds 생성 시 지정한 마스터암호>
jpa:
show-sql: true
hibernate:
ddl-auto: update
logging:
level:
org.hibernate.SQL: debug
hibernate:
ddl-auto: update
데이터베이스 내부에 자동으로 테이블이 만들어지도록 하는 명령어이다.
이 코드를 써주지 않으면 actions파일을 실행시켰을 때 오류가 나므로 꼭 포함시켜주어야한다.
ubuntu
docker 가입할 때 지정한 사용자 이름
docker 가입할 때 지정한 비밀번호
EC2로 할당받은 public IPv4 주소

ppk파일을 다운로드 했다면, 이를 cat명령어를 이용해 확인한 후, 키 부분을 떼어 위와같이 작성한 후 PRIVATE KEY 환경변수로 등록해준다.

먼저 루트 디렉토리 내부의 .github 패키지 내부에 workflows 패키지를 만들고, 그 안에 github-actions.yml 파일을 만든다.
나의 경우에는 dev를 실행하도록 코드를 작성했다.
# github repository actions 페이지에 나타날 이름
name: CI/CD using github actions & docker
# event trigger
# main브랜치에 push가 되었을 때 실행
on:
push:
branches: [ "main" ]
permissions:
contents: read
jobs:
CI-CD:
runs-on: ubuntu-latest
steps:
# JDK setting - github actions에서 사용할 JDK 설정 (프로젝트나 AWS의 java 버전과 달라도 무방)
- 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-
# 권한 부여
- name: Add execution permissions to Gradle Wrapper
run: chmod +x ./gradlew
# 환경별 yml 파일 생성(1) - application.yml
- name: make application.yml
if: |
contains(github.ref, 'main')
run: |
mkdir ./src/main/resources # resources 폴더 생성
cd ./src/main/resources # resources 폴더로 이동
touch ./application.yml # application.yml 생성
echo "${{ secrets.YML }}" > ./application.yml # github actions에서 설정한 값을 application.yml 파일에 쓰기
shell: bash
# 환경별 yml 파일 생성(2) - dev
- name: make application-dev.yml
run: |
cd ./src/main/resources
touch ./application-dev.yml
echo "${{ secrets.YML_DEV }}" > ./application-dev.yml
shell: bash
# gradle build
- name: Build with Gradle
run: ./gradlew build -x test
# docker build & push to develop
- name: Docker build & push to dev
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -f Dockerfile-dev -t ${{ secrets.DOCKER_USERNAME }}/docker-test-dev .
docker push ${{ secrets.DOCKER_USERNAME }}/docker-test-dev
## deploy to develop
- name: Deploy to dev
uses: appleboy/ssh-action@master
id: deploy-dev
with:
host: ${{ secrets.HOST_DEV }} # EC2 퍼블릭 IPv4 DNS
username: ${{ secrets.USERNAME }} # ubuntu
password: ${{ secrets.PASSWORD }}
port: 22
key: ${{ secrets.PRIVATE_KEY }}
script: |
port=8080
echo "Checking for containers using port $port..."
# Find the container ID using the specified port
container_id=$(docker ps --filter "publish=$port" --format "{{.ID}}")
if [ -n "$container_id" ]; then
echo "Found container with ID: $container_id. Stopping it..."
docker stop "$container_id"
docker rm "$container_id"
echo "Container stopped successfully."
else
echo "No container is using port $port."
fi
sudo docker ps
sudo docker pull ${{ secrets.DOCKER_USERNAME }}/docker-test-dev
sudo docker run --name team-18 -d -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/docker-test-dev
spring:
application:
name: <애플리케아션 이름>
profiles:
group:
dev: dev, local
deploy: deploy
active: dev
💻 코드 설명
2024-11-22 12:00:00.000 INFO 12345 --- [ main] hyeondooori.Application : Started Application in 5.123 seconds (JVM running for 5.678)💻동작 방식
1. spring.profiles.active에 따라 프로파일 로드
개발 환경에 따라 application.yml 내부의
spring.profiles.active를 변경하여 활성되는 프로파일을 변경할 수 있다.
로컬환경에서 작업할 때는 active를 local로 하고, 개발환경에서는 dev로 하는 방식!
로컬에서 Docker컨테이너를 실행하려면 Docker Desktop이 실행중이어야만 했다.
이는 Windows나 Mac과 같은 운영체제에서 Docker engine을 실행하는데 필요하다.
하지만, AWS에서 실행되는 Docker는 해당 서버(AWS 인스턴스)에 설치된 Docker engine 위에서 동작한다. 이 Docker engine은 AWS 서버 자체에서 관리되며, 로컬 Docker Desktop과는 전혀 관계가 없다.
AWS에서 퍼블릭IP를 할당받은 인스턴스(AWS EC2 등)에서 Docker컨테이너를 실행했다면:
컨테이너 실행 유지 조건
1. AWS EC2 인스턴스가 계속 실행 중이어야 한다.
EC2가 중지되면, Docker 컨테이너도 중단된다.
2. Docker 컨테이너가 백그라운드에서 실행중이어야한다.
컨테이너를 실행할 때 -d(detached mode)옵션을 사용하여 컨테이너를 백그라운드에 유지한다.
docker run -d -p 3306:3306 --name mysql-container -e MYSQL_ROOT_PASSWORD=<password> mysql