この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
一時期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にインストールするライブラリなどを指定します。
Dockerfile
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のサンプルそのままです。
bootstrap
#!/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向けのファイルをコピーします。
bash.sh
#!/bin/bash
docker build -t lambda-cobol:latest .
docker run -it --rm -v `pwd`:/tmp lambda-cobol cp /lambda-cobol-hello.zip /tmp/
hello.cob
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上で環境を作ろうとして、ライブラリ関連の相性が悪くてなかなかできませんでした。社内に相談したところ、そのままズバリの解決策を教えてもらえまして、どうにか動作確認まですることができました。山下さんありがとうございました!!