iT邦幫忙

2026 iThome 鐵人賽

DAY 23
0
IT Operation

從前後端踏上 AWS 雲端架構勇者之路系列 第 23 篇

把 ECR 的 Image 拉到 EC2,用 Compose 跑起 API

  • 分享至 

  • xImage
  •  

前篇已經把 demo-api:v1 推上 ECR,不過 Image 放上去後,API 就會自己開始跑了嗎?

還不會哩,ECR 負責保存 Image,接下來還得有一台主機,把它下載下來並啟動。今天就來換 EC2 來做這件事啦!

我們會先準備 EC2 裡的 Docker,再把啟動設定寫進 Compose,最後在主機裡用 curl 呼叫 /health。看到 HTTP 200,才知道 API 真的有在處理請求

先把這三個地方分開看:程式在自己電腦修改打包,ECR 保存打包好的 Image,EC2 才是讓 API 持續執行的地方。今天會一直在 EC2 的 SSH 視窗操作,只有產生 SSH 金鑰時會切回自己的電腦

程式在本機打包並 push 到 ECR,再由 EC2 pull 下來,依 Compose 設定啟動 API

這次沿用東京區域的 demo-api Repository,裡面已有前篇的 ARM64、v1 Image。EC2 使用 Ubuntu 24.04、ARM64,放在 Public Subnet,有公有 IP 與對外路由,才下載得到套件和 Image

EC2 透過既有 Role 下載這個 Repository 的權限,請先自行準備好。SSH 的 22 則維持自己目前的公有 IP /32,只讓自己這邊連進去

下面是 EC2 → Instances → Launch instances 裡的實際選單。在 Application and OS Images 選 Ubuntu,再從 Amazon Machine Image 下拉選單選 Ubuntu Server 24.04 LTS,Architecture 選 64-bit (Arm)。只點 Ubuntu 圖示還不夠,版本與架構也要看哦

AWS EC2 建立頁:Ubuntu Server 24.04 LTS,Architecture 已選取 64-bit Arm

圖中是建立表單的設定畫面。AMI ID 會隨更新改變,確定 24.04、Arm、Username 是 ubuntu 就好;Instance type 也要搭配支援 ARM 的型號,例如 t4g.micro。已有符合規格的 EC2,就沿用原本那台

再來用前面練過的 SSH,以 ubuntu 登入自己的 EC2。下面的安裝指令都在 EC2 執行~

先執行 uname -m,本篇的 ARM64 主機應顯示 aarch64

執行 aws --version;已有 AWS CLI v2 就略過安裝。還沒有的話,在 EC2 執行:

sudo apt update
sudo apt install -y curl unzip
mkdir -p ~/aws-cli-setup
cd ~/aws-cli-setup
curl -fL https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip -o awscliv2.zip
unzip awscliv2.zip
sudo ./aws/install
aws --version

這段是下載 ARM64 安裝檔、解壓縮並安裝,最後應看到 aws-cli/2...(附上 AWS CLI 安裝說明)

在 EC2 準備 Docker

前兩天裝的是自己電腦上的 Docker,現在換了一台 EC2,裡面也得準備好,才能執行下載回來的 Image

這裡繼續用 ubuntu 安裝 Docker Engine,以及等一下要用來管理啟動設定的 Compose

這裡先安來光過 Docker 的 Ubuntu 24.04 ARM64 練習主機~

先加入 Docker 官方套件來源:

sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: noble
Components: stable
Architectures: arm64
Signed-By: /etc/apt/keyrings/docker.asc
EOF

從 sudo tee 到最後的 EOF 要整段一起貼。noble 是 Ubuntu 24.04 的代號,arm64 是這台 EC2 的架構

再安裝、啟動並測試:

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo docker run --rm hello-world

看到 Hello from Docker!,代表 Docker 能下載並執行測試容器,接下來才換成自己的 API

接下來,誰負責在主機上執行部署?

