身為一個寫 Python 腳本的工程師,大家應該都有這種經驗:
你在本地端 pip install requests
跑得好好的,拍胸脯說穩了。結果程式丟到 AWS Lambda 一跑,馬上冒出一個 import error
,瞬間彷彿聽到老天爺在笑你:「哼,太天真了吧。」
在 Lambda 裡面要用 Python 套件,規矩超嚴格:程式碼 + 相依套件,全部乖乖打包成一顆 ZIP,才能上台表演。更刺激的是,這包 ZIP 檔案體重還不能超過 250MB,否則 Lambda 會直接跟你說「抱歉,本場不收超重行李」。
更慘的還在後頭:你只是改了兩行小程式,結果還是得重新打包、壓縮、上傳,搞到最後,你的日常不是在跟 Bug 打仗,而是變成「壓縮大師」。一天工作八小時,有六小時都在等壓縮條跑完,人生徹底走偏。
就在你懷疑自己是不是轉職去物流業比較快時,AWS Lambda Layer 帶著聖光降臨了。它就像 Uber Eats 外送員一樣,把套件乾乾淨淨打包好,直接送到 Lambda 手上。從此以後,你不用每天揹著整家便利商店去上班,終於可以專心寫程式,而不是扛套件。
不想用 Layer 的理由可以千奇百怪:懶得學、嫌麻煩、覺得 zip 打包是修行的一部分……但說真的,Layer 至少有幾個好處,讓人用過就回不去。
requests
。結果你乖乖打包了十次,硬碟爆哭、打包的空間也跟著掉眼淚,你的 CI/CD pipeline 更是一路塞車到環狀線。Layer 出來之後,直接一次打包,全場共享,乾淨俐落,工程師的背痛指數瞬間下降。說穿了,Layer 就是一個「額外的資料夾」,AWS Lambda 執行時會自動幫你把這個資料夾加到 PYTHONPATH
裡。
換句話說,只要你乖乖把套件丟進正確的資料夾(名字還要乖乖叫 python/
),Lambda 執行的時候就會像在本地端一樣輕鬆 import
。
一句話總結:Layer 就是共用的外掛倉庫。
在開始之前,先來一個小提醒:AWS Lambda 的執行環境其實是 Linux。意思就是——如果你在 Windows 或 Mac 上面直接亂包,八成會遇到「本地跑得好好的,丟到 Lambda 就不能用」的經典災情。要避免這種「異地相依套件水土不服症候群」,乖乖找一個 Linux 環境才是王道。
問題來了:手邊有 Linux 的人少之又少(工程師筆電 80% 都是 Mac,剩下的 Windows,多半是公司發的)。那怎麼辦?方法大概有三:
以正常人(懶人)的角度來看,Docker 幾乎是最方便的選擇。唯一的麻煩就是:你得先安裝 Docker。對,這件事對某些人來說比學 Kubernetes 還難。
好啦,這邊用 Docker 來示範(安裝的部分就不在我們這次的主題內了請自行處理)。
先在本機建立一個目錄來放 Layer:
mkdir -p C:\docker_spaces\docker-layer\my-layer
然後在裡面建一個 requirements.txt
,內容假設我們只要 pillow
,requirements.txt
的內容就如下:
pillow
目錄結構長這樣:
└─my-layer
requirements.txt
接著開啟 Windows 的 CMD,cd 到這個目錄:
cd C:\docker_spaces\docker-layer\my-layer
然後執行 Docker 指令,模擬一個跟 Lambda 一樣的 Python 環境來安裝套件。
檔案路徑: C:\docker_spaces\docker-layer\my-layer
Python: 3.13 (這裡要跟 Lambda 的 Runtime 版本一致)
docker run -v C:\docker_spaces\docker-layer\my-layer:/var/task "public.ecr.aws/sam/build-python3.13" /bin/sh -c "pip install -r requirements.txt -t python/lib/python3.13/site-packages/; zip -r layer.zip python; exit"
執行過程,大概就像以下這樣:
c:\docker_spaces\docker-layer\my-layer>docker run -v C:\docker_spaces\docker-layer\my-layer:/var/task "public.ecr.aws/sam/build-python3.13" /bin/sh -c "pip install -r requirements.txt -t python/lib/python3.13/site-packages/; zip -r layer.zip python; exit"
Collecting pillow (from -r requirements.txt (line 1))
Downloading pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (9.0 kB)
Downloading pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (6.6 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.6/6.6 MB 17.6 MB/s eta 0:00:00
Installing collected packages: pillow
Successfully installed pillow-11.3.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
[notice] A new release of pip is available: 25.1.1 -> 25.2
[notice] To update, run: pip install --upgrade pip
adding: python/ (stored 0%)
adding: python/lib/ (stored 0%)
adding: python/lib/python3.13/ (stored 0%)
adding: python/lib/python3.13/site-packages/ (stored 0%)
adding: python/lib/python3.13/site-packages/PIL/ (stored 0%)
adding: python/lib/python3.13/site-packages/PIL/AvifImagePlugin.py (deflated 68%)
adding: python/lib/python3.13/site-packages/PIL/BdfFontFile.py (deflated 59%)
adding: python/lib/python3.13/site-packages/PIL/BlpImagePlugin.py (deflated 76%)
....
....
....
c:\docker_spaces\docker-layer\my-layer>
跑完之後,如果沒有紅字 error,你會在目錄下看到一個 layer.zip
。如果你想換檔名,只要在上面指令改掉 layer.zip
就行。
別急著喝咖啡,先解開 ZIP 看看裡面的結構有沒有長對:
└─python
└─lib
└─python3.13
└─site-packages
├─PIL
│ └─__pycache__
├─pillow-11.3.0.dist-info
│ └─licenses
└─pillow.libs
如果跟上面差不多,恭喜你,Layer 已經打包成功。
接下來就要把剛剛的成果獻祭給 AWS Lambda。
進 Lambda Console → 點 Layers → Create Layer。
相關資訊的補充
py313-pillow
。注意:名稱裡不能有 .
,UI 會兇你。upload zip file
,點選 Choose file
上傳剛剛的 layer.zip
。Compatible architectures
→ 選 x86_64
(除非你真的在玩 ARM)。Compatible Runtimes
→ 勾上 python3.13
。這兩項資訊的填入,有助於我們之後在選擇套件時,可以更快速地找到可用的套件。完成後你會看到 Layer 的資訊,包含名稱、版本、支援架構跟 runtime,這就代表你正式成功了。
到這裡就整個完成了一個layer的建立,有成功的建立嗎?因為下一篇教學會用到哦!如果不成功的話,多試幾次就成功了。
最後補幾個「過來人血淚」:
node_modules
丟進 Python Layer,AWS 會直接打槍。參考資料: