AWS LambdaのCustom RuntimeでCOBOLを動かしてみた #reinvent
はじめに
一時期Twitterで騒然となった、AWSのCOBOL対応ですが、実際にやってみたいと思います。
Dockerとdocker-composeの環境を整える
まずは、EC2でAmazon Linuxのインスタンスを立ち上げてsshでログインします。そして次の手順でDocker環境を整えます。dockerコマンドで環境情報が表示されれば成功です。
$ sudo yum -y update $ sudo amazon-linux-extras -y install docker $ sudo service docker start $ sudo chkconfig docker on $ sudo usermod -a -G docker ec2-user $ sudo gpasswd -a $USER docker $ sudo systemctl restart docker $ exit # もう1回ログインする $ docker info Containers: 0 Running: 0 Paused: 0 Stopped: 0 ....
次に、docker-composeの環境を整えます。
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose $ docker-compose --version docker-compose version 1.23.1, build b02f1306
COBOLをコンパイルする環境を整える
Dockerにインストールするライブラリなどを指定します。
FROM amazonlinux:1 # install tools RUN yum -y groupinstall "Development tools" # install GnuCOBOL 2.2 RUN yum -y install gmp-devel ncurses-devel db4-devel RUN curl -L -o gnucobol-2.2.tar.gz https://sourceforge.net/projects/open-cobol/files/gnu-cobol/2.2/gnucobol-2.2.tar.gz/download RUN tar zxf gnucobol-2.2.tar.gz RUN cd gnucobol-2.2 && ./configure --prefix=/usr --libdir=/usr/lib64 && make && make install # build lambda function package RUN mkdir -p /cobol/lib COPY bootstrap /cobol COPY hello.cob /cobol RUN cp /usr/lib64/libcob.so.4 \ /lib64/libm.so.6 \ /usr/lib64/libgmp.so.10 \ /lib64/libncursesw.so.5 \ /lib64/libtinfo.so.5 \ /usr/lib64/libdb-4.7.so \ /lib64/libdl.so.2 \ /lib64/libc.so.6 \ /lib64/libpthread.so.0 \ /lib64/ld-linux-x86-64.so.2 \ /cobol/lib RUN cd /cobol && \ COB_LDFLAGS="-Wl,--rpath=./lib -Wl,--dynamic-linker=./lib/ld-linux-x86-64.so.2" cobc -x hello.cob RUN cd /cobol && zip -r /lambda-cobol-hello.zip ./bootstrap ./hello ./lib CMD /bin/bash
Lambdaのサンプルそのままです。
#!/bin/sh set -euo pipefail LM=$(echo "$_HANDLER" | cut -d. -f2) # Processing while true; do HEADERS="$(mktemp)" # Get an event EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next") REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2) # Execute the handler function from the script export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$LAMBDA_TASK_ROOT/lib RESPONSE="$(./$LM "$EVENT_DATA")" echo $RESPONSE # Send the response curl -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE" done
Dockerを起動してLambda向けのファイルをコピーします。
#!/bin/bash docker build -t lambda-cobol:latest . docker run -it --rm -v `pwd`:/tmp lambda-cobol cp /lambda-cobol-hello.zip /tmp/
IDENTIFICATION DIVISION. PROGRAM-ID. SAMPLE-01. ENVIRONMENT DIVISION. DATA DIVISION. PROCEDURE DIVISION. MAIN. DISPLAY "Hello world!" UPON CONSOLE. STOP RUN.
ビルドする
Lambdaにデプロイするために必要なファイルが揃いましたので、セットアップとコンパイルを行います。
$ ./build.sh Successfully built 912ab7f887a4 Successfully tagged lambda-cobol:latest $ ls Dockerfile bootstrap build.sh hello.cob lambda-cobol-hello.zip
ビルド済みのファイルが圧縮されて保存されていることが分かります。
Lambdaにデプロイ
出来上がったZIPを下記のコマンドでデプロイします。
$ export LAMBDA_EXEC_ROLE=arn:aws:iam::XXXXXXXXXXXX:role/exe-lambda $ aws lambda create-function --function-name hello-cobol --runtime provided --role $LAMBDA_EXEC_ROLE --handler cobol.hello --zip-file fileb://lambda-cobol-hello.zip --region ap-northeast-1 { "TracingConfig": { "Mode": "PassThrough" }, ....
作成したLambda関数を動かしてみる
まとめ
当初、Amazon Linux 2上で環境を作ろうとして、ライブラリ関連の相性が悪くてなかなかできませんでした。社内に相談したところ、そのままズバリの解決策を教えてもらえまして、どうにか動作確認まですることができました。山下さんありがとうございました!!