update: Dockerfile 단축 #17
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Deploy to Production Server | |
on: | |
push: | |
branches: | |
- main | |
jobs: | |
set: | |
environment: Deploy-Prod | |
runs-on: ubuntu-latest | |
outputs: | |
TIMESTAMP: ${{ steps.set_timestamp.outputs.TIMESTAMP }} | |
steps: | |
- name: 🕒 Set Timestamp | |
id: set_timestamp | |
run: echo "TIMESTAMP=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT | |
build: | |
environment: Deploy-Prod | |
runs-on: ubuntu-latest | |
steps: | |
- name: 📂 Checkout Repository | |
uses: actions/checkout@v3 | |
- name: 🏗️ Setup JDK 21 | |
uses: actions/setup-java@v3 | |
with: | |
java-version: '21' | |
distribution: 'temurin' | |
- name: 🎖️ Grant Execute Permission | |
run: chmod +x gradlew | |
- name: ⚙️ Create application-prod.yml | |
run: | | |
touch ./src/main/resources/application-prod.yml | |
echo "${{ secrets.APPLICATION_PROD_YML }}" > ./src/main/resources/application-prod.yml | |
shell: bash | |
- name: Debug yml | |
run: cat ./src/main/resources/application-prod.yml | |
- name: 🔨 Build Gradle | |
run: ./gradlew build --no-daemon | |
- name: 🪂 Upload Artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
path: build/libs/groom-0.0.1-SNAPSHOT.jar | |
retention-days: 1 | |
push: | |
needs: | |
- build | |
- set | |
runs-on: ubuntu-latest | |
environment: Deploy-Prod | |
steps: | |
- name: 📥 Load Outputs | |
run: echo "TIMESTAMP=${{ needs.set.outputs.TIMESTAMP }}" >> $GITHUB_ENV | |
- name: 🏷️ Set Docker Image Name | |
run: echo "IMAGE_NAME=${{ secrets.DOCKER_USERNAME }}/groom-server" >> $GITHUB_ENV | |
- name: 📂 Checkout Repository | |
uses: actions/checkout@v3 | |
- name: 📦 Download Artifact | |
uses: actions/download-artifact@v4 | |
with: | |
path: build/libs/ | |
- name: 🐋 Docker Login | |
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin | |
- name: 📦 Build Docker Image | |
run: docker build -t ${IMAGE_NAME}:latest -t ${IMAGE_NAME}:${TIMESTAMP} . | |
- name: 🚀 Push Docker Image | |
run: | | |
docker push ${IMAGE_NAME}:latest | |
docker push ${IMAGE_NAME}:${TIMESTAMP} | |
deploy: | |
needs: push | |
runs-on: ubuntu-latest | |
environment: Deploy-Prod | |
steps: | |
- name: 🏷️ Set Docker Image Name | |
run: echo "IMAGE_NAME=${{ secrets.DOCKER_USERNAME }}/groom-server" >> $GITHUB_ENV | |
- name: 🎁 Set Docker Container Name | |
run: echo "CONTAINER_NAME=groom-server" >> $GITHUB_ENV | |
- name: 🔑 Setup SSH | |
run: | | |
mkdir -p ~/.ssh | |
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa | |
chmod 600 ~/.ssh/id_rsa | |
ssh-agent bash -c "ssh-add ~/.ssh/id_rsa" | |
ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts | |
- name: 🚀 Deploy to Production | |
run: | | |
ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << EOF | |
set -e | |
echo "🛑 Stop and Remove Existing Container" | |
docker stop $CONTAINER_NAME || true | |
docker rm $CONTAINER_NAME || true | |
echo "📥 Pull Latest Image" | |
docker pull ${IMAGE_NAME}:latest | |
echo "🚀 Run New Container" | |
docker run -d --name $CONTAINER_NAME -p 8080:8080 ${IMAGE_NAME}:latest | |
exit 0 | |
EOF | |
- name: ⌛ Wait for Application to Start | |
run: sleep 30 | |
test: | |
needs: | |
- deploy | |
- set | |
runs-on: ubuntu-latest | |
environment: Deploy-Prod | |
steps: | |
- name: 🏷️ Set Docker Image Name | |
run: echo "IMAGE_NAME=${{ secrets.DOCKER_USERNAME }}/groom-server" >> $GITHUB_ENV | |
- name: 🎁 Set Docker Container Name | |
run: echo "CONTAINER_NAME=groom-server" >> $GITHUB_ENV | |
- name: 📥 Load Outputs | |
run: echo "TIMESTAMP=${{ needs.set.outputs.TIMESTAMP }}" >> $GITHUB_ENV | |
- name: 🔐 Setup SSH | |
run: | | |
mkdir -p ~/.ssh | |
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa | |
chmod 600 ~/.ssh/id_rsa | |
ssh-agent bash -c "ssh-add ~/.ssh/id_rsa" | |
ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts | |
- name: 🫀 Check Application Health & Rollback if needed | |
id: health_check | |
run: | | |
RESULT=$(ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << EOF | |
set -e | |
echo "🩺 Checking Application Health..." | |
RESPONSE=\$(curl -s https://${{ secrets.PROD_SERVER_URL }}/) | |
if [ "\$RESPONSE" = "OK" ]; then | |
echo "DEPLOYMENT_STATUS=successful" | |
exit 0 | |
else | |
echo "❌ Deployment Failed! Rolling back..." | |
docker stop $CONTAINER_NAME || true | |
docker rm $CONTAINER_NAME || true | |
PREVIOUS_IMAGE=\$(docker images --format "{{.Repository}}:{{.Tag}}" | grep "$IMAGE_NAME" | grep -v "latest" | sort -r | sed -n '2p') | |
if [ -z "\$PREVIOUS_IMAGE" ]; then | |
echo "⚠️ No previous image found! Manual rollback required." | |
echo "DEPLOYMENT_STATUS=rollback_failed_no_previous" | |
exit 1 | |
fi | |
echo "🔄 Rolling back to previous image: \$PREVIOUS_IMAGE" | |
docker run -d --name $CONTAINER_NAME -p 8080:8080 \$PREVIOUS_IMAGE | |
if [ \$? -eq 0 ]; then | |
echo "✅ Rollback completed successfully!" | |
echo "DEPLOYMENT_STATUS=rollback_success" | |
exit 2 | |
else | |
echo "❌ Rollback execution failed!" | |
echo "DEPLOYMENT_STATUS=rollback_failure" | |
exit 3 | |
fi | |
fi | |
EOF | |
) | |
echo "$RESULT" | |
ROLLBACK_STATUS=$(echo "$RESULT" | grep "DEPLOYMENT_STATUS=" | cut -d '=' -f2) | |
echo "rollback_status=$ROLLBACK_STATUS" >> $GITHUB_OUTPUT | |
continue-on-error: true | |
- name: 📢 Post Warning in Summary (Rollback Success) | |
if: steps.health_check.outputs.rollback_status == 'rollback_success' | |
run: echo "⚠️ Deployment failed, but rollback was successfully executed. Please verify the system." >> $GITHUB_STEP_SUMMARY | |
- name: 📢 Post Warning in Summary (Rollback Failed) | |
if: steps.health_check.outputs.rollback_status == 'rollback_failure' || steps.health_check.outputs.rollback_status == 'rollback_failed_no_previous' | |
run: echo "⚠️ Deployment failed and rollback was not successful. Manual intervention is required!" >> $GITHUB_STEP_SUMMARY |