src/resource/ application.yml
spring:
profiles:
active: local
group:
local: common
blue: blue, common
green: green, common
server:
env: blue
---
spring:
config:
activate:
on-profile: common
serverName: common
---
spring:
config:
activate:
on-profile: blue
server:
port: 8080
serverName: blue_server
---
spring:
config:
activate:
on-profile: green
server:
port: 8081
serverName: green_server
---
vim docker-compose-blue.yml
i를 누르고 --insert-- 모드로 아래 사진 처럼 내용을 작성해 준다
version: '3.8'
services:
blue:
image: {dockerHubUserName}/boardServer:latest
container_name: blue
ports:
- "8080:8080"
environment:
- PROFILES=blue
- ENV=blue
esc -> :wq! 로 저장 후 나가기
cp docker-compose-blue.yml ./docker-compose-green.yml
현재 파일을 복제해서 이름을 바꿔서 저장해준다
vim docker-compose-green.yml
blue->green으로 바꿔주고 포트번호를 8081로 변경해준다
version: '3.8'
services:
green:
image: {dockerHubUserName}/boardServer:latest
container_name: green
ports:
- "8081:8081"
environment:
- PROFILES=green
- ENV=green
파일 내용 확인 하기
cat docker-compose-blue.yml
cat명령어로 vim 수정으로 들어가지 않아도 안에 내용을 확인할 수 있다
name: CICD
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
- name: Build with Gradle
uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0
with:
arguments: build
# run : ./gradlew clean build --exclude-task test
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build Docker
run: docker build --platform linux/amd64 -t ${{ secrets.DOCKERHUB_USERNAME }}/boardServer .
- name: Push Docker
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/boardServer:latest
인텔리제이에서 project -> new file
Dockerfile 생성
FROM amazoncorretto:21-alpine-jdk
ARG JAR_FILE=build/libs/*.jar
ARG PROFILES
ARG ENV
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "Dspring.profiles.active=${PROFILES}", "-Dserver.env=${ENV}", "-jar", "app.jar"]
Dockerfile에 위에 내용을 작성해줌
이렇게 공개되면 안되는 중요한 정보를 담아준다 생각하면 된다
ec2 pem 키 설정
mac 에서 pem키를 그냥 열수 없기 때문에 어떻게 접근해야하냐면 vscode로 파일을 열면
-----BEGIN RSA PRIVATE KEY-----
.
.
.
-----END RSA PRIVATE KEY-----
이 내용 전부를 긁어서 secrets에 설정하면 된다
cicd.yml 파일을 아래처럼 다 완성해주었다
name: CICD
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
- name: Build with Gradle
uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0
with:
arguments: build
# run : ./gradlew clean build --exclude-task test
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build Docker
run: docker build --platform linux/amd64 -t ${{ secrets.DOCKERHUB_USERNAME }}/board_server .
- name: Push Docker
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/board_server:latest
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Set target IP
run: |
STATUS=$(curl -o /dev/null -w "%{http_code}" "http://${{ secrets.BOARD_SERVER_IP }}/env")
echo $STATUS
if [ $STATUS = 200 ]; then
CURRENT_UPSTREAM=$(curl -s "http://${{ secrets.BOARD_SERVER_IP }}/env")
else
CURRENT_UPSTREAM=green
fi
echo CURRENT_UPSTREAM=$CURRENT_UPSTREAM >> $GITHUB_ENV
if [ $CURRENT_UPSTREAM = blue ]; then
echo "CURRENT_PORT=8080" >> $GITHUB_ENV
echo "STOPPED_PORT=8081" >> $GITHUB_ENV
echo "TARGET_UPSTREAM=green" >> $GITHUB_ENV
else
echo "CURRENT_PORT=8081" >> $GITHUB_ENV
echo "STOPPED_PORT=8080" >> $GITHUB_ENV
echo "TARGET_UPSTREAM=blue" >> $GITHUB_ENV
fi
- name: Docker compose
uses: appleboy/ssh-action@master
with:
username: ubuntu
host: ${{ secrets.BOARD_SERVER_IP }}
key: ${{ secrets.EC2_SSH_KEY }}
script_stop: true
script: |
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/board_server:latest
sudo docker-compose -f docker-compose-${{env.TARGET_UPSTREAM}}.yml up -d
- name: Check deploy server URL
uses: jtalk/url-health-check-action@v3
with:
url: http://${{ secrets.BOARD_SERVER_IP }}:${{env.STOPPED_PORT}}/env
max-attempts: 5
retry-delay: 20s
- name: Change nginx upstream
uses: appleboy/ssh-action@master
with:
username: ubuntu
host: ${{ secrets.BOARD_SERVER_IP }}
key: ${{ secrets.EC2_SSH_KEY }}
script_stop: true
script: |
sudo docker exec -i nginxserver bash -c 'echo "set \$service_url ${{ env.TARGET_UPSTREAM }};" > /etc/nginx/conf.d/service-env.inc && nginx -s reload'
- name: Stop current server
uses: appleboy/ssh-action@master
with:
username: ubuntu
host: ${{ secrets.BOARD_SERVER_IP }}
key: ${{ secrets.EC2_SSH_KEY }}
script_stop: true
script: |
sudo docker stop ${{env.CURRENT_UPSTREAM}}
sudo docker rm ${{env.CURRENT_UPSTREAM}}
이렇게 하고
springboot project git commit -> push 를 통해서 빌드 실행해주었다
하지만 바로 오류가 나기 시작했다 ㅎㅎ
이 밑에는 그 오류들을 해결해 나간 기록들이다!
FROM amazoncorretto:21-alpine-jdk
ARG JAR_FILE=*.jar
ARG PROFILES
ARG ENV
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "Dspring.profiles.active=${PROFILES}", "-Dserver.env=${ENV}", "-jar", "app.jar"]
ARG JAR_FILE=target/.jar -> ARG JAR_FILE=build/libs/.jar 으로 변경
target/ 폴더안에 jar이 있지 않기 때문이라고 판단 했기 때문이다
bootjar를 클릭해주면 bootjar이 빌드되는데
그러면 libs 폴더안에 jar 파일이 생성이 된다
그러고 나면 위에 build docker 오류는 해결이 되었다
빌드 단계에서는 성공을 하더니 deploy 단계에서 오류에 봉착했다..🥲
구글링을 하다가 하나의 글에서 본 걸 보고 혹시나 해서 적용을 했는데 이 오류에서 벗어날 수 있었다
그건 ec2에서 보안그룹 인바운드 규칙 설정 중 ssh 서버를 내IP로 설정해두어
ip가 막혀서 연결이 안되는 오류였다
이렇게 다 0.0.0.0/0 서버로 지정해 주니 deploy 단계중 dockercompose 오류에서 빠져나올 수 있었다
정말... 이 오류에서 빠져나오기 까지 꽤 오랜 시간이 걸렸다..
도대체 무엇인지 모르는 상태에서 오류라... 서치를 해도 뚜렷한 답을 찾지 못했다
결국 내가 수정한 부분들이.. 이 오류를 빠져나오게 해주었기에 정확한 방법은 아니지만 공유해보려고 한다
하지만, 이 부분에서 탄력적 Ip 로 정확하게 연결되어있는지를 확인이 되지 않았고, 여기서 헬스체크 오류가 난다고 판단을 했다
그래서 저 빨간색 네모 박스 부분에 탄력적ip를 넣어주었고
application.yml 에서는 탄력적 ip 서버를 삭제해주었다
spring:
profiles:
active: local
group:
local: common
blue: blue, common
green: green, common
server:
env: blue
---
spring:
config:
activate:
on-profile: common
serverName: common
---
spring:
config:
activate:
on-profile: blue
server:
port: 8080
#address: ${AWS_PUBLIC_IP}
serverName: blue_server
---
spring:
config:
activate:
on-profile: green
server:
port: 8081
#address: ${AWS_PUBLIC_IP}
serverName: green_server
---
-> 주석처리된 부분이 없애준 부분
nginx -s reload
끝으로 nginx -s reload를 해주어서 파일 변경된 부분을 반영해주었다
이렇게 해서 헬스체크 오류에서 빠져나올 수 있었다
만약 헬스체크에서 계속 반복적인 오류가 난다면
Ip연결이 제대로 되어있는지 확인해 보면 좋을 것 같다!
배포가 성공한 뒤 이게 제대로 배포가 되었는지 확인하기 위해선 두가지를 확인해봐야한다
docker 에서 서버가 제대로 열렸는지 확인
blue / green 서버가 교체가 잘되는 것을 확인 할 수 있다
무중단 배포가 잘 이루어졌으면 탄력적 Ip로 접근이 가능해져야합니다
저는 아직 도메인 설정을 안해줬기 때문에 탄력적 ip로 접근해보았습니다
이렇게 잘 열리면 무중단 배포가 잘 뜨게 됩니다