剛才用 ubuntu 安裝軟體,是在做系統管理。接下來下載 Image、啟動 API,我們另外建一個 Linux 帳號 deployer,替它準備自己的 SSH 金鑰

1. 在 EC2 建立帳號

接著繼續在在 ubuntu 的 SSH 視窗執行。如果已經有 deployer,就沿用它的設定,略過新增帳號和金鑰這段,別覆蓋原有的登入資料:

sudo adduser --disabled-password --gecos '' deployer
sudo install -d -m 700 -o deployer -g deployer /home/deployer/.ssh
sudo usermod -aG docker deployer

2. 在自己的電腦產生金鑰

保留剛才的 SSH 視窗,在自己的電腦另開終端機。Mac 終端機或 Windows PowerShell 都可以:

cd ~
ssh-keygen -t ed25519 -f ./demo-api-deployer -C "demo-api-deployer"

目錄會出現兩個檔案:demo-api-deployer 是私鑰,留在自己的電腦;demo-api-deployer.pub 是公鑰,等一下放進 EC2。用文字編輯器打開 .pub,複製那一整行 ssh-ed25519 ... 內容

兩個檔案長得很像,差別就在這裡:EC2 收的是公鑰內容,私鑰留在自己電腦,登入時交給 ssh -i 使用

自己的電腦保留 SSH 私鑰,公鑰內容放進 EC2 deployer 的 authorized_keys

3. 把公鑰放進 deployer

切回 EC2 的 ubuntu 視窗,開啟公鑰清單:

sudo nano /home/deployer/.ssh/authorized_keys

貼上剛才的公鑰整行,按 Ctrl+O、Enter 儲存,再按 Ctrl+X 離開

Mac 也是 Control,不是 Command。接著設定檔案擁有者與權限:

sudo chown deployer:deployer /home/deployer/.ssh/authorized_keys
sudo chmod 600 /home/deployer/.ssh/authorized_keys

回到自己電腦的新終端機,把 IP 換成自己的 EC2 公有 IP。假如剛才改過金鑰檔名,路徑也要一起改:

ssh -i "$HOME/demo-api-deployer" deployer@自己的EC2公有IP

登入後執行:

whoami
docker version
docker compose version

依序應看到 deployer、Docker 的 Client/Server,以及 Compose 版本。這幾項都對上,再繼續下載 Image

每次部署,都要重打一串 docker run 嗎?

前幾天我們用 docker run 指定 Image 和 port。現在搬到 EC2,之後還要更新版本,如果每次都重新打一串指令,就得記得上次是怎麼啟動的

這時可以把設定寫成一份檔案,交給 Docker Compose 讀取。裡面記著要用哪個 Image、連哪個 port,下次更新也有檔案可以對照,不一定要很多個 Container 才能用

Image URI 要去哪裡複製?

先回到 AWS 網頁,區域切到東京:

  1. Amazon ECR → Private registry → Repositories,進自己的 demo-api
  2. 在 Images 分頁找前篇上傳的 v1,勾選那一列
  3. 按 Copy URI,等一下貼到 Compose 的 image

https://ithelp.ithome.com.tw/upload/images/20261005/20040221zwkMNISgbo.jpg

這張用我舊的 server Repository 示範按鈕位置,裡面是以前的版本。你要選的是自己的 demo-api:v1,不用照圖改成 server 或 v0.0.1

在 EC2 建立 Compose 設定

後面流程請都在 EC2 的 deployer 視窗執行,這裡就不用加 sudo,避免 Docker 登入資料存到另一個帳號底下

mkdir -p ~/demo-api-deploy
cd ~/demo-api-deploy
nano compose.yaml

~ 是目前帳號的目錄,因此這份檔案會放在 EC2 的 /home/deployer/demo-api-deploy。自己的電腦則保留前幾篇的程式碼,用來修改跟打包上傳

貼入下面設定,image 換成自己的完整 Image URI。完成後一樣 Ctrl+O、Enter 儲存,Ctrl+X 離開:

