これは MIERUNE Advent Calendar 2025 の20日目の記事です。
昨日は @Guarneri009 さんによる 数値地図(国土基本情報)メッシュ標高情報データ ファイル (lem & csv)を高速にGeotiffに変換する でした。
Martin とは
Martin は PostGIS、PMTiles、MBTiles などを MVT タイルとして配信するためのタイルサーバです。URL パラメータをユーザー関数に直接渡すことで、地物の抽出や属性値の集約をサーバーサイドで柔軟に制御できるため、大規模データの配信に適しています。2025 年 11 月、Martin は開発開始から約 8 年を経て、初の正式メジャー版(v1.0)をリリースしました。
この記事では Martin 公式ドキュメント を参考して、AWS Lambda で PMTiles を配信する方法を紹介します。
Martin で PMTiles をホスティングするメリット
PMTiles はプロトコルをクライアント側で整えればファイルに直接接続して配信できますが、Martin タイルサーバを使うとこのようなメリットがあります。
- クライアント側では PMTiles のためのプロトコルが不要で、PMTiles 非対応クライアントでも使える
- キャッシュがカスタマイズできる
- 「何が配信されているか」がサーバ側で可視化できる
- catalog = サーバの公開インターフェース
- Web UI で視覚的にも確認できる
- ダウンロードなどで悪用されにくい
- sprites / fonts / styles を同じサーバにまとめられる
Martin で PMTiles をホスティングする方法
Martin CLI ではこのようにアーカイブタイル形式(PMTiles, MBTiles)をホスティングできます。ローカルファイルのパスもしくはオブジェクトリストレジの URL を martin の後に繋げていくだけです。
martin /path/to/mbtiles/file.mbtiles /path/to/directory https://example.org/path/tiles.pmtiles
Lambda でのホスティング
公式ドキュメントでは、コンテナと ZIP ファイルでデプロイする方法の両方が紹介されていますが、前者の方でデモを作ってみます。
サンプルデータは 国土数値情報 - 行政区域データ を使って PMTiles を作成しています。
Lambdaでもローカルと同じように martin バイナリを利用して Docker コンテナを立ち上げます。
CDK ディレクトリツリー
cdk/
├── bin/
│ └── cdk.ts
├── lib/
│ └── cdk-stack.ts
├── assets/ # タイルファイルなど
├── lambda/
│ └── martin/ # Lambda用のDockerイメージ
└── package.json
lambda/martin/Dockerfile
FROM ghcr.io/maplibre/martin:1.0.0
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
lambda/martin/entrypoint.sh
#!/bin/sh
set -eu
if [ -z "${PMTILES_URL:-}" ]; then
echo "PMTILES_URL is required"
exit 1
fi
exec martin --webui enable-for-all "${PMTILES_URL}"
lib/cdk-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from "aws-cdk-lib/aws-s3";
import * as s3deploy from "aws-cdk-lib/aws-s3-deployment";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as path from "path";
export class CdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const bucket = new s3.Bucket(this, "PmtilesBucket", {
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
});
new s3deploy.BucketDeployment(this, "DeployPmtiles", {
destinationBucket: bucket,
sources: [s3deploy.Source.asset(path.join(__dirname, "../assets"))],
retainOnDelete: false,
});
const pmtilesUrl = `https://${bucket.bucketRegionalDomainName}/japan_prefecture.pmtiles`;
const fn = new lambda.DockerImageFunction(this, "MartinFn", {
architecture: lambda.Architecture.ARM_64,
memorySize: 1024,
timeout: cdk.Duration.seconds(30),
code: lambda.DockerImageCode.fromImageAsset(
path.join(__dirname, "../lambda/martin"),
),
environment: {
PMTILES_URL: pmtilesUrl,
},
});
bucket.grantRead(fn);
const fnUrl = fn.addFunctionUrl({
authType: lambda.FunctionUrlAuthType.NONE,
});
}
}
AWS CLI で デプロイすれば、Lambda の Function URL から Martin タイルサーバに接続できるようになります。
ホスティングの状態を確認する
- Martin の Web UI
{functionURL} が Web UI のエンドポイントになります。ここで配信中のリソースやリクエスト数を監視できます。
- QGIS などのクライアント
{functionURL}/{sourceID}/{z}/{x}/{y} がタイルの URL になります。QGIS の Browser - Vector からリソースを追加できます。レイヤをキャンパスに追加すると、日本全国のデータがタイルとして配信されていることを確認できます。
地図データ出典:
- 国土数値情報 - 行政区域データ を加工したもの
- OpenStreetMap
その他
ドキュメントをまだ読み切れていないですが、便利そうな機能をいくつか紹介します。
- Configuration File の活用
今回コマンドに直接ソースのパスを書き込んでいますが、Configuration File を使えばより複数のソースの定義やサーバー側の設定しやすくなります。
このように config.yaml をパラメータとして渡すことができます。
martin --config config.yaml
martin-cp
martin-cp という Martin がタイル生成用の補助ツールも用意されています。Martin が対応している任意のデータソースからタイルを一括生成し、新規または既存の MBTiles ファイルに保存する。特に複数のエリアの地物が重複している場合でも、同一タイルが重複して生成されることはなく、1 度だけ生成されるように処理さるところポイントです。
ソースコード
参考資料
明日は @bordoray さんによる 猿でもわかる座標系 です!お楽しみにー

