初めに
SageMath の Docker イメージを AWS Lambdaで実行する方法を書きます。
課題
記載した手順で一応コンテナ実行はできます。しかし Lambda 関数自体の実行はエラー終了します。解決方法についてはまだわかっていません。
ソースコード
イメージとバージョンは、sagemath/sagemath:10.1
です。
クローン~ビルド手順は README に記載しています。
実行結果
次のような sage スクリプトを実行します。
print('Hello, from sagemath container!')
R.<x> = PolynomialRing(QQ)
f = 'x^2 - 1'
print(f'The factorization of {f} is {R(f).factor()}.')
実行結果は次のようになります。
ログには sage スクリプトの実行結果が出力されています。
手順
以下に記載する手順はSageMathコンテナをLambdaで実行する際の備忘録です。
1) Dockerfile、sage スクリプトを作成する
1.1) Dockerfile、sage スクリプトを作成する
ディレクトリ構成は以下のようにします。
/home/ec2-user/sage-demo
|---Dockerfile
|---run.sh
|---hello.sage
以下 3 つのファイルを作成します。
FROM sagemath/sagemath
WORKDIR /var/task
RUN sudo chown sage:sage /var/task
COPY . /var/task/
CMD ["sh", "run.sh"]
sage hello.sage
print('Hello from sagemath.')
1.2) コンテナ実行
イメージをビルドし、コンテナを実行します。
$ cd ~/sage-demo
$ docker build -t sage-demo .
$ docker run sage-demo
output) Hello from sagemath.
※標準出力は output)
で記載しています。不要だと思われる標準出力については省略しています。
2) ECR にイメージをプッシュする
ログイン、タグ付け、プッシュを行います。
$ export ACCOUNT_ID=111111111111
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
$ docker tag sage-demo:latest ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sage-demo:latest
$ docker push ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/sage-demo:latest
3) Lambda コンテナを実行する
3.1) Lambda コンテナを実行する
Lambda 関数を作成し、2) のイメージを参照するように設定します。その後、Lambda 関数をテストします。実行は失敗します。以下エラー部分です。
/usr/local/bin/sage-entrypoint: line 8: exec: sage: not found
これは sage コマンドのパスが通っていないことによるエラーです。
3.2) sage コマンド調査
ひとまず sage コマンドに関係するファイルをコンテナからホストにコピーします。まずはホストからコンテナに入ります。
docker run -it sage /bin/bash
次に起動したコンテナから sage
コマンドのパスを調べます。
$ which sage
output) /home/sage/sage/src/bin/sage
次に起動したコンテナ ID を調べ、コンテナからホストへディレクトリ、ファイルをコピーします。
$ docker ps
$ docker cp ab62b0122598:/home/sage/sage/src/bin/ /home/ec2-user/sage-demo/sagebin/
$ docker cp ab62b0122598:/usr/local/bin/sage-entrypoint /home/ec2-user/sage-demo/sagebin/
ここで上記の /home/ec2-user/sage-demo/sagebin/
はホストのディレクトリです。一旦ホストに移動してスクリプトを修正し、ビルド時に COPY で修正を反映します。
※ ab62b0122598
はコンテナ ID
3.3) イメージ修正
sage
関連のファイルと自作ファイルが混在するのを防ぐため、ディレクトリ構成を以下のように変更します。
/home/ec2-user/sage-demo
|---Dockerfile
|---src
| |---run.sh
| |---hello.sage
|
|---sagebin
|---sage
・
(略)
・
|---sage-entrypoint
Dockerfile は以下のように修正します。
FROM sagemath/sagemath
WORKDIR /var/task
RUN sudo chown sage:sage /var/task
COPY ./src/* /var/task/
# sage コマンド関連ファイルを追加
COPY ./sagebin/* /usr/local/bin/
CMD ["sh", "run.sh"]
Dockerfile 修正後、ビルド、プッシュします。
4) Lambda コンテナを再実行する
4.1) Lambda コンテナを再実行する
再実行エラーが発生します。
/usr/local/bin/sage-env: line 58: cd: /home/sage/: Permission denied
mkdir: cannot create directory ‘//R’: Read-only file system
4.2) イメージ修正
エラー修正のため、/home/sage
ディレクトリの権限を緩くします。Dockerfile を以下のように修正後、ビルド、プッシュします。
FROM sagemath/sagemath
WORKDIR /var/task
# /home/sage の権限変更
RUN sudo chown sage:sage /var/task \
&& sudo chmod 777 /home/sage
COPY ./src/* /var/task/
COPY ./sagebin/* /home/sage/sage/src/bin/
CMD ["sh", "run.sh"]
5) Lambda コンテナを再実行する
5.1) Lambda コンテナを再実行する
再実行エラーが発生します。
mkdir: cannot create directory ‘/home/sage/.sage/’: Read-only file system
.
(略)
.
OSError: [Errno 30] Read-only file system: '/var/task/tmpdc83oq9o'
5.2) イメージ修正
以下のように修正してプッシュします。
FROM sagemath/sagemath
WORKDIR /var/task
RUN sudo chown sage:sage /var/task \
&& sudo chmod 777 /home/sage \
&& mkdir /home/sage/.sage \
&& sudo chmod 777 /home/sage/.sage
COPY ./src/* /var/task/
COPY ./sagebin/* /home/sage/sage/src/bin/
CMD ["sh", "run.sh"]
6) Lambda コンテナを再実行する
6.1) Lambda コンテナを再実行する
再実行エラーが発生します。
mkdir: cannot create directory ‘/home/sage/.sage//R’: Read-only file system
/home/sage/sage/src/bin/sage-env: line 436: /home/sage/.sage//R/Makevars.user: No such file or directory
6.2) イメージ修正
/home/sage/sage/src/bin/sage-env: line 436
に対応する箇所をコメントアウトしてプッシュします。具体的には以下のように425行目~441行目をコメントアウトします。
425 # if [ -d "$DOT_SAGE" ] ; then
426 # if ! [ -d "$DOT_SAGE/R" ] ; then
427 # if ! [ -e "$DOT_SAGE/R" ] ; then
428 # mkdir -p "$DOT_SAGE/R"
429 # else
430 # >&2 echo "Warning: $DOT_SAGE/R exists and is not a directory : trouble ahead..."
431 # fi
432 # fi
433 # R_MAKEVARS_USER="$DOT_SAGE/R/Makevars.user" && export R_MAKEVARS_USER
434 # if ! [ -f "$R_MAKEVARS_USER" ] ; then
435 # if ! [ -e "$R_MAKEVARS_USER" ] ; then
436 # echo "## Empty user-specific Makevars file for Sage's R" > "$R_MAKEVARS_USER"
437 # else
438 # >&2 echo "Warning: $R_MAKEVARS_USER exists and is not a file : trouble ahead..."
439 # fi
440 # fi
441 # fi
7) Lambda コンテナを再実行する
7.1) Lambda コンテナを再実行する
再実行エラーが発生します。
Traceback (most recent call last):
File "/home/sage/sage/src/bin/sage-preparse", line 302, in <module>
do_preparse(f)
File "/home/sage/sage/src/bin/sage-preparse", line 151, in do_preparse
with atomic_write(fname) as f:
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/site-packages/sage/misc/temporary_file.py", line 349, in __enter__
fd, name = tempfile.mkstemp(dir=self.tmpdir)
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/tempfile.py", line 341, in mkstemp
return _mkstemp_inner(dir, prefix, suffix, flags, output_type)
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/tempfile.py", line 256, in _mkstemp_inner
fd = _os.open(file, flags, 0o600)
OSError: [Errno 30] Read-only file system: '/var/task/tmpeo_ubjxu'
7.2) イメージ修正
sage 関連ファイルを修正します。以下のように ~~~.sage.py
ファイルを作成するディレクトリを /tmp
ディレクトリに設定します。/tmp
ディレクトリは Lambda 関数が書き込み可能なディレクトリです。
+ import shutil
+ import glob
fn = sys.argv[1]
opts = sys.argv[2:]
+ python_files = glob.glob(os.path.join(os.getcwd(), '*.py'))
+ for python_file in python_files:
+ shutil.copy(python_file, '/tmp')
+ shutil.copy(fn, '/tmp')
+ fn = os.path.join('/tmp', fn)
if fn.startswith('-'):
print("sage-run received unknown option: {}".format(fn))
print("usage: sage [options]")
print("Try 'sage -h' for more information.")
sys.exit(1)
8) Lambda コンテナを再実行する
8.1) Lambda コンテナを再実行する
再実行エラーが発生します。
Traceback (most recent call last):
File "/tmp/hello.sage.py", line 4, in <module>
from sage.all_cmdline import * # import sage library
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/site-packages/sage/all_cmdline.py", line 19, in <module>
from sage.all import *
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/site-packages/sage/all.py", line 124, in <module>
from sage.misc.all import * # takes a while
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/site-packages/sage/misc/all.py", line 8, in <module>
from .misc import (BackslashOperator,
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/site-packages/sage/misc/misc.py", line 286, in <module>
os.makedirs(SAGE_DB, exist_ok=True)
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/os.py", line 225, in makedirs
mkdir(name, mode)
OSError: [Errno 30] Read-only file system: '/home/sage/.sage/db'
8.2) イメージ修正
sage
コマンドにオプション --nodotsage
を追加します。
#!/bin/sh
sage --nodotsage -python "$@"
9) Lambda コンテナを再実行する
9.1) Lambda コンテナを再実行する
再実行エラーが発生します。
Traceback (most recent call last):
File "/tmp/hello.sage.py", line 4, in <module>
from sage.all_cmdline import * # import sage library
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/site-packages/sage/all_cmdline.py", line 19, in <module>
from sage.all import *
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/site-packages/sage/all.py", line 124, in <module>
from sage.misc.all import * # takes a while
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/site-packages/sage/misc/all.py", line 8, in <module>
from .misc import (BackslashOperator,
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/site-packages/sage/misc/misc.py", line 290, in <module>
os.makedirs(os.environ["MPLCONFIGDIR"], exist_ok=True)
File "/home/sage/sage/local/var/lib/sage/venv-python3.10.5/lib/python3.10/os.py", line 225, in makedirs
mkdir(name, mode)
OSError: [Errno 30] Read-only file system: '/home/sage/.sage//matplotlib-1.5.1'
9.2) イメージ修正
以下のように環境変数 MPLCONFIGDIR
の定義をコメントアウトします。なお、この前後の if ブロックもコメントアウトする必要があります。
407 # export MPLCONFIGDIR="$DOT_SAGE/matplotlib-1.5.1"
10) Lambda コンテナを再実行する
10.1) Lambda コンテナを再実行する
エラー終了していますが、Hello from sagemath.
と出力されました。
OpenBLAS WARNING - could not determine the L2 cache size on this system, assuming 256k
Hello from sagemath.
OpenBLAS WARNING - could not determine the L2 cache size on this system, assuming 256k
Hello from sagemath.
START RequestId: fe894660-f0ac-46e6-9985-bdb8dec7beaf Version: $LATEST
RequestId: fe894660-f0ac-46e6-9985-bdb8dec7beaf Error: Runtime exited without providing a reason
Runtime.ExitError
END RequestId: fe894660-f0ac-46e6-9985-bdb8dec7beaf
REPORT RequestId: fe894660-f0ac-46e6-9985-bdb8dec7beaf Duration: 1647.46 ms Billed Duration: 1648 ms Memory Size: 4096 MB Max Memory Used: 119 MB
参考記事