はじめに
LocalStack は知っていたけど、実際に触ったことが無かったので、LocakStack で S3 を起動して、主要な機能を触ってみました。
セットアップ
LocalStack を管理する方法としては、LocalStack CLI, LocalStack Desktop などの専用のツールもありますが、今回はプロジェクトの扱いやすさを考えて、Docker-Compose を利用します。
Docker-Compose で起動する
docker-compose.yml を作成して、S3 を利用できるように LocakStack を起動します。
services:
localstack:
container_name: localstack-poc
image: localstack/localstack # Community イメージ
ports:
- "4566:4566" # LocalStack メインポート
environment:
- SERVICES=s3 # 必要な AWS サービスを指定
- DEBUG=1 # デバッグログの出力
起動時の設定については、環境変数で指定することができます。利用可能な環境変数一覧は、こちらで確認することができます。Legacy パラメータも多くありますね。
LocalStack に接続する
AWS CLI や AWS SDK を利用して LocalStack に接続する方法はいくつかありますが、エンドポイント URL を使ってアクセスする方法がシンプルに接続できそうです。エンドポイント URL の設定は、コマンドや関数のオプションに指定するか、環境変数(AWS_ENDPOINT_URL
)を使って指定することができそうです。また、config ファイルで指定することもできそうです。詳細は AWS 公式ドキュメント(CLI or SDK)を確認してください。
AWS CLI で接続する場合は、
aws --endpoint-url=http://localhost:4566 s3 ls
または
export AWS_ENDPOINT_URL=http://localhost:4566
aws s3 ls
AWS SDK(boto3) で接続する場合は、
# 環境変数に AWS_ENDPOINT_URL が設定されている場合は endpoint_url を指定しなくてよい
# AWS に接続する場合は endpoint_url に None を設定する
s3_client = boto3.client("s3", endpoint_url="http://localhost:4566")
response = s3_client.list_buckets()
このように接続することができます。
また、config ファイルを設定して、プロファイルで切り替えたい場合は、以下のようなプロファイルを作成しておくと接続できました。継続的に AWS CLI を使って接続したい際は、プロファイルを作成するのが楽そうですね。
[localstack]
aws_access_key_id = dummy
aws_secret_access_key = dummy
[profile localstack]
region = dummy
endpoint_url = http://localhost:4566
実行時のオプションや環境変数で設定することができるので、接続先を LocalStack か AWS かを柔軟に切り替えることができそうですね。
起動時にコマンドを実行する
LocalStack 起動時になんらかの処理を実行したい場合は、Initialization Hooksを使うことができます。データを永続化(Persistenceは Pro Image の機能)していない場合は、コンテナを停止または破棄したタイミングでデータが無くなります。起動のたびに作成したいデータなどあれば、Initialization Hooks で作成するのが楽かもしれないですね。
#!/bin/bash
# 起動時にバケットを作成する
awslocal s3 mb s3://sample-bucket
# ...
volumes:
- "/path/to/ready.sh:/etc/localstack/init/ready.d/ready.sh"
# ...
ローカルに作成した ready.sh
ファイルには、実行権限を付与する必要があります。
各種コマンドを実行する
セットアップで起動した LocalStack の S3 に対して、AWS CLI を使って基本的なコマンドを実行してみます。
コマンド実行の際は、config ファイルに LocalStack に接続できるように設定してから、実行していきます。
LocalStack で起動した S3 でサポートされている機能一覧は、公式ページで確認することができます。
バケットを作成する
aws s3api create-bucket --bucket sample-bucket
{
"Location": "/sample-bucket"
}
バケット一覧を表示する
aws s3api list-buckets
{
"Buckets": [
{
"Name": "sample-bucket",
"CreationDate": "2024-11-02T01:44:21+00:00"
}
],
"Owner": {
"DisplayName": "webfile",
"ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
}
}
オブジェクトをアップロードする
aws s3api put-object \
--bucket sample-bucket \
--key upload/sample.pdf \
--body [ローカルファイルパス]sample.pdf
{
"ETag": "\"f15d8a573ef37ccbeeb5da27d09046d7\"",
"ServerSideEncryption": "AES256"
}
オブジェクト一覧を表示する
aws s3api list-objects --bucket sample-bucket
{
"Contents": [
{
"Key": "upload/sample.pdf",
"LastModified": "2024-11-02T01:58:40+00:00",
"ETag": "\"f15d8a573ef37ccbeeb5da27d09046d7\"",
"Size": 341595,
"StorageClass": "STANDARD",
"Owner": {
"DisplayName": "webfile",
"ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
}
}
],
"RequestCharged": null
}
署名付き URL を生成する
署名付き URL を生成して、生成された URL にアクセスすると実際にオブジェクトをダウンロードすることができます。
aws s3 presign s3://sample-bucket/upload/sample.pdf
http://localhost:4566/sample-bucket/upload/sample.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=dummy%2F20241103%2Fdummy%2Fs3%2Faws4_request&X-Amz-Date=20241103T234527Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=865d24edcbffc1bf62bd2d3949579c0ee10808abb055d66c9a0f33b248735c5a
バージョニング機能を使う
バケットのバージョニングを有効にする
aws s3api put-bucket-versioning --bucket sample-bucket --versioning-configuration Status=Enabled
同じキーのオブジェクトをアップロードすると VersionId
が付与されるようになる。
aws s3api put-object \
--bucket sample-bucket \
--key upload/sample.pdf \
--body [ローカルファイルパス]sample-version.pdf
{
"ETag": "\"f15d8a573ef37ccbeeb5da27d09046d7\"",
"ServerSideEncryption": "AES256",
"VersionId": "Hu4vBqQ1Xm__2dxOL3I--A"
}
バージョン情報を確認する
aws s3api list-object-versions --bucket sample-bucket --prefix upload/sample-version.pdf
{
"Versions": [
{
"ETag": "\"f15d8a573ef37ccbeeb5da27d09046d7\"",
"Size": 341595,
"StorageClass": "STANDARD",
"Key": "upload/sample-version.pdf",
"VersionId": "Hu4vBqQ1Xm__2dxOL3I--A",
"IsLatest": true,
"LastModified": "2024-11-04T00:15:20+00:00",
"Owner": {
"DisplayName": "webfile",
"ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
}
},
{
"ETag": "\"f15d8a573ef37ccbeeb5da27d09046d7\"",
"Size": 341595,
"StorageClass": "STANDARD",
"Key": "upload/sample-version.pdf",
"VersionId": "QrHWHuSeXqenDImNRvM_Og",
"IsLatest": false,
"LastModified": "2024-11-04T00:15:15+00:00",
"Owner": {
"DisplayName": "webfile",
"ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
}
}
],
"RequestCharged": null
}
オブジェクトを削除する
aws s3api delete-object --bucket sample-bucket --key upload/sample-version.pdf
{
"DeleteMarker": true,
"VersionId": "iuuscmhfJmTyV3SOEUaIig"
}
バージョン情報を確認すると、削除情報(DeleteMarkers
)も確認することができる。
aws s3api list-object-versions --bucket sample-bucket --prefix upload/sample-version.pdf
{
"Versions": [
{
"ETag": "\"f15d8a573ef37ccbeeb5da27d09046d7\"",
"Size": 341595,
"StorageClass": "STANDARD",
"Key": "upload/sample-version.pdf",
"VersionId": "Hu4vBqQ1Xm__2dxOL3I--A",
"IsLatest": false,
"LastModified": "2024-11-04T00:15:20+00:00",
"Owner": {
"DisplayName": "webfile",
"ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
}
},
{
"ETag": "\"f15d8a573ef37ccbeeb5da27d09046d7\"",
"Size": 341595,
"StorageClass": "STANDARD",
"Key": "upload/sample-version.pdf",
"VersionId": "QrHWHuSeXqenDImNRvM_Og",
"IsLatest": false,
"LastModified": "2024-11-04T00:15:15+00:00",
"Owner": {
"DisplayName": "webfile",
"ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
}
}
],
"DeleteMarkers": [
{
"Owner": {
"DisplayName": "webfile",
"ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
},
"Key": "upload/sample-version.pdf",
"VersionId": "iuuscmhfJmTyV3SOEUaIig",
"IsLatest": true,
"LastModified": "2024-11-04T00:21:00+00:00"
}
],
"RequestCharged": null
}
さいごに
Docker ですぐに起動できて、S3 の主要な機能はほとんど網羅されているように感じました。ローカル開発時やテスト実行時などの S3 接続先としては、十分に使えるなぁと思いました。LocalStack は S3 以外のサービスも多くあるので、いろいろな使い方を試してみたいと思います。
参考