Pipeline de traitement d’image sans serveur avec AWS ECS et Lambda –

Bienvenue aux développeurs dans le monde du développement et de l’automatisation. Aujourd’hui, nous plongeons dans un projet passionnant dans lequel nous créerons un pipeline de traitement d’image sans serveur avec AWS Services.
Le projet commence par la création de seaux S3 pour stocker des images téléchargées et des vignettes traitées, et finalement en utilisant de nombreux services comme Lambda, API Gateway (pour déclencher la fonction lambda), DynamoDB (stockage des métadonnées d’image), et nous exécuterons enfin ce programme dans ECS Cluster en créant une image docker du projet.
Ce projet est rempli de services cloud et de piles technologiques de développement comme Next.js, et la pratique améliorera davantage votre compréhension des services cloud et comment ils interagissent les uns avec les autres. Donc, avec plus ADO, commençons!
Remarque: le code et les instructions de cet article sont destinés à une utilisation et à l’apprentissage de la démonstration uniquement. Un environnement de production nécessitera une poignée plus étroite sur les configurations et la sécurité.
Condition préalable
Avant d’entrer dans le projet, nous devons nous assurer que les exigences suivantes sont satisfaites dans notre système:
- Un compte AWS: Puisque nous utilisons des services AWS pour le projet, nous avons besoin d’un compte AWS. Un utilisateur IAM configuré avec un accès aux services requis serait apprécié.
- Compréhension de base des services AWS: Étant donné que nous avons affaire à de nombreux services AWS, il est préférable d’en avoir une compréhension décente, comme S3, qui est utilisé pour le stockage, la passerelle API pour déclencher la fonction lambda, et bien d’autres.
- Nœud installé: Notre frontend est construit avec Next.js, donc avoir un nœud dans votre système est nécessaire.
Pour référence de code, voici GitHub Repo.
Configuration des services AWS
Nous commencerons le projet par Configuration de nos services AWS. D’abord et avant tout, nous créerons 2 seaux S3, à savoir sample-image-uploads-bucket
et sample-thumbnails-bucket
. La raison de ce nom long est que le nom du seau doit être unique dans tout l’espace de travail AWS.
Donc, pour créer le seau, dirigez-vous vers le tableau de bord S3 et cliquez sur «Créer un seau», sélectionnez «General Purpose» et donnez-lui un nom (exemples-image-uploads-bucket) et laissez le reste de la configuration par défaut.
De même, créez l’autre seau nommé échantillonnage Décochez l’accès public au public Parce que nous en aurons besoin pour notre cluster ECS.



