はじめに
ローカル環境でPyGMTを使えるようにはなったが、せっかくなのでAWS上で使えるようにしたいと思った。…思ってしまった。ので、試行錯誤してみた
構成
当初、できるだけ簡単な構成にしたくてPyGMTをコンテナLambdaで実行してみたのだが、PyGMTは実行時に/.gmtフォルダを作成するらしく、/tmp/以下にしか一時ファイルを保存できないLambdaではエラーが起きてしまった。
そのため搭載先をFargateに変更し、Fargate上で描いたテスト用の地図をファイルとして出力し、S3へ保存するプログラムを作成した。
S3バケットの作成
事前に画像ファイル格納用のS3バケットを作成しておく。バケット名以外はデフォルトでOK。
ソースコード
テスト用に出力する地図の構成はPyGMT-HOWTOの基本の地図から拝借したものを使用。tmp領域にpngファイルを出力後、S3へ送信する処理を行っている。
(出力ファイルを/tmp以下に置こうとしているあたりにLambdaの痕跡が見える)
import pygmt
import boto3
print('Exe Start')
fig = pygmt.Figure()
fig.coast(
projection = 'N138/12c',
region = (128, 146, 30, 46),
shorelines = 'default,black',
area_thresh = 100,
resolution = 'f',
land = '249/243/202',
water = '190/220/250',
map_scale = '142.5/32/32/400',
frame = ['WSen+t"Figure"', 'xafg', 'yafg']
)
fig.savefig('/tmp/pygmt-coastline.png')
s3 = boto3.resource('s3')
s3.Object(
'[S3バケット名]', 'pygmt-coastline.png').upload_file('/tmp/pygmt-coastline.png')
print('Completed!')
Dockerfile
このページ や このページを参考にDocerfileを準備した。
Dockerfileにクレデンシャル情報を入れてるのがとてもアレだが、テスト用の仮置きということでご容赦を、、
FROM continuumio/miniconda3
WORKDIR /app
ENV AWS_ACCESS_KEY_ID "<AWSアクセスキーID>"
ENV AWS_SECRET_ACCESS_KEY "<AWSシークレットアクセスキー>"
# Create the environment:
COPY environment.yml .
RUN conda env create -f environment.yml && conda clean --all
# Copy script
COPY app.py ./
COPY app.sh ./
# activate pygmt env
CMD ["sh", "./app.sh"]
environment.ymlファイルは以下。
name: pygmt
channels:
- conda-forge
dependencies:
- python=3.9
- pandas
- packaging
- gmt=6.4.0
- pygmt=0.8.0
- boto3
最後にapp.sh。
#!/bin/bash
. /root/.bashrc
conda activate pygmt
python app.py
ECRリポジトリの作成
AWSマネジメントコンソールを開いて、Dockerコンテナを保存するための準備をする。
ECR(Amazon Elastic Container Registry)のページを開き、「リポジトリの作成」からリポジトリ名を入力>「リポジトリを作成」をクリックする。
今回はリポジトリ名:pygmt-testで作成。
ECRへのイメージプッシュ
作成したECRリポジトリの画面>プッシュコマンドの表示ボタンから表示されるコマンドをコピーして実行する。
1.docker login(東京リージョンの例)
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin {AWSaccountID}.dkr.ecr.ap-northeast-1.amazonaws.com
2.docker build
全部で2分ほどかかる。
※"pygmt-test"は作成したECRリポジトリ名に置き換えて実行してください。
docker build -t pygmt-test .
3.イメージにタグを付与
docker tag pygmt-test:latest {AWSaccountID}.dkr.ecr.ap-northeast-1.amazonaws.com/pygmt-test:latest
4.ECRにイメージをプッシュ
docker push {AWSaccountID}.dkr.ecr.ap-northeast-1.amazonaws.com/pygmt-test:latest
ECSタスク定義の作成
1.マネジメントコンソールでECSの画面を開き、左メニューで「タスク定義」をクリック。
タスク定義ファミリー(タスク定義名)、コンテナ名を入力。
イメージURIの欄は、ECRに登録したイメージのURIをコピーして入力する。
ポートマッピングは今回必要ないので削除。
あとはデフォルトで「次へ」をクリック。
2.次の画面ではデフォルトのまま、もう一度「次へ」。
確認画面でひと通り確認ができたら「作成」をクリック。
3.作成したタスク定義を選択し、最新のリビジョンを選んでクリック。
表示されたタスク定義画面で、「タスク実行ロール」に表示されているロール名をクリックする。
IAMの画面が開くので、「許可を追加」>「ポリシーをアタッチ」を選択する。
ポリシーの選択画面が開くので、"S3"で検索して「AmazonS3FullAccess」をアタッチする。
ECSクラスターの作成
1.マネジメントコンソールのECS画面から、クラスター>「クラスターの作成」をクリック。
クラスター名を入力、VPCとサブネットは適当なものを選び、インフラストラクチャはAWS Fargateを指定して「作成」をクリック。
(VPCとサブネット周りまで設定していると長くなってしまうので、ここではデフォルトのものを使用しています。ネットワーク周りについては別途設定してください。)
2.しばらく待つとクラスターが作成される。
ECSタスクの作成
1.上記で作成したクラスター名を選択して、サービスの「作成」をクリックする。
2.今回はタスク分散等は必要ないので、コンピューティングオプションは「起動タイプ」を選ぶ。
起動タイプは「FARGATE」、バージョンは「LATEST」を指定する。
デプロイ設定のアプリケーションタイプは「タスク」を選び、タスク定義のファミリーに先ほど作成したタスク定義名を設定する。
ここまで入力したらあとはデフォルトで「作成」をクリック。
3.タスクの実行が始まるので、実行完了を待つ。タスクのステータスが「停止済み」になるまで約1分半~2分かかる。