퍼블릭 클라우드

AWS EC2에서 NGINX 애플리케이션을 Docker 이미지로 빌드하고 Docker Hub에 업로드하는 방법

변군이글루 2025. 1. 19. 16:49
반응형

AWS EC2에서 NGINX 애플리케이션을 Docker 이미지로 빌드하고 Docker Hub에 업로드하는 방법

1. AWS EC2 인스턴스 설정

  • Docker 설치
  • Git 설치

전체 워크플로

더보기

---

vim deploy.yml
name: Build, Deploy, and Health Check NGINX Application

on:
  push:
    branches:
      - main

env:
  AWS_REGION: us-east-1
  SECURITY_GROUP_ID: sg-07f3e
  EC2_CONTAINER_BASE_DIR: "/app/docker-container"
  APPLICATION_PORT: 80
  DOCKER_IMAGE_NAME: springboot-app


jobs:
  build:
    name: Build and Push Docker Image to Docker Hub
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Get GitHub Runner Public IP
        id: ip
        uses: haythem/public-ip@v1.3

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}

      - name: Authorize Runner IP in Security Group
        run: |
          aws ec2 authorize-security-group-ingress \
            --group-id ${{ env.SECURITY_GROUP_ID }} \
            --protocol tcp \
            --port 22 \
            --cidr ${{ steps.ip.outputs.ipv4 }}/32 || echo "IP already exists"

      - name: Deploy Docker Image
        uses: appleboy/ssh-action@v1.2.0
        with:
          host: ${{ vars.AWS_EC2_HOST }}
          username: ${{ vars.AWS_EC2_USER }}
          key: ${{ secrets.AWS_EC2_SSH_KEY }}
          script: |
            git clone https://${{ vars.MY_GITHUB_USERNAME }}:${{ secrets.MY_GITHUB_TOKEN }}@github.com/${{ vars.MY_GITHUB_USERNAME }}/${{ vars.MY_GITHUB_NAMESPACE }}.git
            cd ${{ vars.MY_GITHUB_NAMESPACE }}
            git pull origin main || { echo "Failed to pull changes"; exit 1; }
            echo "<html><head><meta charset='UTF-8'></head><body>날짜 및 시간 : $(date '+%Y년 %m월 %d일 %H시 %M분 %S초')</body></html>" > test.html
            echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login -u "${{ vars.DOCKERHUB_USERNAME }}" --password-stdin
            docker buildx rm mybuilder || true
            docker buildx create --name mybuilder --driver docker-container --use
            docker buildx build \
              --platform linux/amd64,linux/arm64 \
              --tag anti1346/playground:latest \
              --push .

      - name: Revoke Runner IP from Security Group
        run: |
          aws ec2 revoke-security-group-ingress \
            --group-id ${{ env.SECURITY_GROUP_ID }} \
            --protocol tcp \
            --port 22 \
            --cidr ${{ steps.ip.outputs.ipv4 }}/32 || echo "Failed to remove IP"

  deploy:
    name: Deploy Docker Image to EC2    
    runs-on: ubuntu-latest
    needs: build

    steps:
      - name: Get GitHub Runner Public IP
        id: ip
        uses: haythem/public-ip@v1.3

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}

      - name: Authorize Runner IP in Security Group
        run: |
          aws ec2 authorize-security-group-ingress \
            --group-id ${{ env.SECURITY_GROUP_ID }} \
            --protocol tcp \
            --port 22 \
            --cidr ${{ steps.ip.outputs.ipv4 }}/32 || echo "IP already exists"

      - name: Deploy Docker Image
        uses: appleboy/ssh-action@v1.2.0
        with:
          host: ${{ vars.AWS_EC2_HOST }}
          username: ${{ vars.AWS_EC2_USER }}
          key: ${{ secrets.AWS_EC2_SSH_KEY }}
          script: |
            mkdir -p ${{ env.EC2_CONTAINER_BASE_DIR }}
            cd ${{ env.EC2_CONTAINER_BASE_DIR }}
            docker compose down -v
            docker rmi -f $(docker images | grep ${{ env.DOCKER_IMAGE_NAME }}  | awk '{print $3}' | uniq) || true
            docker pull anti1346/playground:latest
            cat <<EOF > ${{ env.EC2_CONTAINER_BASE_DIR }}/docker-compose.yml
            services:
              ${{ env.DOCKER_IMAGE_NAME }}:
                image: anti1346/playground:latest
                container_name: ${{ env.DOCKER_IMAGE_NAME }}
                restart: unless-stopped
                ports:
                  - "${{ env.APPLICATION_PORT }}:${{ env.APPLICATION_PORT }}"
            EOF
            docker compose up -d || echo "Failed to start the container"

      - name: Revoke Runner IP from Security Group
        run: |
          aws ec2 revoke-security-group-ingress \
            --group-id ${{ env.SECURITY_GROUP_ID }} \
            --protocol tcp \
            --port 22 \
            --cidr ${{ steps.ip.outputs.ipv4 }}/32 || echo "Failed to remove IP"

  health_check:
    name: Health Check of Deployed Application
    runs-on: ubuntu-latest
    needs: deploy

    steps:
      - name: Get GitHub Runner Public IP
        id: ip
        uses: haythem/public-ip@v1.3

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}

      - name: Authorize Runner IP in Security Group
        run: |
          aws ec2 authorize-security-group-ingress \
            --group-id ${{ env.SECURITY_GROUP_ID }} \
            --protocol tcp \
            --port 22 \
            --cidr ${{ steps.ip.outputs.ipv4 }}/32 || echo "IP already exists"

      - name: Check Application Health
        uses: appleboy/ssh-action@v1.2.0
        with:
          host: ${{ vars.AWS_EC2_HOST }}
          username: ${{ vars.AWS_EC2_USER }}
          key: ${{ secrets.AWS_EC2_SSH_KEY }}
          script: |
            curl -fsSL "http://localhost:${{ env.APPLICATION_PORT }}/test.html"

      - name: Revoke Runner IP from Security Group
        run: |
          aws ec2 revoke-security-group-ingress \
            --group-id ${{ env.SECURITY_GROUP_ID }} \
            --protocol tcp \
            --port 22 \
            --cidr ${{ steps.ip.outputs.ipv4 }}/32 || echo "Failed to remove IP"

