📝
EC2 に Docker をインストールして AWS SDK for JavaScript V3 を実行してみた
EC2 に Docker を入れてコンテナを動かしてみた
上記に AWS SDK for JavaScript V3 の使用を追加してみました。
SDK での実装内容は Rekognition での画像認識処理です。
Docker のインストールについて
Docker をインストールするまでの手順は上記ブログ通りです。
S3 バケットの作成
Rekognition の画像認識で使用するための S3 バケットとオブジェクトを作成します。
S3 バケットは任意の名称で作成してください。
バケット作成後、適当な画像を「test.png」という名称でアップロードしておいてください。
Dockerfile について
以下の内容で定義しました。
タイトル
Dockerfile
FROM node:22-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . .
RUN npm init -y
RUN npm install express @aws-sdk/client-s3 @aws-sdk/client-rekognition buffer
EXPOSE 80
CMD [ "node", "index.js" ]
今回は S3 と Rekognition の API を使用するため、必要なモジュールをインストールしています。
EC2 内で nano
コマンドなどで上記 Dockerfile を作成します。
$ nano Dockerfile
# 上記の Dockerfile の内容を書き込みます。
$ cat Dockerfile
FROM node:22-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . .
RUN npm init -y
RUN npm install express @aws-sdk/client-s3 @aws-sdk/client-rekognition buffer
EXPOSE 80
CMD [ "node", "index.js" ]
index.js について
以下の内容で定義しました。
タイトル
index.js
const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3");
const {
RekognitionClient,
DetectTextCommand,
} = require("@aws-sdk/client-rekognition");
const s3 = new S3Client({ region: "ap-northeast-1" });
const rekognition = new RekognitionClient({ region: "ap-northeast-1" });
const { Buffer } = require("buffer");
const express = require("express");
const app = express();
app.get("/", (req, res) => {
const main = async () => {
const s3Params = {
Bucket: "your-bucket-name",
Key: "test.png",
};
const { Body } = await s3.send(new GetObjectCommand(s3Params));
const imageBuffer = await streamToBuffer(Body);
const params = {
Image: {
Bytes: imageBuffer,
},
};
const result = await rekognition.send(new DetectTextCommand(params));
res.json(result);
};
main();
});
const streamToBuffer = async (stream) => {
return new Promise((resolve, reject) => {
const chunks = [];
stream.on("data", (chunk) => chunks.push(chunk));
stream.on("end", () => resolve(Buffer.concat(chunks)));
stream.on("error", reject);
});
};
app.listen(80, () => {
console.log("Server is up on 80");
});
your-bucket-name
は作成済みの S3 バケット名に置換してください。
EC2 内で nano
コマンドなどで上記 index.js を作成します。
$ nano index.js
# 上記の index.js の内容を書き込みます。
$ cat Dockerfile
const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3");
const {
RekognitionClient,
DetectTextCommand,
} = require("@aws-sdk/client-rekognition");
const s3 = new S3Client({ region: "ap-northeast-1" });
const rekognition = new RekognitionClient({ region: "ap-northeast-1" });
const { Buffer } = require("buffer");
const express = require("express");
const app = express();
app.get("/", (req, res) => {
const main = async () => {
const s3Params = {
Bucket: "your-bucket-name",
Key: "test.png",
};
const { Body } = await s3.send(new GetObjectCommand(s3Params));
const imageBuffer = await streamToBuffer(Body);
const params = {
Image: {
Bytes: imageBuffer,
},
};
const result = await rekognition.send(new DetectTextCommand(params));
res.json(result);
};
main();
});
const streamToBuffer = async (stream) => {
return new Promise((resolve, reject) => {
const chunks = [];
stream.on("data", (chunk) => chunks.push(chunk));
stream.on("end", () => resolve(Buffer.concat(chunks)));
stream.on("error", reject);
});
};
app.listen(80, () => {
console.log("Server is up on 80");
});
Docker イメージの作成
冒頭のブログと同じ手順でイメージを作成します。
$ docker build -t ec2-nodejs-app .
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ec2-nodejs-app latest xxxxxxxxxxxx 3 seconds ago 75.6MB
$ docker run -d -p 80:80 xxxxxxxxxxxx
b669eaf0f36d5fbb9b5727ed06af8f0c828eb5a21be4d4974f60c07cb2d21533
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
xxxxxxxxxxxx xxxxxxxxxxxx "docker-entrypoint.s…" 57 seconds ago Up 56 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp vibrant_vaughan
アクセス確認
EC2 コンソールから「パブリック IPv4 アドレス」または「パブリック IPv4 DNS」をコピーしてアクセスして以下のような結果が表示されれば成功です。
整形した JSON は以下の通りです。
結果
{
"$metadata": {
"httpStatusCode": 200,
"requestId": "56d24a7d-4934-41b7-80de-900b1ed99870",
"attempts": 1,
"totalRetryDelay": 0
},
"TextDetections": [
{
"Confidence": 50.542545318603516,
"DetectedText": "Google ZIP",
"Geometry": {
"BoundingBox": {
"Height": 0.019531242549419403,
"Left": 0.01251068152487278,
"Top": 0.0234375,
"Width": 0.08618467301130295
},
"Polygon": [
{ "X": 0.01251068152487278, "Y": 0.0234375 },
{ "X": 0.09869536012411118, "Y": 0.0234375 },
{ "X": 0.09869536012411118, "Y": 0.0429687425494194 },
{ "X": 0.01251068152487278, "Y": 0.0429687425494194 }
]
},
"Id": 0,
"Type": "LINE"
},
{
"Confidence": 99.75426483154297,
"DetectedText": "Gmail",
"Geometry": {
"BoundingBox": {
"Height": 0.015625,
"Left": 0.872967541217804,
"Top": 0.0234375,
"Width": 0.03938547894358635
},
"Polygon": [
{ "X": 0.872967541217804, "Y": 0.0234375 },
{ "X": 0.912352979183197, "Y": 0.0234375 },
{ "X": 0.912352979183197, "Y": 0.0390625 },
{ "X": 0.872967541217804, "Y": 0.0390625 }
]
},
"Id": 1,
"Type": "LINE"
},
{
"Confidence": 100,
"DetectedText": "Google",
"Geometry": {
"BoundingBox": {
"Height": 0.1025390625,
"Left": 0.4272165894508362,
"Top": 0.2802734375,
"Width": 0.143177792429924
},
"Polygon": [
{ "X": 0.4272165894508362, "Y": 0.2802734375 },
{ "X": 0.5703943967819214, "Y": 0.2802734375 },
{ "X": 0.5703943967819214, "Y": 0.3828125 },
{ "X": 0.4272165894508362, "Y": 0.3828125 }
]
},
"Id": 2,
"Type": "LINE"
},
{
"Confidence": 99.88655090332031,
"DetectedText": "Google",
"Geometry": {
"BoundingBox": {
"Height": 0.02149811014533043,
"Left": 0.4389778673648834,
"Top": 0.5066777467727661,
"Width": 0.04089590534567833
},
"Polygon": [
{ "X": 0.4389778673648834, "Y": 0.5097874999046326 },
{ "X": 0.47955653071403503, "Y": 0.5066777467727661 },
{ "X": 0.47987377643585205, "Y": 0.525066077709198 },
{ "X": 0.4392951428890228, "Y": 0.5281758308410645 }
]
},
"Id": 3,
"Type": "LINE"
},
{
"Confidence": 99.18763732910156,
"DetectedText": "I'm Feeling Lucky",
"Geometry": {
"BoundingBox": {
"Height": 0.0166015625,
"Left": 0.5032073855400085,
"Top": 0.509765625,
"Width": 0.05652974545955658
},
"Polygon": [
{ "X": 0.5032073855400085, "Y": 0.509765625 },
{ "X": 0.5597371459007263, "Y": 0.509765625 },
{ "X": 0.5597371459007263, "Y": 0.5263671875 },
{ "X": 0.5032073855400085, "Y": 0.5263671875 }
]
},
"Id": 4,
"Type": "LINE"
},
{
"Confidence": 86.1620864868164,
"DetectedText": "Gemini Google Pixel ج",
"Geometry": {
"BoundingBox": {
"Height": 0.02089455910027027,
"Left": 0.36509841680526733,
"Top": 0.559849202632904,
"Width": 0.2692783772945404
},
"Polygon": [
{ "X": 0.36509841680526733, "Y": 0.5624998211860657 },
{ "X": 0.6343363523483276, "Y": 0.559849202632904 },
{ "X": 0.6343767642974854, "Y": 0.5780931711196899 },
{ "X": 0.36513885855674744, "Y": 0.5807437300682068 }
]
},
"Id": 5,
"Type": "LINE"
},
{
"Confidence": 29.602930068969727,
"DetectedText": "8*",
"Geometry": {
"BoundingBox": {
"Height": 0.0166015625,
"Left": 0.0162175502628088,
"Top": 0.9033203125,
"Width": 0.014827474020421505
},
"Polygon": [
{ "X": 0.0162175502628088, "Y": 0.9033203125 },
{ "X": 0.03104502335190773, "Y": 0.9033203125 },
{ "X": 0.03104502335190773, "Y": 0.919921875 },
{ "X": 0.0162175502628088, "Y": 0.919921875 }
]
},
"Id": 6,
"Type": "LINE"
},
{
"Confidence": 98.7762222290039,
"DetectedText": "-",
"Geometry": {
"BoundingBox": {
"Height": 0.019454872235655785,
"Left": 0.8765960931777954,
"Top": 0.9605982899665833,
"Width": 0.044623564928770065
},
"Polygon": [
{ "X": 0.8767257332801819, "Y": 0.9605982899665833 },
{ "X": 0.9212196469306946, "Y": 0.9620190858840942 },
{ "X": 0.9210900068283081, "Y": 0.980053186416626 },
{ "X": 0.8765960931777954, "Y": 0.9786323308944702 }
]
},
"Id": 7,
"Type": "LINE"
},
{
"Confidence": 82.59725189208984,
"DetectedText": "Google",
"Geometry": {
"BoundingBox": {
"Height": 0.01953125,
"Left": 0.01251068152487278,
"Top": 0.0234375,
"Width": 0.05374959483742714
},
"Polygon": [
{ "X": 0.01251068152487278, "Y": 0.0234375 },
{ "X": 0.06626027077436447, "Y": 0.0234375 },
{ "X": 0.06626027077436447, "Y": 0.04296875 },
{ "X": 0.01251068152487278, "Y": 0.04296875 }
]
},
"Id": 8,
"ParentId": 0,
"Type": "WORD"
},
{
"Confidence": 18.487842559814453,
"DetectedText": "ZIP",
"Geometry": {
"BoundingBox": {
"Height": 0.0166015625,
"Left": 0.07552744448184967,
"Top": 0.0234375,
"Width": 0.02316792868077755
},
"Polygon": [
{ "X": 0.07552744448184967, "Y": 0.0234375 },
{ "X": 0.09869537502527237, "Y": 0.0234375 },
{ "X": 0.09869537502527237, "Y": 0.0400390625 },
{ "X": 0.07552744448184967, "Y": 0.0400390625 }
]
},
"Id": 9,
"ParentId": 0,
"Type": "WORD"
},
{
"Confidence": 99.75426483154297,
"DetectedText": "Gmail",
"Geometry": {
"BoundingBox": {
"Height": 0.0107421875,
"Left": 0.872967541217804,
"Top": 0.025390625,
"Width": 0.01714426651597023
},
"Polygon": [
{ "X": 0.872967541217804, "Y": 0.025390625 },
{ "X": 0.8901118040084839, "Y": 0.025390625 },
{ "X": 0.8901118040084839, "Y": 0.0361328125 },
{ "X": 0.872967541217804, "Y": 0.0361328125 }
]
},
"Id": 10,
"ParentId": 1,
"Type": "WORD"
},
{
"Confidence": 100,
"DetectedText": "Google",
"Geometry": {
"BoundingBox": {
"Height": 0.1025390625,
"Left": 0.4272165894508362,
"Top": 0.2802734375,
"Width": 0.143177792429924
},
"Polygon": [
{ "X": 0.4272165894508362, "Y": 0.2802734375 },
{ "X": 0.5703943967819214, "Y": 0.2802734375 },
{ "X": 0.5703943967819214, "Y": 0.3828125 },
{ "X": 0.4272165894508362, "Y": 0.3828125 }
]
},
"Id": 11,
"ParentId": 2,
"Type": "WORD"
},
{
"Confidence": 99.88655090332031,
"DetectedText": "Google",
"Geometry": {
"BoundingBox": {
"Height": 0.0166015625,
"Left": 0.4392639100551605,
"Top": 0.509765625,
"Width": 0.02363128587603569
},
"Polygon": [
{ "X": 0.4392639100551605, "Y": 0.509765625 },
{ "X": 0.4628952145576477, "Y": 0.509765625 },
{ "X": 0.4628952145576477, "Y": 0.5263671875 },
{ "X": 0.4392639100551605, "Y": 0.5263671875 }
]
},
"Id": 12,
"ParentId": 3,
"Type": "WORD"
},
{
"Confidence": 97.82994842529297,
"DetectedText": "I'm",
"Geometry": {
"BoundingBox": {
"Height": 0.0126953125,
"Left": 0.5032073855400085,
"Top": 0.509765625,
"Width": 0.009730529971420765
},
"Polygon": [
{ "X": 0.5032073855400085, "Y": 0.509765625 },
{ "X": 0.5129379034042358, "Y": 0.509765625 },
{ "X": 0.5129379034042358, "Y": 0.5224609375 },
{ "X": 0.5032073855400085, "Y": 0.5224609375 }
]
},
"Id": 13,
"ParentId": 4,
"Type": "WORD"
},
{
"Confidence": 99.76399993896484,
"DetectedText": "Feeling",
"Geometry": {
"BoundingBox": {
"Height": 0.0166015625,
"Left": 0.5147913694381714,
"Top": 0.509765625,
"Width": 0.02409464493393898
},
"Polygon": [
{ "X": 0.5147913694381714, "Y": 0.509765625 },
{ "X": 0.5388860106468201, "Y": 0.509765625 },
{ "X": 0.5388860106468201, "Y": 0.5263671875 },
{ "X": 0.5147913694381714, "Y": 0.5263671875 }
]
},
"Id": 14,
"ParentId": 4,
"Type": "WORD"
},
{
"Confidence": 99.96896362304688,
"DetectedText": "Lucky",
"Geometry": {
"BoundingBox": {
"Height": 0.0146484375,
"Left": 0.5412027835845947,
"Top": 0.5107421875,
"Width": 0.01853434182703495
},
"Polygon": [
{ "X": 0.5412027835845947, "Y": 0.5107421875 },
{ "X": 0.5597371459007263, "Y": 0.5107421875 },
{ "X": 0.5597371459007263, "Y": 0.525390625 },
{ "X": 0.5412027835845947, "Y": 0.525390625 }
]
},
"Id": 15,
"ParentId": 4,
"Type": "WORD"
},
{
"Confidence": 99.10094451904297,
"DetectedText": "Gemini",
"Geometry": {
"BoundingBox": {
"Height": 0.0126953125,
"Left": 0.3651265501976013,
"Top": 0.5625,
"Width": 0.02177785150706768
},
"Polygon": [
{ "X": 0.3651265501976013, "Y": 0.5625 },
{ "X": 0.38690438866615295, "Y": 0.5625 },
{ "X": 0.38690438866615295, "Y": 0.5751953125 },
{ "X": 0.3651265501976013, "Y": 0.5751953125 }
]
},
"Id": 16,
"ParentId": 5,
"Type": "WORD"
},
{
"Confidence": 99.80243682861328,
"DetectedText": "Google",
"Geometry": {
"BoundingBox": {
"Height": 0.0166015625,
"Left": 0.41053569316864014,
"Top": 0.5634765625,
"Width": 0.02224121056497097
},
"Polygon": [
{ "X": 0.41053569316864014, "Y": 0.5634765625 },
{ "X": 0.43277689814567566, "Y": 0.5634765625 },
{ "X": 0.43277689814567566, "Y": 0.580078125 },
{ "X": 0.41053569316864014, "Y": 0.580078125 }
]
},
"Id": 17,
"ParentId": 5,
"Type": "WORD"
},
{
"Confidence": 99.82938385009766,
"DetectedText": "Pixel",
"Geometry": {
"BoundingBox": {
"Height": 0.013671875,
"Left": 0.43416696786880493,
"Top": 0.5634765625,
"Width": 0.01529083214700222
},
"Polygon": [
{ "X": 0.43416696786880493, "Y": 0.5634765625 },
{ "X": 0.4494577944278717, "Y": 0.5634765625 },
{ "X": 0.4494577944278717, "Y": 0.5771484375 },
{ "X": 0.43416696786880493, "Y": 0.5771484375 }
]
},
"Id": 18,
"ParentId": 5,
"Type": "WORD"
},
{
"Confidence": 45.915557861328125,
"DetectedText": "ج",
"Geometry": {
"BoundingBox": {
"Height": 0.0126953125,
"Left": 0.45131123065948486,
"Top": 0.5634765625,
"Width": 0.00880381278693676
},
"Polygon": [
{ "X": 0.45131123065948486, "Y": 0.5634765625 },
{ "X": 0.4601150453090668, "Y": 0.5634765625 },
{ "X": 0.4601150453090668, "Y": 0.576171875 },
{ "X": 0.45131123065948486, "Y": 0.576171875 }
]
},
"Id": 19,
"ParentId": 5,
"Type": "WORD"
},
{
"Confidence": 29.602930068969727,
"DetectedText": "8*",
"Geometry": {
"BoundingBox": {
"Height": 0.0166015625,
"Left": 0.0162175502628088,
"Top": 0.9033203125,
"Width": 0.014827474020421505
},
"Polygon": [
{ "X": 0.0162175502628088, "Y": 0.9033203125 },
{ "X": 0.03104502335190773, "Y": 0.9033203125 },
{ "X": 0.03104502335190773, "Y": 0.919921875 },
{ "X": 0.0162175502628088, "Y": 0.919921875 }
]
},
"Id": 20,
"ParentId": 6,
"Type": "WORD"
},
{
"Confidence": 98.7762222290039,
"DetectedText": "-",
"Geometry": {
"BoundingBox": {
"Height": 0.019454872235655785,
"Left": 0.8765960931777954,
"Top": 0.9605982899665833,
"Width": 0.044623564928770065
},
"Polygon": [
{ "X": 0.8767257332801819, "Y": 0.9605982899665833 },
{ "X": 0.9212196469306946, "Y": 0.9620190858840942 },
{ "X": 0.9210900068283081, "Y": 0.980053186416626 },
{ "X": 0.8765960931777954, "Y": 0.9786323308944702 }
]
},
"Id": 21,
"ParentId": 7,
"Type": "WORD"
}
],
"TextModelVersion": "3.0"
}
ちなみに今回使用した画像は以下の通りグーグルのトップ画像です。
そのため、検出結果には Google などの文字列が含まれています。
まとめ
EC2 に Docker をインストールして AWS SDK for JavaScript V3 を実行してみました。
どなたかの参考になれば幸いです。
Discussion