---
# System prepended metadata

title: '[AWS EC2] 將GitHub程式打包成Docker自動部屬至EC2'
tags: [發佈GitHub]

---

# [AWS EC2] 將GitHub程式打包成Docker自動部屬至EC2

## :book: 設定 EC2 環境

**更新套件列表**
```
sudo apt update
sudo apt upgrade
```

**安裝必要的依賴**
```
sudo apt install -y apt-transport-https wget
```

**安裝 .Net**
```
sudo apt update && sudo apt install [package]
```

> EX:
sudo apt update && sudo apt install dotnet6 

**安裝 Docker**
```
sudo apt-get update

sudo apt-get install docker.io
```

**登入 Docker Hub**
```
docker login
```

## :book: 設定CICD文件 (Git Action)

> 流程講解：
> 1. tags: 觸發條件設定為更新tags
> 2. jobs: 將工作流程設定為Test、Deploy

```
name: Deploy to EC2

on:
  push:
    tags:
      - '*'

jobs:
  Test:
    runs-on: ubuntu-latest

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

    - name: Set up .NET SDK
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 6.0.x 
    
    - name: Build .NET app
      run: dotnet build
          
  Deploy:
    runs-on: ubuntu-latest
    needs: Test
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
    # 將BotToken 插入到 appsettings.json 中
      - name: Add BotToken
        run: |
          sed -i "s/\"BotToken\": \".*\"/\"BotToken\": \"${{ secrets.BOT_TOKEN }}\"/" appsettings.json
      - name: Login to Docker Hub
        uses: docker/login-action@v1 
        with:
          # 使用你的 Docker Hub 使用者名稱和ACCESS_TOKEN
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
        
      - name: Build and push Docker image
        uses: docker/build-push-action@v2
        with:
          context: ${{ github.workspace }}
          push: true
          tags: ${{ secrets.DOCKER_HUB_USERNAME }}/tgbot_tw_stock_polling:latest  
  
      - name: Executing remote ssh commands using ssh key
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.HOST_DNS }}
          username: ${{ secrets.USERNAME }}
          key: ${{ secrets.EC2_SSH_KEY }}
          script: |
                    # 直接在 SSH 腳本中設置 REPO_NAME
                    REPO_NAME=${{ github.repository }}
                    REPO_NAME=${REPO_NAME##*/}
                    echo "PROJECT_NAME=$REPO_NAME"
                    # 檢查 PROJECT_NAME 是否為空
                    if [ -z "$REPO_NAME" ]; then
                      echo "Error: REPO_NAME is empty"
                      exit 1
                    fi
                    # 檢查容器是否存在
                    if sudo docker ps -a --format '{{.Names}}' | grep -q "^$REPO_NAME$"; then
                      echo "Stopping and removing container: $REPO_NAME"
                      sudo docker stop $REPO_NAME || true
                      sudo docker rm $REPO_NAME || true
                      sudo docker rmi -f ${{ secrets.DOCKER_HUB_USERNAME }}/$REPO_NAME:latest || true
                    else
                      echo "Container $REPO_NAME does not exist, skipping stop/remove."
                    fi
                    # 確保映像存在
                    sudo docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/$REPO_NAME:latest
                    sudo docker run -d --name $REPO_NAME --restart=unless-stopped ${{ secrets.DOCKER_HUB_USERNAME }}/$REPO_NAME:latest
```

## :book: 設定Git Action 參數
**EC2_SSH_KEY**: 
>This will be your .pem file which you will use to login to the instance
>需要包含-----BEGIN RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

**HOST_DNS**: 
> Public DNS record of the instance, it will look something like this 
> ec2-xx-xxx-xxx-xxx.us-west-2.compute.amazonaws.com

**USERNAME**: 
> Will be the username of the EC2 instance, usually **ubuntu**

**TARGET_DIR**: 
> Is where you want to deploy your code.
> (optional, default '/home/REMOTE_USER/')
> *Ex: Bot/*

**DOCKER_HUB_USERNAME**: 
> DOCKER_HUB 帳號

**DOCKER_HUB_ACCESS_TOKEN**: 
> DOCKER_HUB > MyAccount > Security > New Access Tokens > 設定完後產生

**BOT_TOKEN**: 
>TG機器人Token

## :book: EC2 常用指令

**查看當前路徑**
```
ls
```

**移動路徑**
```
cd + 資料夾名稱 
cd .. (回到上一層)
```

**查看當前執行程序**
```
ps
```

**查看當前背景執行程式**
```
ps aux | grep dotnet
```

**移除資料夾**
```
sudo rm -rf 資料夾名稱
```

**清理 apt 快取**
```
sudo apt-get autoremove
sudo apt-get autoclean
```

## :book: Docker 常用指令

**啟動Docker**
```
sudo service docker start
```


**查看images**
```
docker images
```

**查看執行中容器**
```
docker ps
```

**啟動容器**
```
sudo docker run -d --restart=unless-stopped <容器名稱或容器ID>

#-d = 背景執行
#--restart = 重新啟動條件
```

**追蹤容器LOG**
```
docker logs -f <容器名稱或容器ID>
```

**移除images**
```
# 移除指定 REPOSITORY 和標籤的映像
docker rmi my_repository:latest

# 移除指定 REPOSITORY 的所有標籤的映像
docker rmi my_repository

# 使用通配符移除所有符合條件的映像
docker rmi my_repository:*
```

## :book: Ubuntu 系統設定

**設定虛擬記憶體**
```
#設定虛擬記憶體大小
sudo fallocate -l 4G /swapfile

#修改文件權限
sudo chmod 600 /swapfile


sudo mkswap /swapfile

sudo swapon /swapfile

```

> 參考文章
> https://www.astralweb.com.tw/how-to-manually-add-swap-to-ubuntu/