Nous devons nous assurer que l’échantillon de trois ans-trois-Bucket a un accès à la lecture du public, afin que le frontend ECS puisse les afficher. Pour cela, nous attacherons la politique suivante à ce seau:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::sample-thumbnails-bucket/*"
}
]
}
Après avoir créé des seaux, passons à notre base de données pour stocker les métadonnées de l’image. Nous allons créer une table DynamoDB pour cela. Accédez à votre console DynamoDB, cliquez sur Créer une table, donnez-lui un nom (image_metadata), et dans la clé primaire Sélectionnez String, nommez-le image_id
.

Les services AWS communiqueront entre eux, ils ont donc besoin d’un rôle avec des autorisations appropriées. Pour créer un rôle, accédez au tableau de bord IAM, sélectionnez le rôle et cliquez sur Créer un rôle. Sous Type d’identité de confiancesélectionner Service AWS, et sous cas d’utilisationchoisissez Lambda. Joindre les politiques suivantes:
- Amazons3fullaccess
- Amazondynamodbfullaccess
- Cloudwatchlogsfullaccess
Donnez un nom à ce rôle (Lambda-Image-Processor-Role) et enregistrez-le.


Création de la fonction lambda
Nous avons notre rôle lambda, nos seaux et notre table DynamoDB prêts, alors maintenant, allons-y Créer la fonction lambda qui traitera l’image et en fera la vignette, puisque nous utilisons la bibliothèque d’oreillers pour traiter les images, Lambda par défaut ne le fournit pas. Pour résoudre ce problème, nous ajouterons une couche dans la fonction lambda. Pour ce faire, suivez les étapes suivantes:
Maintenant, allez à votre Lambda Tableau de bord, cliquez sur Créer une fonction. Sélectionner Auteur de zéro et choisir Python 3.9 En tant que langue d’exécution, donnez-lui un nom: Processeur d’image et dans le Code onglet, vous avez le Télécharger de Option, sélectionnez cela, choisissez fermeture éclair fichier et télécharger votre fichier zip du image-processeur.
Aller à Configurationet sous le Autorisation colonne, modifiez la configuration par Changer le rôle existant Au rôle, nous avons créé le roleur de processeur d’image lambda-IMAGE.


Maintenant, allez dans votre seau S3 (échantillon d’image-uploads-bucket) et aller à son Propriétés section et faire défiler vers le haut Notificatio de l’événementn, ici cliquez sur Créer une notification d’événementdonnez-lui un nom (déclencheur de déclencheur-image) et dans le type d’événement, sélectionnez Put et sélectionnez la fonction lambda que nous avons créée (Processeur d’image).

Maintenant, puisque l’oreiller n’est pas intégré avec la bibliothèque Lambda, nous ferons les étapes suivantes pour résoudre ce problème:
- Allez à votre fonction Lambda (jemage-processeur) et faire défiler vers le bas vers le Couche Section, ici cliquez sur Ajouter la couche.

- Dans le Ajouter la couche Section, sélectionnez Spécifiez un ARN et fournir cet arn
arn:aws:lambda:us-east-1:770693421928:layer:Klayers-p39-pillow:1
. Changer la région en conséquence; J’utilise US-East-1. Ajoutez la couche.

Maintenant, dans l’onglet Code de votre fonction lambda, vous auriez un lambda-function.py, mettez le contenu suivant à l’intérieur du lambda_function.py:
import boto3
import uuid
import os
from PIL import Image
from io import BytesIO
import datetime
s3 = boto3.client('s3')
dynamodb = boto3.client('dynamodb')
UPLOAD_BUCKET = '<YOUR_BUCKET_NAME>'
THUMBNAIL_BUCKET = '<YOUR_BUCKET_NAME>'
DDB_TABLE = 'image_metadata'
def lambda_handler(event, context):
record = event['Records'][0]
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
response = s3.get_object(Bucket=bucket, Key=key)
image = Image.open(BytesIO(response['Body'].read()))
image.thumbnail((200, 200))
thumbnail_buffer = BytesIO()
image.save(thumbnail_buffer, 'JPEG')
thumbnail_buffer.seek(0)
thumbnail_key = f"thumb_{key}"
s3.put_object(
Bucket=THUMBNAIL_BUCKET,
Key=thumbnail_key,
Body=thumbnail_buffer,
ContentType='image/jpeg'
)
image_id = str(uuid.uuid4())
original_url = f"https://{UPLOAD_BUCKET}.s3.amazonaws.com/{key}"
thumbnail_url = f"https://{THUMBNAIL_BUCKET}.s3.amazonaws.com/{thumbnail_key}"
uploaded_at = datetime.datetime.now().isoformat()
dynamodb.put_item(
TableName=DDB_TABLE,
Item={
'image_id': {'S': image_id},
'original_url': {'S': original_url},
'thumbnail_url': {'S': thumbnail_url},
'uploaded_at': {'S': uploaded_at}
}
)
return {
'statusCode': 200,
'body': f"Thumbnail created: {thumbnail_url}"
}
Maintenant, nous aurons besoin d’une autre fonction lambda pour la passerelle API, car cela agira comme le point d’entrée pour que notre application Frontend ECS récupérera les données d’image de DynamoDB.
Pour créer la fonction lambda, accédez à votre Tableau de bord Lambdacliquez sur créer une fonctionsélectionner Auteur de zéro et Python 3.9 Comme l’exécution, donnez-lui un nom, get-image-metadata et dans la configuration, sélectionnez le même rôle que nous avons attribué à d’autres fonctions lambda (Lambda-Image-Processor-Role)

Maintenant, dans la section Code de la fonction, mettez le contenu suivant:
import boto3
import json
dynamodb = boto3.client('dynamodb')
TABLE_NAME = 'image_metadata'
def lambda_handler(event, context):
try:
response = dynamodb.scan(TableName=TABLE_NAME)
images = []
for item in response['Items']:
images.append({
'image_id': item['image_id']['S'],
'original_url': item['original_url']['S'],
'thumbnail_url': item['thumbnail_url']['S'],
'uploaded_at': item['uploaded_at']['S']
})
return {
'statusCode': 200,
'headers': {
"Content-Type": "application/json"
},
'body': json.dumps(images)
}
except Exception as e:
return {
'statusCode': 500,
'body': f"Error: {str(e)}"
}
Création de la passerelle API
La passerelle API agira comme le point d’entrée pour que votre application Frontend ECS puisse récupérer les données d’image de DynamoDB. Il se connectera à la fonction lambda qui interroge DynamoDB et renvoie les métadonnées d’image. L’URL de la passerelle est utilisée dans notre application Frontend pour afficher des images. Pour créer la passerelle API, effectuez les étapes suivantes:
- Aller au Console de gestion AWS → Rechercher Passerelle API → Click Créer une API.
- Sélectionner API HTTP.
- Cliquer sur Construire.
- Nom de l’API: Image-gallery-api
- Ajouter des intégrations: Sélectionnez Lambda et sélectionnez la fonction get_image_metadata
- Sélectionner Méthode: Obtenir et Chemin: / images
- Type de point de terminaison: Régional
- Cliquer sur Suivant et créer l’URL de la passerelle API.

Avant de créer le frontend, testons manuellement l’application. Accédez d’abord à votre seau S3 Téléchargez (échantillon d’image-uploads-bucket) et télécharger un JPG / JPEG image; Une autre image ne fonctionnera pas car votre fonction ne traite que ces deux types:
Dans l’image ci-dessus, j’ai téléchargé une image intitulée «ghibil-art.jpg”Fichier, et une fois téléchargé, il déclenchera la fonction lambda, qui en créera la vignette nommée »Thumbnail-Ghibil-art.jpg»Et stockez-le échantillon Et les informations sur l’image seront stockées dans image-métadata table dans dynamoDB.


Dans l’image ci-dessus, vous pouvez voir l’élément à l’intérieur de la section d’élément Explore de notre table DynamoDB « Image-Metadata.”Pour tester l’api-gateway, nous vérifierons l’URL invoquée de notre image-Gallery-API suivie de / images. Il affichera la sortie suivante, avec la commande Curl:
Maintenant, notre application fonctionne bien, nous pouvons déployer un frontend pour visualiser le projet.
Création de l’application Frontend
Par souci de simplicité, nous créerons une galerie simple et minimale en utilisant Next.js, Le docker et le déployer sur ECS. Pour créer l’application, effectuez les étapes suivantes:
Initialisation
npx create-next-app@latest image-gallery
cd image-gallery
npm install
npm install axios
Créer le composant de la galerie
Créez un nouveau fichier composants / galerie.js:
'use client';
import { useState, useEffect } from 'react';
import axios from 'axios';
import styles from './Gallery.module.css';
const Gallery = () => {
const [images, setImages] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchImages = async () => {
try {
const response = await axios.get('https://<YOUR_API_GATEWAY_INVOKE_URL>/images');
setImages(response.data);
setLoading(false);
} catch (error) {
console.error('Error fetching images:', error);
setLoading(false);
}
};
fetchImages();
}, []);
if (loading) {
return <div className={styles.loading}>Loading...</div>;
}
return (
<div className={styles.gallery}>
{images.map((image) => (
<div key={image.image_id} className={styles.imageCard}>
<img
src={image.thumbnail_url}
alt="Gallery thumbnail"
width={200}
height={150}
className={styles.thumbnail}
/>
<p className={styles.date}>
{new Date(image.uploaded_at).toLocaleDateString()}
</p>
</div>
))}
</div>
);
};
export default Gallery;
Assurez-vous de changer la passerelle-url en votre API_GATEWAY_URL
Ajouter le module CSS
Créer des composants / galerie.module.css:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 20px;
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
.imageCard {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
overflow: hidden;
transition: transform 0.2s;
}
.imageCard:hover {
transform: scale(1.05);
}
.thumbnail {
width: 100%;
height: 150px;
object-fit: cover;
}
.date {
text-align: center;
padding: 10px;
margin: 0;
font-size: 0.9em;
color: #666;
}
.loading {
text-align: center;
padding: 50px;
font-size: 1.2em;
}
Mettre à jour la page d’accueil
Modifier app / page.js:
import Gallery from '../components/Gallery';
export default function Home() {
return (
<main>
<h1 style={{ textAlign: 'center', padding: '20px' }}>Image Gallery</h1>
<Gallery />
</main>
);
}
Composant d’image intégré de next.js
Pour utiliser le composant d’image intégré de Next.js pour une meilleure optimisation, mise à jour Next.config.mjs:
const nextConfig = {
images: {
domains: ['sample-thumbnails-bucket.s3.amazonaws.com'],
},
};
export default nextConfig;
Exécuter l’application
Visitez http: // localhost: 3000 dans votre navigateur, et vous verrez l’application fonctionner avec toutes les miniatures téléchargées.
À des fins de démonstration, j’ai mis quatre images (JPEG / JPG) dans mes échantillons-images-téléchargement-Bucket. Grâce à la fonction, ils sont transformés en vignettes et stockés dans l’échantillon-thumbnail-bucket.



L’application ressemble à ceci:

Conteneuriser et créer le cluster ECS
Maintenant, nous avons presque terminé le projet, nous continuerons donc en créant un docker du projet comme suit:
# Use the official Node.js image as a base
FROM node:18-alpine AS builder
# Set working directory
WORKDIR /app
# Copy package files and install dependencies
COPY package.json package-lock.json ./
RUN npm install
# Copy the rest of the application code
COPY . .
# Build the Next.js app
RUN npm run build
# Use a lightweight Node.js image for production
FROM node:18-alpine
# Set working directory
WORKDIR /app
# Copy built files from the builder stage
COPY --from=builder /app ./
# Expose port
EXPOSE 3000
# Run the application
CMD ["npm", "start"]
Nous allons maintenant construire l’image Docker en utilisant:
docker build -t sample-nextjs-app .

Maintenant que nous avons notre image Docker, nous allons le pousser vers AWS ECR Repo, pour cela, faire les étapes suivantes:
Étape 1: poussez l’image Docker vers Amazon ECR
- Aller à la console de gestion AWS → Rechercher ECR (Registre des conteneurs élastiques) → Ouvert ECR.
- Créer un nouveau référentiel:
- Faire un clic Créer un référentiel.
- Ensemble Nom de référentiel (par exemple, échantillon-nextjs-app).
- Choisir Privé (ou Publique si nécessaire).
- Faire un clic Créer un référentiel.
- Poussez votre image Docker vers ECR:
- Dans le référentiel nouvellement créé, cliquez Afficher les commandes push.
- Suivez les commandes à:
- Authentifiez Docker avec ECR.
- Construisez, étiquetez et poussez votre image.
- Vous devez avoir AWS CLI configuré pour cette étape.


Étape 2: Créez un cluster ECS
aws ecs create-cluster --cluster-name sample-ecs-cluster
Étape 3: Créez une définition de la tâche
- Dans la console ECSaller à Définitions des tâches.
- Faire un clic Créer une nouvelle définition de la tâche.
- Choisir Fargate → Click Prochaine étape.
- Définir les détails de la définition de la tâche:
- Nom: Sample-NEXTJS-TAKE
- Rôle de la tâche: ecstaskexecutionRole (En créer un en cas de manque).
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability"
],
"Resource": "arn:aws:ecr:us-east-1:624448302051:repository/sample-nextjs-app"
}
]
}
- Mémoire de tâche et processeur: Choisissez des valeurs appropriées (par exemple, 512 Mo et 256 CPU).
- Définir le conteneur:
- Faire un clic Ajouter un conteneur.
- Nom de conteneur: Sample-NextJS-Container.
- URL d’image: Collez le Image ECR URI de l’étape 1.
- Mappages de ports: Ensemble 3000 pour les ports de conteneur et d’hôte.
- Faire un clic Ajouter.
- Faire un clic Créer.
Étape 4: Créez un service ECS
- Aller à « ECS » → Click Groupes → Sélectionnez votre cluster (exemples-ECS-Cluster).
- Faire un clic Créer un service.
- Choisissez Fargate → Click Prochaine étape.
- Configurer le service:
- Définition de la tâche: sélectionnez échantillon.
- Grappe: échantillon.
- Nom du service: échantillon.
- Nombre de tâches: 1 (Peut évoluer plus tard).
- Paramètres de réseautage:
- Sélectionner un VPC existant.
- Choisir Sous-réseaux publics.
- Activer IP publique d’attribution automatique.
- Faire un clic Prochaine étape → Créer un service.


Étape 5: accéder à l’application
- Accédez à ECS> Clusters> Exemple-ECS-Cluster.
- Cliquez sur le Onglet Tâches.
- Cliquez sur la tâche en cours d’exécution.
- Trouver le IP publique sous Réseau.
Ouvrez un navigateur et allez à:
http: //
Ton Next.js L’application devrait être en direct! 🚀

Conclusion
Cela marque la fin du blog. Aujourd’hui, nous avons divisé en de nombreux services AWS: S3, IAM, ECR, Fonction Lambda, ECS, Fargate et API Gateway. Nous avons commencé le projet en créant des seaux S3 et finalement déployé notre application dans un cluster ECS.
Tout au long de ce guide, nous avons couvert conteneurisation de l’application suivante.js, la poussant vers ECR, configurer les définitions de tâches ECS et déploier via la console AWS. Cette configuration permet une mise à l’échelle automatisée, des mises à jour faciles et un accès à l’API sécurisé – tous les avantages clés d’un déploiement natif du cloud.
Les configurations de production potentielles peuvent inclure des modifications comme ci-dessous:
- Implémentation d’autorisations IAM plus restrictives, améliorant le contrôle sur l’accès du public aux seaux S3 (en utilisant des URL CloudFront, pré-signes ou un proxy backend au lieu de rendre l’échantillon
- Ajout de la gestion des erreurs et de la pagination (en particulier pour les requêtes DynamoDB)
- Utilisation de configurations VPC / réseau sécurisées pour ECS (comme utiliser un équilibreur de chargement d’application et des sous-réseaux privés au lieu de PIC directs)
- Répondre aux préoccupations de mise à l’échelle en remplaçant l’opération DynamoDB.Scan dans la Lambda à la recherche de métadonnées avec le dynamoDB.Query
- Utilisation de variables d’environnement au lieu d’une URL de passerelle API à code en dur dans le code suivant.js
Source link