Elastic Beanstalk 上的 Metabase 怎麼升級

EB 上的 Metabase 升級,其實只是把 Dockerrun.aws.json 裡的 image tag 改一行。這篇記錄我從 0.56.8 升到 0.63 的完整流程,含備份跟 rollback。

黑暗機房裡泛綠光的網路機櫃,線材整齊接在 patch panel 上
Photo by Tyler on Unsplash

這篇是我 2026 年 9 月把 Metabase 從 0.56.8 升到 0.63.16.6 的紀錄。環境是 AWS Elastic Beanstalk(底下簡稱 EB),全部在 CloudShell 裡跑完,不用下載任何東西到自己電腦。

下次要升級,改一個版本號,從頭跑到尾就好。

先講結論:升級就是改一行字

EB 上的 Metabase 就是一個 Docker container。整包 source bundle 裡,真正決定「跑哪個版本」的只有 Dockerrun.aws.json 這個檔案裡的 image tag:

"Name": "metabase/metabase:v0.56.8"   →   "Name": "metabase/metabase:v0.63.16.6"

其他檔案都是你自己的環境設定,一個都不能少:

  • .ebextensions/:metabase-setup.sh、CloudWatch、Papertrail 這些
  • .platform/:nginx.conf、nginx-ssl.conf、postdeploy hooks

所以正確做法不是去 Metabase 官網重抓一包空的 metabase-aws-eb.zip。而是把你現在正在跑的那包從 S3 拉下來,改一行,再上架回去。

順帶一提,Metabase 官方文件已經不建議用 EB 跑 production 了。所以這套流程要自己維護,這篇就是維護說明。

我的環境

你的值會不一樣,底下的指令把 <...> 換成自己的就好。

  • 平台:Docker on 64bit Amazon Linux 2023
  • 部署策略:AllAtOnce,MinSize 1 / MaxSize 2,前面掛 ALB
  • Application DB:掛在 EB 環境上的 RDS PostgreSQL 16
  • Region:ap-northeast-1

七個步驟

0. 設好變數

下次升級只要改 NEW 和 OLD,其他照抄。開 CloudShell(Console 左下角),貼這段:

# 下次升級只要改這兩行
NEW=0.63.16.6          # 要升到的版本
OLD=0.56.8-1           # 目前跑的 application version label

APP=<你的 EB application 名稱>
ENV=<你的 EB environment 名稱>
BUCKET=elasticbeanstalk-<region>-<account-id>
DB=<你的 RDS instance identifier>
SNAP=metabase-pre-$(date +%Y%m%d-%H%M)

export AWS_PAGER=""   # 不然輸出會卡在 less 裡

先確認這個 tag 真的存在,免得部署一個不存在的 image:

curl -s -o /dev/null -w '%{http_code}\n' https://hub.docker.com/v2/repositories/metabase/metabase/tags/v$NEW

要回 200。

1. 備份 application database

Metabase 一啟動就會跑 schema migration,而且不會自動降版。整個流程只有這一步不能省。出事的時候,能救你的只有這顆快照。

aws rds create-db-snapshot \
  --db-instance-identifier $DB \
  --db-snapshot-identifier $SNAP

aws rds wait db-snapshot-available --db-snapshot-identifier $SNAP && echo READY

看到 READY 再往下。小資料庫大概 2 到 5 分鐘。快照本身不影響線上服務。

2. 找出目前的 source bundle 在哪

EB 把每一版部署包都存在 S3。用指令查目前這版的 key,不用去 Console 點:

aws elasticbeanstalk describe-application-versions \
  --application-name $APP \
  --query 'ApplicationVersions[].[VersionLabel,SourceBundle.S3Key]' \
  --output text

# 輸出長這樣:
#   0.56.8-1   1759489403130-metabase-deploy.zip
#   0.56.8     1759487844154-metabase-deploy.zip

KEY=1759489403130-metabase-deploy.zip   # 換成 $OLD 那一列的 key

3. 下載、改 image tag、重新打包

重點在最後那行 zip。一定要 cd 進解壓後的資料夾裡面再打包。如果把外層資料夾一起包進去,EB 會找不到 Dockerrun.aws.json。. 開頭的目錄也要包到。

cd ~ && rm -rf mb && mkdir -p mb/src && cd mb
aws s3 cp s3://$BUCKET/$KEY cur.zip
cd src && unzip -o ../cur.zip