services:
  api:
    image: YOUR_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/demo-api:v1
    platform: linux/arm64
    ports:
      - "127.0.0.1:8080:8080"
    restart: unless-stopped
    logging:
      driver: local
      options:
        max-size: "10m"
        max-file: "3"

api 是我們替這個服務取的名字。127.0.0.1:8080:8080 則沿用前面的做法,只讓 EC2 主機內部連進來,所以 SG 不用對外開 8080

為什麼有兩個 8080?前面是 EC2 主機接收請求的 port,後面是 Container 裡 API 監聽的 port

最前面的 127.0.0.1,主要是把這個入口限制在 EC2 自己

Compose ports 對照:EC2 的 127.0.0.1:8080 轉到 API 容器的 8080,外部電腦無法直接連入

所以等一下的 curl 要在 EC2 的 SSH 視窗 執行。在自己 Mac/Windows 打 127.0.0.1,連到的是自己電腦,不會連到 EC2

下面的 restart 管理重新啟動方式,logging 則限制日誌大小,避免檔案一直累積

把 ECR 裡的 Image 跑起來

設定檔存好了,接下來由 AWS CLI 取得 ECR 登入 Token,交給 Docker 登入,再下載並啟動 Image

接下來在 EC2 的 ~/demo-api-deploy,將 YOUR_ACCOUNT_ID 換成自己的:

REGISTRY=YOUR_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com
aws ecr get-login-password --region ap-northeast-1 \
  | docker login --username AWS --password-stdin "$REGISTRY"
docker compose config --quiet
docker compose pull
docker compose up -d
docker compose ps
curl -i http://127.0.0.1:8080/health

登入應看到 Login Succeeded;config --quiet 檢查 Compose 格式,成功通常沒有文字。pull 下載 Image,up -d 才啟動,最後 ps 的 api 順利的話會顯示 Up,/health 回 HTTP 200 與 {"status":"ok"}

指定 Compose 裡的版本,依序下載 Image、啟動 Container,再測試 HTTP

圖中的 v2 是之後更新的例子,今天還是用 v1。這裡換個條件問一下,假設你在自己電腦改好程式,把 v2 推上 ECR,EC2 上的 API 會自動變新版嗎?

答案是不會哩,EC2 的 Compose 還寫著 v1,它根本不知道你想換版本。所以要先改 image,再依序 pull、up -d,最後看 HTTP 回應,才知道新版有沒有真的跑起來

遇到問題可以先對照一下:

可能卡在哪裡 那要看什麼?
ECR 登入或下載被拒 是否已備妥這個 Repository 的下載權限、URI 是否填對;登入過期就重新執行登入指令
Container 顯示 Exited/Restarting 在部署目錄執行 docker compose logs --tail=50 api,看程式啟動錯誤
出現 exec format error Image 和 EC2 是否都是 ARM64

ECR 的 Docker 登入 Token 有效 12 小時。下次部署遇到登入過期,就再執行一次上面的登入指令~

回頭看剛才的流程圖,pull 是下載,up -d 才是啟動,最後再用 /health 確認有沒有回應。三個步驟都做到,那就恭喜妳,真的把 ECR 裡的成品搬到 EC2 跑起來啦 (灑花

不過 API 會回應,還沒辦法證明它查得到資料庫。下一篇繼續接 Private RDS,把這個網站做更深入的整合~

練習完可以到到 EC2 → Instances → 選取練習主機 → Instance state → Stop instance,確認狀態變成 Stopped

另外停止容器不等於停止 EC2;EBS 磁碟與保留的 Elastic IP 還是會計費,別誤按 Terminate 勒,我們下篇見 :D


上一篇
ECR:把本機的 Docker Image 推上 AWS
下一篇
Container 跑起來了,為什麼還連不到私有 RDS?
系列文
從前後端踏上 AWS 雲端架構勇者之路 共 26 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言