VS Codeを使わずに Dev Container CLI + AWS SAM で Python 3.11 Lambda 開発環境を作る
はじめに
AWS Lambda の開発環境として、以下を満たす構成を作りました。
- Linux
- Docker
- Dev Container
- Python 3.11 固定
- AWS CLI
- AWS SAM CLI
- Lambda API のローカル実行
- HTML から API を呼び出す
- VS Code は使用しない
一般的に Dev Container というと VS Code の Dev Containers 拡張機能を使う例が多いですが、今回は開発端末の負荷を抑えたかったため、CLI中心の構成にしました。
エディタも Vim / nano を中心にしています。
最終的には、ブラウザからボタンを押すと、
{
"message": "hello"
}
を返す Lambda API を呼び出せるところまで構築します。
構成
全体像は以下です。
クライアントPC
│
│ SSH / Tailscale
▼
Ubuntu Server
│
├─ Docker Engine
│ │
│ ├─ Dev Container
│ │ └─ Python 3.11
│ │
│ └─ AWS SAM用コンテナ
│ └─ Lambda Python 3.11環境
│
├─ Dev Container CLI
├─ AWS CLI
└─ AWS SAM CLI
ポイントは、Dev ContainerもSAMのローカルLambdaも、最終的にはDockerコンテナとして動作することです。
違うのは用途です。
Docker
├─ Dev Container
│ └─ 人間が開発するための環境
│
└─ AWS SAM Container
└─ Lambdaのビルド・実行環境を再現
検証環境
今回使用した環境です。
Host OS:
Ubuntu Server 26.04.1 LTS
Docker:
Docker Engine 29.8.0
Docker Compose:
v5.5.1
Docker Buildx:
v0.37.1
Dev Container CLI:
0.89.0
Dev Container:
Debian 12 bookworm
Python 3.11.16
AWS CLI:
2.36.45
AWS SAM CLI:
1.166.2
Ubuntu Server 自体は仮想マシンとして動かしています。
1. Docker Engineをインストール
まず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: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
更新。
sudo apt update
Dockerをインストールします。
sudo apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
確認。
sudo systemctl status docker --no-pager
さらに実際にコンテナを起動します。
sudo docker run hello-world
成功すると、
Hello from Docker!
と表示されます。
sudoなしでDockerを使えるようにする
sudo usermod -aG docker $USER
一度SSHからログアウトして再ログインします。
その後、
docker run hello-world
がsudoなしで動けばOKです。
バージョン確認。
docker --version
docker compose version
docker buildx version
2. CLI開発環境を準備
今回はGUIエディタを中心にせず、CLIで作業します。
sudo apt install -y git tmux tree jq ripgrep vim nano
主な用途は以下です。
| ツール | 用途 |
|---|---|
| Vim | コード・設定ファイル編集 |
| nano | 新規ファイル作成・貼り付け |
| tmux | SSH切断後もセッション維持 |
| Git | バージョン管理 |
| tree | ディレクトリ構造確認 |
| jq | JSON処理 |
| ripgrep | 高速検索 |
個人的には、
Vim = 編集
nano = 新規作成・コピペ
くらいの使い分けがかなり快適でした。
3. プロジェクトを作成
mkdir -p ~/projects/saas-poc
cd ~/projects/saas-poc
ディレクトリを作ります。
mkdir -p \
.devcontainer \
docs \
logs/evidence \
src \
html \
scripts
確認。
tree -a
saas-poc/
├── .devcontainer/
├── docs/
├── html/
├── logs/
│ └── evidence/
├── scripts/
└── src/
4. Gitリポジトリを作る
git init
git branch -m main
以後の初期ブランチも main にします。
git config --global init.defaultBranch main
Gitのユーザー情報を、このリポジトリだけに設定します。
git config user.name "<YOUR_GIT_NAME>"
git config user.email "<YOUR_EMAIL>"
5. Dev Container CLIをインストール
今回はVS Codeを使わないので、Dev Container CLIを直接使用します。
インストーラーを取得します。
curl -fsSL \
https://raw.githubusercontent.com/devcontainers/cli/main/scripts/install.sh \
-o /tmp/devcontainer-install.sh
実行前に中身を見ることもできます。
less /tmp/devcontainer-install.sh
インストール。
sh /tmp/devcontainer-install.sh
PATHを追加します。
echo 'export PATH="$HOME/.devcontainers/bin:$PATH"' >> ~/.bashrc
export PATH="$HOME/.devcontainers/bin:$PATH"
確認。
which devcontainer
devcontainer --version
今回の環境では、
/home/<user>/.devcontainers/bin/devcontainer
0.89.0
となりました。
6. Python 3.11 Dev Containerを作る
.devcontainer/Dockerfile を作ります。
FROM python:3.11-bookworm
WORKDIR /workspace
次に、
.devcontainer/devcontainer.json
を作ります。
{
"name": "saas-python311",
"build": {
"dockerfile": "Dockerfile"
},
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
"workspaceFolder": "/workspace"
}
この設定では、
ホスト
~/projects/saas-poc
│
│ bind mount
▼
Dev Container
/workspace
という関係になります。
Dev Containerを起動
devcontainer up --workspace-folder .
初回は python:3.11-bookworm のDockerイメージを取得するため、少し時間がかかります。
成功すると、
{
"outcome": "success"
}
を含む結果が表示されます。
Pythonを確認します。
devcontainer exec --workspace-folder . python --version
今回の結果は、
Python 3.11.16
でした。
コンテナOSも確認します。
devcontainer exec --workspace-folder . cat /etc/os-release
Debian GNU/Linux 12 (bookworm)
つまり、
Host:
Ubuntu Server 26.04
Dev Container:
Debian 12
Python 3.11
と、ホストOSから分離できています。
7. Dev Container内でPythonを実行
src/hello.py を作ります。
import platform
import sys
print("Hello from Dev Container!")
print(f"Python: {sys.version}")
print(f"Platform: {platform.platform()}")
実行。
devcontainer exec --workspace-folder . python src/hello.py
結果。
Hello from Dev Container!
Python: 3.11.16 ...
Platform: Linux-...
これで、
Dev Container上でPython 3.11を固定してコードを実行できる
ことを確認できました。
8. AWS CLIをインストール
AWS CLI v2のインストーラーを取得します。
curl -fsSL \
https://awscli.amazonaws.com/v2/install.sh \
-o /tmp/aws-cli-install.sh
実行時に unzip が必要でした。
sudo apt install -y unzip
再度実行。
bash /tmp/aws-cli-install.sh
PATH追加。
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
export PATH="$HOME/.local/bin:$PATH"
確認。
which aws
aws --version
今回の結果。
aws-cli/2.36.45
AWSリージョンを設定
認証情報を入れる前に、リージョンだけ設定しました。
aws configure set region ap-northeast-1
確認。
aws configure get region
ap-northeast-1
9. AWS SAM CLIをインストール
Linux x86_64版を取得します。
cd /tmp
curl -fL \
https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip \
-o aws-sam-cli-linux-x86_64.zip
展開。
rm -rf /tmp/sam-installation
mkdir -p /tmp/sam-installation
unzip -q \
/tmp/aws-sam-cli-linux-x86_64.zip \
-d /tmp/sam-installation
インストール。
sudo /tmp/sam-installation/install
確認。
which sam
sam --version
今回の結果。
/usr/local/bin/sam
SAM CLI, version 1.166.2
10. Lambda Hello APIを作る
ディレクトリを作ります。
mkdir -p src/hello_api
src/hello_api/app.py
import json
def lambda_handler(event, context):
return {
"statusCode": 200,
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
},
"body": json.dumps({
"message": "hello"
})
}
11. SAM template.yamlを作る
プロジェクト直下に template.yaml を作ります。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
HelloFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/hello_api/
Handler: app.lambda_handler
Runtime: python3.11
Architectures:
- x86_64
Events:
HelloApi:
Type: Api
Properties:
Path: /hello
Method: get
意味は以下です。
CodeUri
→ Lambdaソースコード
Handler
→ app.py の lambda_handler()
Runtime
→ Python 3.11
Path
→ /hello
Method
→ GET
12. SAMテンプレートを検証
sam validate
結果。
template.yaml is a valid SAM Template
さらにlint。
sam validate --lint
こちらも成功しました。
13. Dockerを使ってLambdaをビルド
sam build --use-container
ここが面白いところです。
SAM CLIが以下のようなDockerイメージを取得します。
public.ecr.aws/sam/build-python3.11
つまり、
SAM CLI
↓
Docker Engine
↓
Python 3.11 Lambda build container
という構造です。
成功すると、
Build Succeeded
と表示されます。
成果物は、
.aws-sam/
└── build/
├── HelloFunction/
│ └── app.py
└── template.yaml
に生成されます。
14. Lambda APIをローカル起動
sam local start-api --host 0.0.0.0
今回、別PCから検証するため 0.0.0.0 で待ち受けています。
ローカルPCだけで使用する場合は、デフォルトの 127.0.0.1 のままでも構いません。
起動すると、
Mounting HelloFunction at http://0.0.0.0:3000/hello [GET]
のように表示されます。
curlでAPI確認
別ターミナルから、
curl -i http://<SERVER_IP>:3000/hello
実際の結果。
HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: *
{"message": "hello"}
これで、
HTTP Request
↓
SAM local API
↓
Docker Lambda Runtime
↓
Python 3.11
↓
lambda_handler()
↓
{"message":"hello"}
まで動作しました。
15. HTMLからLambda APIを呼ぶ
html/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Lambda Hello API</title>
</head>
<body>
<h1>AWS Lambda API Test</h1>
<button id="call-api">APIを呼び出す</button>
<pre id="result">まだ呼び出していません</pre>
<script>
const button = document.getElementById("call-api");
const result = document.getElementById("result");
button.addEventListener("click", async () => {
result.textContent = "loading...";
try {
const response =
await fetch("http://<SERVER_IP>:3000/hello");
const data = await response.json();
result.textContent =
JSON.stringify(data, null, 2);
} catch (error) {
result.textContent = String(error);
}
});
</script>
</body>
</html>
16. 簡易HTMLサーバーを起動
今回は検証だけなのでPython標準のHTTPサーバーを使用します。
cd html
python3 -m http.server 8000 --bind 0.0.0.0
ブラウザから、
http://<SERVER_IP>:8000/
へアクセスします。
ボタンを押すと、
{
"message": "hello"
}
が表示されました。
Dev ContainerとSAMコンテナの違い
途中で少し混乱したので、整理しておきます。
両方とも普通のDockerコンテナです。
Docker Engine
│
├─ Dev Container
│ └─ 開発環境
│
└─ SAM Container
└─ Lambda環境再現
Dev Containerは、
開発者がコードを書くための環境
SAMのコンテナは、
AWS Lambdaに近い環境でビルド・実行するための環境
という違いです。
コンテナ技術そのものが違うわけではありません。
VS Codeを使わなくてもDev Containerは使える
今回一番確認したかった点です。
一般的には、
VS Code
↓
Dev Containers Extension
↓
Docker
という使い方が多いですが、CLIなら、
Terminal
↓
devcontainer CLI
↓
Docker
で動かせます。
起動。
devcontainer up --workspace-folder .
実行。
devcontainer exec --workspace-folder . python --version
VS Codeは便利なフロントエンドですが、Dev Containerそのものではありません。
CLI中心で作業したい場合は、Dev Container CLIだけでも十分利用できます。
Gitで段階ごとに記録
今回は構築過程もGitに残しました。
chore: initialize SaaS PoC development environment
feat: add Python 3.11 Dev Container environment
feat: add local AWS SAM hello API and HTML client
こうしておくと、
Dockerホスト
↓
Dev Container
↓
AWS SAM
↓
Lambda API
のどこで何を追加したか追いやすくなります。
また、検証結果も、
logs/
└── evidence/
├── 00-host-environment.txt
├── 01-devcontainer-cli.txt
├── 02-devcontainer-python311.txt
├── 03-aws-cli.txt
├── 04-sam-cli.txt
├── 05-sam-build.txt
└── 06-hello-api-html.txt
のように残しています。
今回できたこと
最終的に以下を確認できました。
Ubuntu Server
↓
Docker Engine
↓
Dev Container CLI
↓
Python 3.11
↓
AWS CLI
↓
AWS SAM CLI
↓
SAM Template
↓
Docker Lambda Runtime
↓
Python Lambda
↓
GET /hello
↓
HTML fetch()
↓
Browser
GUI IDEを使わなくても、かなり快適にAWS Lambdaの開発環境を構築できました。
今後
次は、この環境を使って以下を作る予定です。
ファイル登録API
↓
データ一覧
↓
キー検索
↓
ベクトル登録
↓
ベクトル類似検索
↓
Top 10表示
保存先についても、
Local PoC
├─ File → Local filesystem
├─ Metadata → SQLite
└─ Vector → PostgreSQL + pgvector
AWS
├─ File → S3
├─ Metadata → DynamoDB
└─ Vector → pgvector / OpenSearch
のように段階的に検証していく予定です。
まとめ
今回やってみて、Dev Containerについての理解がかなり変わりました。
最初は、
Dev Container = VS Codeの機能
に近いイメージを持っていました。
実際には、
Docker上に再現可能な開発環境を定義する仕組みで、VS Codeはその操作手段の一つ
と考える方が理解しやすかったです。
また、AWS SAMも独自の仮想化技術を使うわけではなく、Dockerを利用してLambdaのビルド・実行環境を再現していることが、実際に構築することで確認できました。
CLI中心の環境でも、
Vim
nano
Git
Docker
Dev Container CLI
AWS CLI
SAM CLI
だけで十分開発できます。
軽量なリモート開発環境を作りたい場合には、こういう構成も選択肢になりそうです。
