💭
AWS LambdaでWeb操作してみた
やったこと
API GateWayにPOST そしてLambdaコンテナでSeleniumでタイトルを取得した。
対象読者
- Lambdaでweb操作したい方
- API Gatewayを使いたい方
検証環境
- AWS Lambda Python
- Selenium
- chrome
- umihico/docker-lambda-selenium
- AWS CLI
- Docker
- Ubuntu 24.04LTS (AWS CLIを実行した環境)
手順
ステップ1: ファイル構成
最終的なファイル構成は以下のようになります:
docker-selenium-lambda/
├── Dockerfile
├── main.py
作業ディレクトリを作成
mkdir docker-selenium-lambda
cd docker-selenium-lambda
ステップ2: Dockerfileを作成
Lambdaの環境にはブラウザがインストールされてないため、コンテナを利用します。
以下のDockerイメージを活用させていただきます。ありがとうございます!
以下のようにDockerfileとして保存する
# Dockerfile
FROM umihico/aws-lambda-selenium-python:latest
# Lambda関数コードをコピー
COPY main.py ./
# Lambda関数のハンドラを指定
CMD ["main.handler"]
ステップ3: main.pyを作成
# main.py
from selenium import webdriver
from tempfile import mkdtemp
def handler(event, context):
# Chrome オプションの設定
options = webdriver.ChromeOptions()
options.binary_location = '/opt/chrome/chrome'
options.add_argument("--headless=new")
options.add_argument('--no-sandbox')
options.add_argument("--disable-gpu")
options.add_argument("--window-size=1280,1696")
options.add_argument("--single-process")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-dev-tools")
options.add_argument("--no-zygote")
options.add_argument(f"--user-data-dir={mkdtemp()}")
options.add_argument(f"--data-path={mkdtemp()}")
options.add_argument(f"--disk-cache-dir={mkdtemp()}")
options.add_argument("--remote-debugging-port=9222")
# ChromeDriverサービスの設定
service = webdriver.ChromeService("/opt/chromedriver")
# WebDriverを起動 with文でエラーが起きても確実にdriver.quitする
with webdriver.Chrome(service=service, options=options) as driver:
driver.get("https://www.google.com/")
title = driver.title
print(f"ページタイトル: {title}")
return {'statusCode': 200, 'body': title}
ステップ4: デプロイ
今回使う変数
AWS_ACCOUNT_ID=あなたのアカウントID 後で変数に格納する。
AWS_REGION=あなたの使うリージョン
FUNCTION_NAME=ラムダ関数の名前
REPOSITORY_NAME=リポジトリで使う名前
ROLE_NAME=IAMロールの名前
例
AWS_ACCOUNT_ID="000011112222"
AWS_REGION="ap-northeast-1"
FUNCTION_NAME="selenium"
REPOSITORY_NAME="selenium-lambda"
ROLE_NAME="lambda-selenium-execution-role"
AWSアカウントIDを取得
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
ECRリポジトリを作成
aws ecr create-repository --repository-name $REPOSITORY_NAME --region $AWS_REGION
実行結果
test@test:~$ aws ecr create-repository --repository-name $REPOSITORY_NAME --region $AWS_REGION
{
"repository": {
"repositoryArn": "arn:aws:ecr:ap-northeast-1:************:repository/selenium-lambda",
"registryId": "************",
"repositoryName": "selenium-lambda",
"repositoryUri": "************.dkr.ecr.ap-northeast-1.amazonaws.com/selenium-lambda",
"createdAt": "2025-11-08T02:02:58.122000+09:00",
"imageTagMutability": "MUTABLE",
"imageScanningConfiguration": {
"scanOnPush": false
},
"encryptionConfiguration": {
"encryptionType": "AES256"
}
}
}
Dockerイメージをビルド
docker build -t $REPOSITORY_NAME .
ECRにログイン
aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
実行結果
test@test:~$ docker build -t $REPOSITORY_NAME .
[+] Building 53.5s (12/12) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 426B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:22.04 2.5s
=> [auth] library/ubuntu:pull token for registry-1.docker.io 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/7] FROM docker.io/library/ubuntu:22.04@sha256:09506232a8004baa32c47d68f1e5c307d648fdd59f5e7eaa42aaf87914100db3 2.4s
=> => resolve docker.io/library/ubuntu:22.04@sha256:09506232a8004baa32c47d68f1e5c307d648fdd59f5e7eaa42aaf87914100db3 0.0s
=> => sha256:392fa14dddd09da29a5c3d26948ff81c494424035b755d01b84ab12d92127433 2.30kB / 2.30kB 0.0s
=> => sha256:af6eca94c8104c8e90d3f9efe59c2b3a02b20aad3d985e31c7cd009ea104c447 29.54MB / 29.54MB 1.3s
=> => sha256:09506232a8004baa32c47d68f1e5c307d648fdd59f5e7eaa42aaf87914100db3 6.69kB / 6.69kB 0.0s
=> => sha256:4cb780d50443fc4463f1f9360c03ca46512e4fdd8fd97c5ce7e69c8758924575 424B / 424B 0.0s
=> => extracting sha256:af6eca94c8104c8e90d3f9efe59c2b3a02b20aad3d985e31c7cd009ea104c447 0.9s
=> [2/7] RUN apt-get update && apt-get install -y openssh-server sudo 45.2s
=> [3/7] RUN mkdir /var/run/sshd 0.5s
=> [4/7] RUN mkdir -p /root/.ssh 0.5s
=> [5/7] RUN chmod 700 /root/.ssh 0.4s
=> [6/7] RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config 0.5s
=> [7/7] RUN sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config 0.4s
=> exporting to image 0.8s
=> => exporting layers 0.8s
=> => writing image sha256:9c491dda071ec10dba8d4342dac54d6dbf564c0d2343c953b847dc41e54addbd 0.0s
=> => naming to docker.io/library/selenium-lambda
イメージにタグを付ける
docker tag $REPOSITORY_NAME:latest $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$REPOSITORY_NAME:latest
ECRにプッシュ
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$REPOSITORY_NAME:latest
実行結果
test@test:~/lambda/test/docker-selenium-lambda$ docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$REPOSITORY_NAME:latest
The push refers to repository [************.dkr.ecr.ap-northeast-1.amazonaws.com/selenium-lambda]
3904acea8cae: Pushed
42ad71c1513d: Pushed
7423929354e4: Pushed
770d3ade5423: Pushed
dfa564011b45: Pushed
d04b1852737c: Pushed
d2bc5d348ed7: Pushed
7c5a65f222db: Pushed
98f316bb40c4: Pushed
fc1541de968a: Pushed
231ae437bba4: Pushed
latest: digest: sha256:6823d0ed47085d7fa27c86dd9b176f4d7a5a3f1013df96ba8526219ea402705f size: 2629
ロールを作成
aws iam create-role --role-name $ROLE_NAME --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "lambda.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}'
実行結果
test@test:~/lambda/test/docker-selenium-lambda$ aws iam create-role --role-name $ROLE_NAM
E --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "lambda.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}'
{
"Role": {
"Path": "/",
"RoleName": "lambda-selenium-execution-role",
"RoleId": "************",
"Arn": "arn:aws:iam::************:role/lambda-selenium-execution-role",
"CreateDate": "2025-11-07T17:16:50+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
}
}
ロールにポリシーを付与
aws iam attach-role-policy --role-name $ROLE_NAME --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
lambda関数を作成
ロールが付与されるのを待ってから作成します。なので30秒ほど待ちます。
ROLE_ARN="arn:aws:iam::$AWS_ACCOUNT_ID:role/lambda-selenium-execution-role"
aws lambda create-function --function-name $FUNCTION_NAME --package-type Image --code ImageUri=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$REPOSITORY_NAME:latest --role $ROLE_ARN --timeout 300 --memory-size 2048 --ephemeral-storage Size=2048 --region $AWS_REGION
実行結果
test@test:~/lambda/test/docker-selenium-lambda$ ROLE_ARN="arn:aws:iam::$AWS_ACCOUNT_ID:ro
le/lambda-selenium-execution-role"
aws lambda create-function --function-name $FUNCTION_NAME --package-type Image --code ImageUri
=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$REPOSITORY_NAME:latest --role $ROLE_ARN --
timeout 300 --memory-size 2048 --ephemeral-storage Size=2048 --region $AWS_REGION
{
"FunctionName": "selenium",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:************:function:selenium",
"Role": "arn:aws:iam::************:role/lambda-selenium-execution-role",
"CodeSize": 0,
"Description": "",
"Timeout": 300,
"MemorySize": 2048,
"LastModified": "2025-11-07T17:21:05.761+0000",
"CodeSha256": "6823d0ed47085d7fa27c86dd9b176f4d7a5a3f1013df96ba8526219ea402705f",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "0cdee188-39f0-45e9-9cf7-5776bcc34c73",
"State": "Pending",
"StateReason": "The function is being created.",
"StateReasonCode": "Creating",
"PackageType": "Image",
"Architectures": [
"x86_64"
],
"EphemeralStorage": {
"Size": 2048
},
"SnapStart": {
"ApplyOn": "None",
"OptimizationStatus": "Off"
},
"LoggingConfig": {
"LogFormat": "Text",
"LogGroup": "/aws/lambda/selenium"
}
}
ステップ6: テスト実行
# Lambda関数をテスト
aws lambda invoke --function-name $FUNCTION_NAME --region $AWS_REGION --log-type Tail --query 'LogResult' --output text response.json | base64 -d
実行結果
test@test:~/lambda/test/docker-selenium-lambda$ # Lambda関数をテスト
aws lambda invoke --function-name $FUNCTION_NAME --region $AWS_REGION --log-type Tail --query
'LogResult' --output text response.json | base64 -d
START RequestId: 0d243959-e165-49ed-98b6-37612856f102 Version: $LATEST
ページタイトル: Google
END RequestId: 0d243959-e165-49ed-98b6-37612856f102
REPORT RequestId: 0d243959-e165-49ed-98b6-37612856f102 Duration: 5713.08 ms Billed Duratio
n: 6183 ms Memory Size: 2048 MB Max Memory Used: 535 MB Init Duration: 469.11 ms
# レスポンスを確認
cat response.json
実行結果
test@test:~/lambda/test/docker-selenium-lambda$ cat response.json
{"statusCode": 200, "body": "Google"}
ステップ7: ログの確認
# CloudWatch Logsでリアルタイムにログを確認
aws logs tail /aws/lambda/$FUNCTION_NAME --follow --region $AWS_REGION
実行結果
test@test:~/lambda/test/docker-selenium-lambda$ # CloudWatch Logsでリアルタイムにログを確認
aws logs tail /aws/lambda/$FUNCTION_NAME --follow --region $AWS_REGION
2025-11-07T17:25:06.647000+00:00 2025/11/07/[$LATEST]9c42a19112ab43eca03f3247eefb5e10 START RequestId: 0d243959-e165-49ed-98b6-37612856f102 Version: $LATEST
2025-11-07T17:25:12.074000+00:00 2025/11/07/[$LATEST]9c42a19112ab43eca03f3247eefb5e10 ページタイトル: Google
2025-11-07T17:25:12.361000+00:00 2025/11/07/[$LATEST]9c42a19112ab43eca03f3247eefb5e10 END RequestId: 0d243959-e165-49ed-98b6-37612856f102
2025-11-07T17:25:12.361000+00:00 2025/11/07/[$LATEST]9c42a19112ab43eca03f3247eefb5e10 REPORT RequestId: 0d243959-e165-49ed-98b6-37612856f102 Duration: 5713.08 ms Billed Duration: 6183ms Memory Size: 2048 MB Max Memory Used: 535 MB Init Duration: 469.11 ms
API Gatewayを設定する
HTTP APIを作成
今回は低コストで運用できるためHTTP APIを使用
また、次のインテグレーションでIDを使うため変数に格納します。
API_ID=$(aws apigatewayv2 create-api --name "selenium-test-api" --protocol-type HTTP --region $AWS_REGION --query 'ApiId' --output text)
test用のインテグレーションを作成
また、インテグレーションで使うIDを変数に格納します。
TEST_INTEGRATION_ID=$(aws apigatewayv2 create-integration --api-id $API_ID --integration-type AWS_PROXY --integration-uri arn:aws:lambda:$AWS_REGION:$AWS_ACCOUNT_ID:function:$FUNCTION_NAME --payload-format-version 2.0 --region $AWS_REGION --query 'IntegrationId' --output text)
ルートを作成
aws apigatewayv2 create-route --api-id $API_ID --route-key "POST /test" --target integrations/$TEST_INTEGRATION_ID --region $AWS_REGION
実行結果
test@test:~/lambda/test/docker-selenium-lambda$ aws apigatewayv2 create-route --api-id $API_ID --route-key "POST /test" --target integrations/$TEST_INTEGRATION_ID --region $AWS_REGION{
"ApiKeyRequired": false,
"AuthorizationType": "NONE",
"RouteId": "************",
"RouteKey": "POST /test",
"Target": "integrations/e4o2enn"
}
ステージを作成しデプロイする
aws apigatewayv2 create-stage --api-id $API_ID --stage-name prod --auto-deploy --region $AWS_REGION
実行結果
test@test:~/lambda/test/docker-selenium-lambda$ aws apigatewayv2 create-stage --api-id$API_ID --stage-name prod --auto-deploy --region $AWS_REGION
{
"AutoDeploy": true,
"CreatedDate": "2025-11-07T17:29:47+00:00",
"DefaultRouteSettings": {
"DetailedMetricsEnabled": false
},
"LastUpdatedDate": "2025-11-07T17:29:47+00:00",
"RouteSettings": {},
"StageName": "prod",
"StageVariables": {},
"Tags": {}
}
Lambda関数に API Gateway からの呼び出し権限を付与
aws lambda add-permission --function-name $FUNCTION_NAME --statement-id apigateway-test --action lambda:InvokeFunction --principal apigateway.amazonaws.com --source-arn "arn:aws:execute-api:$AWS_REGION:$AWS_ACCOUNT_ID:$API_ID/*/*/test" --region $AWS_REGION
実行結果
test@test:~/lambda/test/docker-selenium-lambda$ aws lambda add-permission --function-name
$FUNCTION_NAME --statement-id apigateway-test --action lambda:InvokeFunction --principal apig
ateway.amazonaws.com --source-arn "arn:aws:execute-api:$AWS_REGION:$AWS_ACCOUNT_ID:$API_ID/*/*
/test" --region $AWS_REGION
{
"Statement": "{\"Sid\":\"apigateway-test\",\"Effect\":\"Allow\",\"Principal\":{\"Service\"
:\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lam
bda:ap-northeast-1:************:function:selenium\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":
\"arn:aws:execute-api:ap-northeast-1:************:urmkpnelmf/*/*/test\"}}}"
}
API エンドポイント
ENDPOINT=https://$API_ID.execute-api.$AWS_REGION.amazonaws.com/prod/test
API Gatewayのテスト
curl -X POST $ENDPOINT
実行結果
test@test:~/lambda/test/docker-selenium-lambda$ curl -X POST $ENDPOINT
Google
Discussion