← Tous les guidesDéveloppement web

Créer un pipeline d’envoi et d’optimisation d’images avec DigitalOcean

Envoyez des originaux privés vers DigitalOcean Spaces, générez des variantes WebP réactives avec Functions et déployez le flux sécurisé sur App Platform.

Ce que vous allez créer

Ce guide crée un pipeline volontairement simple mais proche de la production. Le navigateur ne reçoit jamais un secret Spaces. Il demande une URL d’envoi temporaire à votre application App Platform, envoie l’original vers une clé privée, puis demande à l’application de démarrer une Function sécurisée. La Function crée des variantes WebP de 400, 800 et 1600 pixels et renvoie leurs URL CDN.

Utilisez-le pour des avatars, annonces, portfolios ou autres charges synchrones modestes. Ce n’est pas un système de comptes, d’antivirus ou de file durable. Le projet de départ accepte JPEG, PNG et WebP jusqu’à 10 Mo ; ajoutez authentification et quotas avant d’accepter du trafic non fiable.

  • App Platform héberge l’interface Next.js et garde les secrets côté serveur.
  • Spaces stocke les originaux privés sous uploads/ et les dérivés publics sous images/.
  • Une Function Node.js avec Sharp traite des clés objet, pas des corps de requête image.
  • Le CDN Spaces sert uniquement les variantes finales.

Comprendre l’architecture et la frontière de sécurité

La frontière importante est l’envoi direct vers le stockage. Faire passer une image complète par une route API consomme inutilement la bande passante de l’application. POSTez plutôt les métadonnées à /api/uploads, recevez une URL PUT présignée de cinq minutes, puis envoyez directement vers Spaces. La réponse contient un UUID imprévisible, jamais le nom de fichier original.

Après le PUT, le navigateur POSTe cet UUID vers /api/images/:id/process sur le même domaine. Cette route appelle la Function avec son secret web. Ni l’URL de la Function ni la valeur X-Require-Whisk-Auth ne parviennent au navigateur.

Créer un Space pour les originaux et les variantes

Créez un bucket Spaces standard dans la même région que l’application et activez son CDN. Gardez la liste de fichiers désactivée. L’application écrit les originaux avec une ACL privée et écrit les fichiers générés avec une ACL public-read. Vous obtenez ainsi un stockage unique sans exposer accidentellement le chemin d’envoi.

Configurez CORS pour n’autoriser PUT que depuis l’origine App Platform déployée et pour l’en-tête Content-Type. N’utilisez pas une origine générique en production.

  • Original privé : uploads/<uuid>/original
  • Variante publique : images/<uuid>/<largeur>.webp
  • Base CDN : https://YOUR_BUCKET.YOUR_REGION.cdn.digitaloceanspaces.com

Configurer les secrets de l’application et de la Function

Clonez le projet compagnon dans examples/digitalocean-image-upload-pipeline, copiez .env.example vers .env.local et renseignez le Space, la région, les clés d’accès, l’URL CDN, l’URL de Function et un long secret. Les clés existent seulement comme variables chiffrées App Platform et dans la configuration de Functions ; ne leur donnez jamais le préfixe NEXT_PUBLIC_.

Le fichier project.yml rend l’action accessible sur le web tout en exigeant le même secret via X-Require-Whisk-Auth. Utilisez une compilation distante pour Sharp : les dépendances natives doivent être compilées pour le runtime Functions.

Installer et lancer le projet localement
Set-Location examples\digitalocean-image-upload-pipeline
npm install
Copy-Item .env.example .env.local
npm run dev
Premier test

Vérifier ce flux avant de l’étendre

Entrée
Choisissez un JPEG, PNG ou WebP inférieur à 10 Mo que vous pouvez utiliser sans risque pour un test public.
Mise en place
Demandez une URL d’envoi présignée, envoyez l’original vers Spaces, puis appelez la route de traitement sécurisée avec l’identifiant retourné.
Résultat attendu
L’original existe uniquement sous le préfixe privé uploads/ et la réponse liste des URL WebP 400, 800 et 1600 pixels sous images/.
Arrêter si
Arrêtez si une URL d’original est publique, si le navigateur voit un secret Spaces ou Function, ou si un envoi non-image/trop volumineux est accepté.
Étape suivante
Ouvrez une variante CDN en fenêtre privée, puis ajoutez authentification et quotas avant d’accepter de vrais envois utilisateurs.

Déployer les deux composants dans une application App Platform

Envoyez le projet vers GitHub, puis créez une application App Platform depuis le dépôt. Le fichier .do/app.yaml déclare le service Next.js et le composant Functions. Ajoutez les valeurs de .env.example comme variables chiffrées avant le déploiement. Ne placez aucun secret dans Git ni dans la spécification.

Déployez la Function avec une compilation distante. Le service a besoin de FUNCTION_URL et FUNCTION_AUTH_TOKEN pour l’appeler ; la Function a besoin des variables Spaces. Utilisez l’URL affichée dans les réglages App Platform, mettez à jour FUNCTION_URL, puis redéployez le service.

Compiler Sharp à distance
Set-Location functions
doctl serverless deploy . --remote-build

Envoyer une image et vérifier le résultat

Ouvrez l’application déployée, choisissez un JPEG, PNG ou WebP inférieur à 10 Mo et envoyez-le. La page indique d’abord que l’original est arrivé dans Spaces, puis affiche les URL des variantes. Vérifiez que uploads/<uuid>/original reste privé et que seules les trois clés sous images/<uuid>/ sont publiques.

Ouvrez une URL CDN dans une fenêtre privée. Elle doit fonctionner sans chaîne de requête signée. Si ce n’est pas le cas, vérifiez l’ACL de l’objet, puis l’endpoint CDN. Ne rendez jamais uploads/ public juste pour réussir ce test.

Connaître les limites avant de passer à l’échelle

La Function reçoit un petit objet JSON avec un identifiant, jamais les octets d’image. Le traitement reste toutefois synchrone. DigitalOcean Functions impose des limites de mémoire, délai, taille de fonction et requête/réponse. Ajustez mémoire et délai à vos images testées, puis refusez les entrées hors de cette enveloppe.

Pour les transformations longues, un gros volume, la vidéo ou les reprises, utilisez une file et un worker. Ajoutez vérification du contenu, limitation de débit, autorisation, suppression planifiée et antivirus avant de traiter ce projet comme une plateforme de contenu utilisateur.