Skip to content

feat: blue green 무중단 배포 스크립트 #36

feat: blue green 무중단 배포 스크립트

feat: blue green 무중단 배포 스크립트 #36

Workflow file for this run

name: backend-push
on:
push:
branches: [ "main", "feature/#745" ]
paths:
- 'server/**'
- '.github/workflows/**'
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
working-directory: ./server
permissions:
contents: read
steps:
- name: CheckOut
uses: actions/checkout@v4
with:
token: ${{secrets.CONFIG_SUBMODULE_TOKEN}}
submodules: true
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Test with Gradle Wrapper
run: ./gradlew clean build
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Set up Docker BuildX
uses: docker/setup-buildx-action@v3
- name: Build and push
run: |
docker buildx build --platform linux/arm64 -t \
${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} --push .
deploy:
needs: build
strategy:
matrix:
runner: [ prod-1 , prod-2 ]
runs-on: [ self-hosted, '${{ matrix.runner }}' ]
steps:
- name: Docker Image pull
run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }}
- name: Check running container and determine the next port
id: check-port
run: |
echo "Checking if any container is running on ports 8080 or 8081..."
CURRENT_PORT=$(sudo docker ps --format "{{.Names}}" | grep "haengdong-backend" | grep -o '8080\|8081' || echo "")
echo "CURRENT_PORT on port $CURRENT_PORT."
# CURRENT_PORT가 빈 문자열이거나 8081인 경우
if [ "$CURRENT_PORT" == "8081" ]; then
echo "IF CURRENT_PORT : null or 8081"
NEXT_PORT=8080
else
echo "IF CURRENT_PORT : 8080"
NEXT_PORT=8081
fi
echo "Next container will run on port $NEXT_PORT."
echo "::set-output name=next_port::$NEXT_PORT"
echo "::set-output name=current_port::$CURRENT_PORT"
- name: Run new container on the alternate port
run: |
echo "Running new container on port ${{ steps.check-port.outputs.next_port }}..."
sudo docker run -d -p ${{ steps.check-port.outputs.next_port }}:8080 \
-e SPRING_PROFILES_ACTIVE=prod -v log-volume:/app/logs --name haengdong-backend-${{ steps.check-port.outputs.next_port }} \
${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }}
- name: Wait for Application Booting 30 seconds
run: |
echo "Waiting for the application to boot..."
for ((i=1;i<=30;i++)); do
echo -n "."
sleep 1
done
echo # 줄바꿈
- name: Health check the new container
id: health-check
run: |
echo "Performing health check for the new container on port ${{ steps.check-port.outputs.next_port }}..."
HEALTH_STATUS=$(curl -s http://localhost:${{ steps.check-port.outputs.next_port }}/actuator/health | sed -n 's/.*"status":"\([^"]*\)".*/\1/p')
echo "Health check status: $HEALTH_STATUS"
if [ "$HEALTH_STATUS" != "UP" ]; then
echo "Health check failed. Rolling back..."
sudo docker rm -f haengdong-backend-${{ steps.check-port.outputs.next_port }}
exit 1
fi
echo "Health check passed."
- name: Update or create Nginx container to point to new container port
run: |
NGINX_CONTAINER_NAME="nginx-proxy"
echo "Checking if Nginx container exists..."
if sudo docker ps -a --filter "name=$NGINX_CONTAINER_NAME" --format "{{.Names}}" | grep -w $NGINX_CONTAINER_NAME; then
# Check if the Nginx container is running
if sudo docker ps --filter "name=$NGINX_CONTAINER_NAME" --format "{{.Names}}" | grep -w $NGINX_CONTAINER_NAME; then
echo "Nginx container is running."
else
echo "Nginx container exists but is not running. Starting Nginx container..."
sudo docker start $NGINX_CONTAINER_NAME
echo "Nginx container started."
fi
# Ensure nginx-conf directory and default.conf file exist
mkdir -p ./nginx-conf
# Create or update the default.conf file with the new configuration
echo "Creating or updating default.conf..."
cat > ./nginx-conf/default.conf <<EOF
server {
listen 80;
location / {
proxy_pass http://127.0.0.1:${{ steps.check-port.outputs.next_port }};
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
# Test Nginx configuration inside a temporary container
echo "Testing Nginx configuration..."
sudo docker run --rm -v $(pwd)/nginx-conf:/etc/nginx/conf.d:ro nginx nginx -t
if [ $? -eq 0 ]; then
echo "Nginx configuration test passed."
else
echo "Nginx configuration test failed. Please check the configuration file."
exit 1
fi
# Restart the Nginx container to apply changes
echo "Restarting Nginx container..."
sudo docker restart $NGINX_CONTAINER_NAME
echo "Nginx container restarted."
else
echo "Nginx container not found. Creating a new Nginx container..."
# Create nginx-conf directory
mkdir -p ./nginx-conf
# Create the default.conf file with the initial configuration
echo "Creating default.conf..."
cat > ./nginx-conf/default.conf <<EOF
server {
listen 80;
location / {
proxy_pass http://127.0.0.1:${{ steps.check-port.outputs.next_port }};
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
# Test Nginx configuration inside a temporary container
echo "Testing Nginx configuration..."
sudo docker run --rm -v $(pwd)/nginx-conf:/etc/nginx/conf.d:ro nginx nginx -t
if [ $? -eq 0 ]; then
echo "Nginx configuration test passed."
else
echo "Nginx configuration test failed. Please check the configuration file."
exit 1
fi
# Run a new Nginx container with the updated config
sudo docker run -d --name $NGINX_CONTAINER_NAME -p 80:80 \
-v $(pwd)/nginx-conf:/etc/nginx/conf.d:ro nginx
echo "New Nginx container created and running."
fi
- name: Stop and remove the old container
run: |
CURRENT_PORT=${{ steps.check-port.outputs.current_port }}
if [ -n "$CURRENT_PORT" ]; then
echo "Stopping on port $CURRENT_PORT..."
sudo docker ps --filter "publish=$CURRENT_PORT" --format "{{.ID}}" | xargs sudo docker stop
echo "Sleeping on port $CURRENT_PORT..."
sleep 15
echo "Removing on port $CURRENT_PORT..."
sudo docker ps -a --format "{{.Names}}" | grep "haengdong-backend-$CURRENT_PORT" | xargs sudo docker rm
else
echo "No container to stop and remove."
fi
# port-switch:
# needs: build
# strategy:
# matrix:
# runner: [ prod-1 , prod-2 ]
# runs-on: [ self-hosted, '${{ matrix.runner }}' ]
# steps: