前篇已經把 demo-api:v1 推上 ECR,不過 Image 放上去後,API 就會自己開始跑了嗎?
還不會哩,ECR 負責保存 Image,接下來還得有一台主機,把它下載下來並啟動。今天就來換 EC2 來做這件事啦!
我們會先準備 EC2 裡的 Docker,再把啟動設定寫進 Compose,最後在主機裡用 curl 呼叫 /health。看到 HTTP 200,才知道 API 真的有在處理請求
先把這三個地方分開看:程式在自己電腦修改打包,ECR 保存打包好的 Image,EC2 才是讓 API 持續執行的地方。今天會一直在 EC2 的 SSH 視窗操作,只有產生 SSH 金鑰時會切回自己的電腦
這次沿用東京區域的 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 圖示還不夠,版本與架構也要看哦
圖中是建立表單的設定畫面。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 安裝說明)
前兩天裝的是自己電腦上的 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 金鑰
接著繼續在在 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
保留剛才的 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 使用
切回 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 指定 Image 和 port。現在搬到 EC2,之後還要更新版本,如果每次都重新打一串指令,就得記得上次是怎麼啟動的
這時可以把設定寫成一份檔案,交給 Docker Compose 讀取。裡面記著要用哪個 Image、連哪個 port,下次更新也有檔案可以對照,不一定要很多個 Container 才能用
先回到 AWS 網頁,區域切到東京:
demo-api
v1,勾選那一列image

這張用我舊的 server Repository 示範按鈕位置,裡面是以前的版本。你要選的是自己的 demo-api:v1,不用照圖改成 server 或 v0.0.1
後面流程請都在 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 自己
所以等一下的 curl 要在 EC2 的 SSH 視窗 執行。在自己 Mac/Windows 打 127.0.0.1,連到的是自己電腦,不會連到 EC2
下面的 restart 管理重新啟動方式,logging 則限制日誌大小,避免檔案一直累積
設定檔存好了,接下來由 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"}
圖中的 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