この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
追記:こちらの記事で掲載している nodejs コンテナイメージベースの Puppeteer を、実際の AWS Lambda 環境で動かしてみたところコアダンプ等のエラーが発生し動作しないことを確認しております。実際に AWS Lambda 環境で Puppeteer を利用する方法としては、下記の記事を参考に alixaxel/chrome-aws-lambda を利用されるのが良いかと思われます。
先日の re:Invent にて Lambda Container Support が発表されました。
注意:こちらの手順は、ローカル環境で Amazon ECR Public Gallery の nodejs コンテナイメージをベースに Puppeteer が動作することを検証した記事となっております。
検証環境について
筆者のローカル環境は、以下の構成です。
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.7
BuildVersion: 19H15
$ docker -v
Docker version 20.10.0, build 7287ab3
curl -V
curl 7.64.1 (x86_64-apple-darwin19.0) libcurl/7.64.1 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.39.2
Release-Date: 2019-03-27
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS GSS-API HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM NTLM_WB SPNEGO SSL UnixSockets
やってみた
用意するファイルは、2つだけ
- app.js
- Dockerfile
Dockerfile は、以下のとおりです。
Dockerfile
FROM public.ecr.aws/lambda/nodejs:12
LABEL example=lambda-container
ARG LAMBDA_TASK_ROOT="/var/task"
RUN yum install -y https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
RUN npm install puppeteer-core
COPY app.js ${LAMBDA_TASK_ROOT}
CMD [ "app.handler" ]
Amazon ECR Public Gallery の nodejs コンテナイメージをベースに google-chrome-stable と puppeteer-core をインストールしてソースコードを LAMBDA_TASK_ROOT(/var/task)にコピーしハンドラーを起動しています。
次に、app.js
app.js
const puppeteer = require('puppeteer-core');
exports.handler = async (event) => {
const browser = await puppeteer.launch({
headless: true,
executablePath: '/usr/bin/google-chrome-stable',
args: [
'--no-sandbox',
'--disable-setuid-sandbox'
]
});
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
await browser.close();
const response = {
statusCode: 200,
};
return response;
};
yum インストールした Chrome をヘッドレスモードで起動し、https://example.com のスクリーンショットを example.png として保存するサンプルになります。
先の Dockerfile を利用して、コンテナイメージをビルドします。
$ docker build -t example .
Sending build context to Docker daemon 32.26kB
Step 1/7 : FROM public.ecr.aws/lambda/nodejs:12
---> 80d7260f97c9
Step 2/7 : LABEL example=lambda-container
---> Running in 8a9ed315b107
Removing intermediate container 8a9ed315b107
---> df5ef5d27555
Step 3/7 : ARG LAMBDA_TASK_ROOT="/var/task"
---> Running in 3866d4a3a2d7
Removing intermediate container 3866d4a3a2d7
---> ecca97455032
Step 4/7 : RUN yum install -y https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
---> Running in 9bdd12ea0473
Loaded plugins: ovl
Examining /var/tmp/yum-root-_IfE9n/google-chrome-stable_current_x86_64.rpm: google-chrome-stable-87.0.4280.88-1.x86_64
Marking /var/tmp/yum-root-_IfE9n/google-chrome-stable_current_x86_64.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package google-chrome-stable.x86_64 0:87.0.4280.88-1 will be installed
:
略
:
Installed:
google-chrome-stable.x86_64 0:87.0.4280.88-1
Dependency Installed:
acl.x86_64 0:2.2.51-14.amzn2
adwaita-cursor-theme.noarch 0:3.26.0-1.amzn2
adwaita-icon-theme.noarch 0:3.26.0-1.amzn2
alsa-lib.x86_64 0:1.1.4.1-2.amzn2
at-spi2-atk.x86_64 0:2.22.0-2.amzn2.0.2
at-spi2-core.x86_64 0:2.22.0-1.amzn2.0.2
atk.x86_64 0:2.22.0-3.amzn2.0.2
audit-libs.x86_64 0:2.8.1-3.amzn2.1
avahi-libs.x86_64 0:0.6.31-20.amzn2
cairo.x86_64 0:1.15.12-4.amzn2
cairo-gobject.x86_64 0:1.15.12-4.amzn2
colord-libs.x86_64 0:1.3.4-1.amzn2.0.2
cracklib.x86_64 0:2.9.0-11.amzn2.0.2
cracklib-dicts.x86_64 0:2.9.0-11.amzn2.0.2
cryptsetup-libs.x86_64 0:1.7.4-4.amzn2
cups-libs.x86_64 1:1.6.3-51.amzn2
dbus.x86_64 1:1.10.24-7.amzn2
dbus-libs.x86_64 1:1.10.24-7.amzn2
dconf.x86_64 0:0.28.0-4.amzn2
dejavu-fonts-common.noarch 0:2.33-6.amzn2
dejavu-sans-fonts.noarch 0:2.33-6.amzn2
desktop-file-utils.x86_64 0:0.23-2.amzn2
device-mapper.x86_64 7:1.02.146-4.amzn2.0.2
device-mapper-libs.x86_64 7:1.02.146-4.amzn2.0.2
elfutils-default-yama-scope.noarch 0:0.176-2.amzn2
elfutils-libs.x86_64 0:0.176-2.amzn2
emacs-filesystem.noarch 1:25.3-3.amzn2.0.2
fontconfig.x86_64 0:2.13.0-4.3.amzn2
fontpackages-filesystem.noarch 0:1.44-8.amzn2
freetype.x86_64 0:2.8-14.amzn2.1
fribidi.x86_64 0:1.0.2-1.amzn2.1
gdk-pixbuf2.x86_64 0:2.36.12-3.amzn2
glib-networking.x86_64 0:2.56.1-1.amzn2
gnutls.x86_64 0:3.3.29-9.amzn2
graphite2.x86_64 0:1.3.10-1.amzn2.0.2
gsettings-desktop-schemas.x86_64 0:3.28.0-3.amzn2.0.1
gtk-update-icon-cache.x86_64 0:3.22.30-3.amzn2
gtk3.x86_64 0:3.22.30-3.amzn2
gzip.x86_64 0:1.5-10.amzn2
harfbuzz.x86_64 0:1.7.5-2.amzn2
hicolor-icon-theme.noarch 0:0.12-7.amzn2
hwdata.x86_64 0:0.252-9.3.amzn2
jasper-libs.x86_64 0:1.900.1-33.amzn2
jbigkit-libs.x86_64 0:2.0-11.amzn2.0.2
json-glib.x86_64 0:1.4.2-2.amzn2
kmod.x86_64 0:25-3.amzn2.0.2
kmod-libs.x86_64 0:25-3.amzn2.0.2
lcms2.x86_64 0:2.6-3.amzn2.0.2
libX11.x86_64 0:1.6.7-3.amzn2
libX11-common.noarch 0:1.6.7-3.amzn2
libXau.x86_64 0:1.0.8-2.1.amzn2.0.2
libXcomposite.x86_64 0:0.4.4-4.1.amzn2.0.2
libXcursor.x86_64 0:1.1.15-1.amzn2
libXdamage.x86_64 0:1.1.4-4.1.amzn2.0.2
libXext.x86_64 0:1.3.3-3.amzn2.0.2
libXfixes.x86_64 0:5.0.3-1.amzn2.0.2
libXft.x86_64 0:2.3.2-2.amzn2.0.2
libXi.x86_64 0:1.7.9-1.amzn2.0.2
libXinerama.x86_64 0:1.1.3-2.1.amzn2.0.2
libXrandr.x86_64 0:1.5.1-2.amzn2.0.3
libXrender.x86_64 0:0.9.10-1.amzn2.0.2
libXtst.x86_64 0:1.2.3-1.amzn2.0.2
libXxf86vm.x86_64 0:1.1.4-1.amzn2.0.2
libcap-ng.x86_64 0:0.7.5-4.amzn2.0.4
libdrm.x86_64 0:2.4.97-2.amzn2
libepoxy.x86_64 0:1.3.1-2.amzn2
liberation-fonts.noarch 1:1.07.2-16.amzn2
liberation-fonts-common.noarch 1:1.07.2-16.amzn2
liberation-mono-fonts.noarch 1:1.07.2-16.amzn2
liberation-narrow-fonts.noarch 1:1.07.2-16.amzn2
liberation-sans-fonts.noarch 1:1.07.2-16.amzn2
liberation-serif-fonts.noarch 1:1.07.2-16.amzn2
libfdisk.x86_64 0:2.30.2-2.amzn2.0.4
libglvnd.x86_64 1:1.0.1-0.1.git5baa1e5.amzn2.0.1
libglvnd-egl.x86_64 1:1.0.1-0.1.git5baa1e5.amzn2.0.1
libglvnd-glx.x86_64 1:1.0.1-0.1.git5baa1e5.amzn2.0.1
libgusb.x86_64 0:0.2.9-1.amzn2.0.2
libidn.x86_64 0:1.28-4.amzn2.0.2
libjpeg-turbo.x86_64 0:1.2.90-6.amzn2.0.3
libmodman.x86_64 0:2.0.1-8.amzn2.0.2
libpciaccess.x86_64 0:0.14-1.amzn2
libpng.x86_64 2:1.5.13-8.amzn2
libproxy.x86_64 0:0.4.11-10.amzn2.0.3
libpwquality.x86_64 0:1.2.3-5.amzn2
libsemanage.x86_64 0:2.5-11.amzn2
libsmartcols.x86_64 0:2.30.2-2.amzn2.0.4
libsoup.x86_64 0:2.56.0-6.amzn2
libthai.x86_64 0:0.1.14-9.amzn2.0.2
libtiff.x86_64 0:4.0.3-35.amzn2
libusbx.x86_64 0:1.0.21-1.amzn2
libutempter.x86_64 0:1.1.6-4.amzn2.0.2
libwayland-client.x86_64 0:1.17.0-1.amzn2
libwayland-cursor.x86_64 0:1.17.0-1.amzn2
libwayland-egl.x86_64 0:1.17.0-1.amzn2
libwayland-server.x86_64 0:1.17.0-1.amzn2
libxcb.x86_64 0:1.12-1.amzn2.0.2
libxkbcommon.x86_64 0:0.7.1-3.amzn2
libxshmfence.x86_64 0:1.2-1.amzn2.0.2
lz4.x86_64 0:1.7.5-2.amzn2.0.1
mesa-libEGL.x86_64 0:18.3.4-5.amzn2.0.1
mesa-libGL.x86_64 0:18.3.4-5.amzn2.0.1
mesa-libgbm.x86_64 0:18.3.4-5.amzn2.0.1
mesa-libglapi.x86_64 0:18.3.4-5.amzn2.0.1
nettle.x86_64 0:2.7.1-8.amzn2.0.2
pam.x86_64 0:1.1.8-23.amzn2.0.1
pango.x86_64 0:1.42.4-4.amzn2
pixman.x86_64 0:0.34.0-1.amzn2.0.2
qrencode-libs.x86_64 0:3.4.1-3.amzn2.0.2
rest.x86_64 0:0.8.0-2.amzn2
shadow-utils.x86_64 2:4.1.5.1-24.amzn2.0.2
systemd.x86_64 0:219-57.amzn2.0.12
systemd-libs.x86_64 0:219-57.amzn2.0.12
trousers.x86_64 0:0.3.14-2.amzn2.0.2
ustr.x86_64 0:1.0.4-16.amzn2.0.3
util-linux.x86_64 0:2.30.2-2.amzn2.0.4
vulkan.x86_64 0:1.0.61.1-2.amzn2
vulkan-filesystem.noarch 0:1.0.61.1-2.amzn2
wget.x86_64 0:1.14-18.amzn2.1
which.x86_64 0:2.20-7.amzn2.0.2
xdg-utils.noarch 0:1.1.0-0.17.20120809git.amzn2
xkeyboard-config.noarch 0:2.20-1.amzn2
Complete!
Removing intermediate container 9bdd12ea0473
---> f4731c48c18d
Step 5/7 : RUN npm install puppeteer-core
---> Running in 177559a5bc04
npm WARN saveError ENOENT: no such file or directory, open '/var/task/package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open '/var/task/package.json'
npm WARN task No description
npm WARN task No repository field.
npm WARN task No README data
npm WARN task No license field.
+ puppeteer-core@5.5.0
added 54 packages from 75 contributors and audited 54 packages in 3.98s
8 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Removing intermediate container 177559a5bc04
---> 0810cea6a9f0
Step 6/7 : COPY app.js ${LAMBDA_TASK_ROOT}
---> f0a47cd52a53
Step 7/7 : CMD [ "app.handler" ]
---> Running in 0429754cc7a7
Removing intermediate container 0429754cc7a7
---> eab9382dbeb3
Successfully built eab9382dbeb3
Successfully tagged example:latest
コンテナイメージがビルドできたら、ターミナルから docker コマンドを利用して、ローカル環境でコンテナを起動します。
$ docker run -it --name example -p 9000:8080 example
INFO[0000] exec '/var/runtime/bootstrap' (cwd=/var/task, handler=)
起動できました。
次に別のターミナルから、curl コマンドで POST リクエストを送信します。
$ curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
{"statusCode":200}
Docker コンテナを起動しているターミナルには、ログが出力されます。
$ docker run -it --name example -p 9000:8080 example
INFO[0000] exec '/var/runtime/bootstrap' (cwd=/var/task, handler=)
INFO[0030] extensionsDisabledByLayer(/opt/disable-extensions-jwigqn8j) -> stat /opt/disable-extensions-jwigqn8j: no such file or directory
WARN[0030] Cannot list external agents error="open /opt/extensions: no such file or directory"
START RequestId: b3ed3890-c2ba-438b-a5a3-7f3d595a344a Version: $LATEST
END RequestId: b3ed3890-c2ba-438b-a5a3-7f3d595a344a
REPORT RequestId: b3ed3890-c2ba-438b-a5a3-7f3d595a344a Init Duration: 0.33 ms Duration: 1049.27 ms Billed Duration: 1100 ms Memory Size: 3008 MB Max Memory Used: 3008 MB
それでは、https://example.com のスクリーンショット(example.png)が保存されているか確認しましょう。
curl コマンドを実行したターミナルで、コンテナから画像ファイル(example.png)をコピーします。
$ docker cp example:/var/task/example.png .
コピーした画像は、以下のとおりです。
ちゃんとキャプチャできてますね。
さいごに
ローカル環境でのコンテナイメージサイズを確認すると、1.2GB 程度の規模でした。
$ docker images -f label=example
REPOSITORY TAG IMAGE ID CREATED SIZE
example latest 29df2f38a5f3 7 seconds ago 1.2GB
Lambda 関数は最大で 10GB のコンテナイメージ をサポートしているため、これまでよりも Lambda の活用シーンや利用機会が増えるのではないかと期待しております。
ではでは