---

코드 블록 설명

Deploy Docker Image

  • GitHub 저장소에서 최신 코드를 받아옵니다.
  • Docker 이미지를 빌드하여 Docker Hub에 푸시합니다.
- name: Deploy Docker Image
  uses: appleboy/ssh-action@v1.2.0
  with:
    host: ${{ vars.AWS_EC2_HOST }}
    username: ${{ vars.AWS_EC2_USER }}
    key: ${{ secrets.AWS_EC2_SSH_KEY }}
    script: |
      git clone https://${{ vars.MY_GITHUB_USERNAME }}:${{ secrets.MY_GITHUB_TOKEN }}@github.com/${{ vars.MY_GITHUB_USERNAME }}/${{ vars.MY_GITHUB_NAMESPACE }}.git
      cd ${{ vars.MY_GITHUB_NAMESPACE }}
      git pull origin main || { echo "Failed to pull changes"; exit 1; }
      echo "<html><head><meta charset='UTF-8'></head><body>날짜 및 시간 : $(date '+%Y년 %m월 %d일 %H시 %M분 %S초')</body></html>" > test.html
      echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login -u "${{ vars.DOCKERHUB_USERNAME }}" --password-stdin
      docker buildx rm mybuilder || true
      docker buildx create --name mybuilder --driver docker-container --use
      docker buildx build \
        --platform linux/amd64,linux/arm64 \
        --tag anti1346/playground:latest \
        --push .

Deploy Docker Image

  • Docker Compose를 사용하여 기존 컨테이너를 중단하고 새로운 이미지를 풀한 후 실행합니다.
- name: Deploy Docker Image
  uses: appleboy/ssh-action@v1.2.0
  with:
    host: ${{ vars.AWS_EC2_HOST }}
    username: ${{ vars.AWS_EC2_USER }}
    key: ${{ secrets.AWS_EC2_SSH_KEY }}
    script: |
      mkdir -p ${{ env.EC2_CONTAINER_BASE_DIR }}
      cd ${{ env.EC2_CONTAINER_BASE_DIR }}
      docker compose down -v
      docker rmi -f $(docker images | grep ${{ env.DOCKER_IMAGE_NAME }}  | awk '{print $3}' | uniq) || true
      docker pull anti1346/playground:latest
      cat <<EOF > ${{ env.EC2_CONTAINER_BASE_DIR }}/docker-compose.yml
      services:
        ${{ env.DOCKER_IMAGE_NAME }}:
          image: anti1346/playground:latest
          container_name: ${{ env.DOCKER_IMAGE_NAME }}
          restart: unless-stopped
          ports:
            - "${{ env.APPLICATION_PORT }}:${{ env.APPLICATION_PORT }}"
      EOF
      docker compose up -d || echo "Failed to start the container"

Check Application Health

  • 애플리케이션의 건강 상태를 확인하기 위해 curl을 사용하여 test.html 페이지에 접근합니다. 해당 페이지는 build 작업에서 날짜 및 시간이 포함된 HTML로 생성됩니다.
- name: Check Application Health
  uses: appleboy/ssh-action@v1.2.0
  with:
    host: ${{ vars.AWS_EC2_HOST }}
    username: ${{ vars.AWS_EC2_USER }}
    key: ${{ secrets.AWS_EC2_SSH_KEY }}
    script: |
      curl -fsSL "http://localhost:${{ env.APPLICATION_PORT }}/test.html"

 

AWS EC2에서 NGINX 애플리케이션을 Docker로 빌드하여 Docker Hub에 푸시하고 해당 이미지를 사용하여 애플리케이션을 배포하며 최종적으로 애플리케이션의 상태를 확인하는 GitHub Actions 워크플로우를 자동화하는 과정입니다.

 

728x90
반응형