# 只改 image tag,其他都不動
sed -i "s#metabase/metabase:v[0-9.]*#metabase/metabase:v$NEW#" Dockerrun.aws.json
cat Dockerrun.aws.json          # 用眼睛確認一下

zip -r ../new.zip . -x '*.DS_Store'
cd .. && unzip -l new.zip      # 應該看到 .ebextensions/ 跟 .platform/ 都在

4. 上傳並建立 application version

這步還不會部署,只是把新版本上架。做完可以去 Console 的 Application versions 看一眼有沒有出現。

aws s3 cp new.zip s3://$BUCKET/metabase-$NEW-deploy.zip

aws elasticbeanstalk create-application-version \
  --application-name $APP \
  --version-label $NEW \
  --description "Metabase v$NEW" \
  --source-bundle S3Bucket=$BUCKET,S3Key=metabase-$NEW-deploy.zip

回傳的 Status 是 UNPROCESSED 很正常。EB 只對 Java、PHP 這類 bundle 做預處理,Docker 的不會。

5. 部署

我的部署策略是 AllAtOnce:所有機器同時換,中間會斷線幾分鐘。好處是不會出現新舊版同時連同一顆 DB 的狀況,對 Metabase 的 migration 反而比較安全。挑離峰時間跑。

aws elasticbeanstalk update-environment \
  --environment-name $ENV --version-label $NEW

aws elasticbeanstalk wait environment-updated --environment-name $ENV

aws elasticbeanstalk describe-environments --environment-names $ENV \
  --query 'Environments[0].[Status,Health,VersionLabel]' --output text
# 期望:Ready   Green   0.63.16.6

卡住或變紅的話,去環境的 Events 分頁看,或用 aws elasticbeanstalk retrieve-environment-info 拉 log。

6. 驗證真的換版了

EB 顯示的 version label 只是你自己取的名字,不代表 container 真的跑那版。要問 Metabase 自己:

URL=https://<你的 metabase 網址>

curl -s -o /dev/null -w 'health:%{http_code}\n' $URL/api/health

curl -s $URL/api/session/properties \
  | python3 -c "import sys,json;print(json.load(sys.stdin)['version'])"
# {'date': '2026-09-04', 'tag': 'v0.63.16.6', 'hash': '05fdcf7'}

出事了怎麼退回去

Metabase 升級會改資料庫 schema,所以只把 image 換回舊版是起不來的。rollback 一定是兩件事一起做:

# 1. 應用退版
aws elasticbeanstalk update-environment --environment-name $ENV --version-label $OLD

# 2. 資料庫從升級前的快照還原(會建出一台新的 RDS instance)
aws rds restore-db-instance-from-db-snapshot \
  --db-instance-identifier metabase-restore-$(date +%Y%m%d) \
  --db-snapshot-identifier $SNAP

快照不要急著刪。升完跑個幾天,確定沒問題再清。

幾個會踩到的坑

  • 可以跳版。 0.40 以上可以直接跳到最新,不用一版一版升。只有 0.40 以下才要逐版爬。
  • 打包位置。 要在解壓資料夾裡面 zip,而且一定要帶到 .ebextensions/ 跟 .platform/。少了 nginx 設定或 metabase-setup.sh,環境會起來,但行為不對。
  • DB 跟環境綁在一起。 如果你的 application DB 是掛在 EB 環境上的 RDS,原地部署沒問題。但哪天要「重建環境」,這台 RDS 會跟著環境一起被砍。那種情況要先把 DB 拆成獨立的 instance。
  • 版本壽命很短。 非 LTS 版大概發布後兩個月就停止支援,LTS 是 14 個月。0.63 支援到 2026-11,0.58 是 LTS,支援到 2027-02。
  • 舊環境的 Deprecated 警告。 如果 Console 一直跳平台已棄用的警告,先看是不是另一個沒在用的舊環境發出來的。確認沒人用再終止,而且要先確認它的 RDS 不是跟現役環境共用的。

升完之後:開啟 AI 功能

自架版的 Metabot 要自己帶 LLM API key。Metabase 自家的 AI Service 只給 Metabase Cloud 用。位置在 Admin settings → AI:選 provider(Anthropic、OpenAI、Amazon Bedrock、Azure、Mistral、OpenRouter、Z.AI),填 key,選 model,開 Metabot。

如果你本來就在 AWS 上,用 Amazon Bedrock 可以同帳號同區走 IAM,不用另外管一組 key。

參考