Essai gratuit · 14 jours · Sans engagementDémarrer

Projets

Regroupe conteneurs, volumes et réseaux dans une unité isolée.

Dernière mise à jour : 8 septembre 2026

Qu'est-ce qu'un projet ?

Un projet rassemble les conteneurs d'une application (front, back, base de données, sidecars) dans ses propres réseaux Docker, avec son quota dédié. Il appartient à une seule organisation. La page détail d'un projet s'organise en huit onglets : Conteneurs, Topologie, Déploiements, Dépôts, Logs, Secrets, Sauvegardes et Groupes réseau.

La page détail d'un projet s'organise en neuf onglets : Conteneurs, Topologie, Déploiement, Dépôts utilisés, Logs, Secrets, Sauvegardes, Sécurité et Groupes réseau. Chacun est décrit plus bas, à l'exception de Sécurité, qui a sa propre page.

La liste des projets

La page Projets liste tous les projets de l'organisation active. Chaque ligne porte une icône, le nom et le slug, le nombre de conteneurs utilisés (rapporté au quota), la date de création et des actions (ouvrir, renommer, supprimer). Un compteur en haut indique votre usage par rapport au plan.

Chaque ligne affiche aussi une barre de santé sur 7 jours, même langage visuel que le tableau de bord : une cellule colorée par jour de la semaine courante, résumant le pire état de conteneur observé ce jour-là. Survolez une cellule pour voir la date, le statut et le nombre de conteneurs en bonne santé rapporté au total. Cliquez une cellule pour ouvrir l'historique détaillé de ce jour, scopé à ce projet.

La liste des projets de l'organisation, avec le compteur de quota.

Créer un projet

Cliquez sur Créer un projet. Donnez-lui un nom, le slug en est dérivé et figé à la création. Selon votre cible de déploiement, choisissez l'agent (serveur) qui hébergera le projet. Confirmez pour créer le projet vide, prêt à recevoir des conteneurs.

Le nombre de projets et de conteneurs par projet dépend de votre plan. Quand le quota est atteint, le bouton de création propose de passer à un plan supérieur (dialogue d'upgrade) au lieu de créer.

Créer un conteneur

Dans un projet, le bouton dédié ouvre la création d'un conteneur. Vous fournissez un nom, dont le slug est dérivé, puis :

  • Le type. Un conteneur web est joignable en HTTP et reçoit un sous-domaine ; un conteneur worker, pour une file de messages ou une tâche planifiée, n'expose aucun port et n'est pas sondé en HTTP. Choisissez-le à la création, il ne se change pas ensuite.
  • Le dépôt GitHub, la branche à surveiller et le dossier du code dans le dépôt, avec un explorateur pour le retrouver.
  • Le framework. Si votre Dockerfile porte une ligne LABEL framework, Pierrr le déduit tout seul et verrouille le choix ; sinon vous le sélectionnez, à titre d'information si un Dockerfile existe, ou pour choisir le modèle que Pierrr générera s'il n'y en a pas.
  • Un interrupteur « Monorepo : construire depuis la racine du dépôt », quand le Dockerfile vit dans un sous-dossier mais que le build a besoin de voir tout le dépôt.

Onglet Conteneurs

L'onglet Conteneurs présente chaque conteneur du projet sous forme de carte : logo du framework détecté, nom et slug, et état en direct. Vous pouvez :

  • Lire l'état en direct de chaque conteneur, En cours, Arrêté, En création ou Échec, avec un point coloré.
  • Démarrer un conteneur arrêté, individuellement ou tous d'un coup via Démarrer tout.
  • Arrêter un ou tous les conteneurs pour mettre le trafic en pause.
  • Redémarrer un conteneur, utile après une modification de variables d'environnement ou la rotation d'un secret.
  • Déployer un conteneur avec le bouton éclair de sa carte : un clic construit et déploie la dernière version de la branche suivie, et le chevron voisin permet de choisir un autre commit.
  • Créer un conteneur via le bouton dédié (bloqué par un dialogue d'upgrade si le quota du projet est atteint).
  • Ajuster le nombre d'instances d'un conteneur avec le stepper +/- à côté de « Nb d'instances », directement sur la carte.
Chaque conteneur affiche son logo de framework, son état en direct et ses actions.

Actions au niveau du projet

L'en-tête du projet expose des actions globales (démarrer / arrêter / redémarrer tous les conteneurs) ainsi que le mode de déploiement (l'agent ciblé et la façon dont les déploiements sont déclenchés).

Faire évoluer le nombre d'instances

Chaque carte de conteneur affiche un stepper « Nb d'instances » permettant d'augmenter ou de réduire le nombre d'instances du conteneur sans repasser par un déploiement. Tant que le nombre d'instances actives n'a pas rejoint la cible, un indicateur du type « 2/3 actives » reste visible sur la carte.

Le nombre maximal d'instances par conteneur dépend de votre plan : 1 en Free, 2 en Starter, 5 en Pro et 15 en Business, avec un plafond absolu de 50 instances quel que soit le plan. Au-delà du quota du plan, le stepper propose un dialogue d'upgrade au lieu d'augmenter le nombre d'instances.

Limites processeur et mémoire

Chaque conteneur expose ses limites de ressources. Deux valeurs, à ne pas confondre : le plafond, que le conteneur ne peut pas dépasser, et la part garantie, qui lui reste acquise même quand un voisin gourmand tourne sur la même machine. C'est la seconde qui protège votre service, la première qui protège les autres.

Le plafond que vous pouvez demander dépend du plan : 512 Mo de mémoire et un demi-cœur en Free, 1 Go et un cœur en Starter, 2 Go et deux cœurs en Pro, 4 Go et quatre cœurs en Business.

Le endpoint /health, obligatoire

Pierrr impose son propre healthcheck à chaque conteneur : une requête GET sur http://127.0.0.1:<PORT>/health, indépendamment de tout HEALTHCHECK déclaré dans votre Dockerfile (qui est ignoré : le healthcheck compose de Pierrr prend toujours le dessus). Votre app DOIT donc répondre 200 sur /health, sans le préfixe global de votre framework s'il en a un (ex. NestJS avec setGlobalPrefix('api') : excluez explicitement la route health du préfixe). Sans ça, le conteneur ne passera jamais healthy et chaque déploiement échouera après 90 secondes, même si l'app démarre et fonctionne normalement.

Répondre 200 ne suffit pas à rendre le signal utile. Faites répondre 200 seulement quand votre service peut réellement servir : base joignable ET schéma en place, dépendances indispensables prêtes. Une route qui renvoie 200 dès que le processus tourne indique un processus vivant, pas un service qui fonctionne, et elle ne pourra jamais signaler une panne. Un cas vécu : un `/health` qui vérifiait une extension Postgres installée par Pierrr avant tout code client répondait 200 alors que la base n'avait aucune table.

typescript
// NestJS - exclure /health du préfixe global
app.setGlobalPrefix('api/v1', { exclude: ['health'] });
  • Aucune configuration côté Pierrr : la route /health doit simplement exister et répondre 200 sur le port de votre app. Un HEALTHCHECK dans votre Dockerfile n'est pas nécessaire (il est ignoré), inutile de le maintenir en double.
  • Pendant un déploiement, Pierrr attend que la nouvelle instance passe healthy sur /health (jusqu'à 90 secondes) avant de basculer le trafic ; si elle n'y arrive pas, l'ancienne instance reste en place et le déploiement est annulé.
  • L'état healthy/unhealthy renvoyé par Docker alimente le compteur de santé agrégé du serveur et les notifications de conteneur en mauvaise santé, en plus du simple état d'exécution.

/health doit rester accessible sans authentification et sans préfixe, sur le même port que le reste de votre app.

Votre Dockerfile et le préflight

Quand vous déployez depuis un dépôt GitHub, Pierrr utilise votre propre Dockerfile s'il en existe un, sinon il génère un modèle minimal selon le framework. Avant chaque build, Pierrr vérifie votre Dockerfile et quelques fichiers du projet pour attraper les erreurs les plus courantes. Une erreur bloquante arrête le build avec un message clair ; les avertissements n'arrêtent pas le build et apparaissent dans les logs de déploiement, préfixés par préflight.

Les variables du coffre sont injectées à l'EXÉCUTION du conteneur, jamais comme arguments de build : `docker build` ne les voit pas. Cela compte pour les frameworks qui figent leurs variables publiques à la compilation (`NEXT_PUBLIC_*` avec Next.js, `VITE_*` avec Vite) : la valeur du coffre n'atteindra pas votre bundle, qui gardera la valeur de repli codée dans votre source. Rien n'échoue au déploiement, et le défaut ne se voit qu'en regardant les appels réseau du navigateur. Lisez ces valeurs côté serveur au démarrage et passez-les à vos pages, plutôt que de les figer au build.

  • LABEL avant le premier FROM (bloquant) : Docker refuse de builder un Dockerfile dont une ligne LABEL précède le premier FROM. Placez toujours votre ligne LABEL framework après un FROM. Ce cas est aussi signalé en rouge dès la sélection du dépôt, avant même le build.
  • Prisma sans openssl ni schéma (avertissement) : le postinstall prisma generate a besoin du schéma et d'openssl au moment du build. Sur une base alpine, ajoutez RUN apk add --no-cache openssl et copiez COPY prisma ./prisma avant d'installer les dépendances.
  • reactCompiler sans @swc/helpers (avertissement) : si reactCompiler est activé dans next.config, ajoutez @swc/helpers à vos dependencies, sinon l'build standalone de Next ne l'embarque pas et le conteneur plante au démarrage.

Ces vérifications vous évitent un build qui échoue sans message ou un conteneur qui plante au démarrage. Les avertissements restent des conseils : vous gardez la main sur votre Dockerfile.

Valeurs dont votre framework a besoin au build

Certains frameworks résolvent des valeurs pendant la compilation et non à l'exécution. Le cas le plus courant est le `metadataBase` de Next.js, dont dépendent les URL canoniques et les balises Open Graph : si vos pages sont prérendues statiquement, la valeur est figée au moment du `docker build`, c'est-à-dire avant que Pierrr n'injecte quoi que ce soit. Les pages sortent alors avec `http://localhost:3000` en canonique, ce qu'un robot d'indexation ou un aperçu de partage utilisera vraiment.

Pierrr ne passe pas les variables du coffre en arguments de build, et ne le fera pas : un `ARG` reste lisible dans l'historique de l'image (`docker history`), donc le mécanisme pousse naturellement à y mettre des valeurs qui n'ont rien à y faire. Un `ARG` déclaré mais non renseigné produit par ailleurs une chaîne vide, pas une variable absente, ce qui transforme un oubli en `new URL('')` au lieu d'une erreur explicite.

La solution tient en deux règles. D'abord, lisez la variable paresseusement dans une fonction, jamais dans un `const` au niveau du module : un `const` est évalué une seule fois et peut être figé dans le bundle, alors qu'un appel de fonction relit `process.env` dans le conteneur en marche.

typescript
// env.ts - lu à chaque appel, côté serveur, dans le conteneur en marche.
export function getPublicOrigin(): URL {
  return new URL(process.env.PUBLIC_WEB_ORIGIN ?? 'http://localhost:3000');
}

// app/layout.tsx
export async function generateMetadata(): Promise<Metadata> {
  return { metadataBase: getPublicOrigin() };
}

Ensuite, assurez-vous que la métadonnée est bien évaluée à la requête. Une page prérendue statiquement exécute `generateMetadata` au build, où la variable n'existe pas encore. La régénération incrémentale ne suffit pas tout à fait : la première visite après un déploiement reçoit encore la sortie du build. Pour que ce soit juste dès la première requête, dérivez l'origine de l'en-tête `Host` plutôt que d'une variable, ce qui rend la page dynamique et supprime le besoin de configurer quoi que ce soit :

typescript
import { headers } from 'next/headers';

export async function generateMetadata(): Promise<Metadata> {
  const h = await headers();
  const host = h.get('x-forwarded-host') ?? h.get('host');
  return { metadataBase: new URL(`https://${host}`) };
}

Pour une valeur dont un composant client a besoin, le principe est le même : lisez-la dans un composant serveur et passez-la en propriété. Le composant client la reçoit à l'exécution, sans jamais dépendre d'une variable figée à la compilation.

Onglet Topologie

La Topologie affiche conteneurs, base de données managée et, une fois lié, votre add-on Redis sous forme de graphe hiérarchique organisé par niveau : proxy, frontend, backend, cache, base de données. Les réseaux Docker ne sont pas des nœuds à part : ils apparaissent comme des arêtes entre les conteneurs qui les partagent, cliquez une arête pour voir le détail des liaisons réseau sous-jacentes (nom, alias). Sélectionnez un nœud pour voir ses détails (points de montage, réseaux attachés, alias, isolation) et agir dessus : démarrer, arrêter ou redémarrer un conteneur, monter ou démonter un volume, délier une instance Redis (le Postgres managé se délie désormais depuis l'onglet Secrets, voir plus bas). Le nœud base de données est étiqueté partagée (plan Free) ou dédiée (plan payant), une distinction pilotée par le plan aujourd'hui, pas encore une instance physiquement séparée. Quand le projet n'a encore aucun conteneur, un état vide invite à en créer.

Conteneurs, volumes et réseaux du projet sous forme de graphe interactif.

Add-ons Volume et Redis

Un volume et une instance Redis s'achètent en add-ons depuis Facturation, puis Add-ons. Un volume acheté démarre non monté : ouvrez son nœud dans la Topologie pour l'attacher à un conteneur et un chemin de montage. Une instance Redis achetée n'a pas de nœud tant qu'elle n'est pas liée : liez-la à un projet depuis le panneau Redis au-dessus de la Topologie, puis déliez-la depuis son nœud dans la Topologie une fois connectée.

Connecter une ressource à un conteneur

Une ressource managée n'atteint un conteneur que si vous l'y connectez explicitement : acheter un stockage objet ou lier une base ne suffit pas, et rien n'est diffusé à l'ensemble du projet par défaut. La commande se trouve sur le nœud de la RESSOURCE, pas sur celui du conteneur : ouvrez le nœud base de données, cache ou stockage dans la Topologie, et cochez les conteneurs qui doivent le recevoir. Les variables correspondantes (DATABASE_*, CACHE_*, STORAGE_*) sont injectées au déploiement suivant, et un conteneur non connecté démarrera sans elles. Depuis un conteneur, la ligne Ressources connectées indique ce à quoi il est rattaché, ou signale qu'il ne l'est à rien.

Onglet Déploiements

L'historique liste chaque déploiement du projet, du plus récent au plus ancien (paginé). Pour chaque ligne :

  • Les quatre étapes du pipeline, build (construction de l'image), push (envoi vers le registre), load (récupération de l'image) et start (création + démarrage du conteneur), chacune avec son icône d'état.
  • Un badge de statut mono (Réussi, Échec, En cours, En attente, Annulé).
  • Le conteneur (logo + nom + slug), la branche et le commit (cliquables vers GitHub), l'heure de démarrage et la durée.
  • Le nombre de tentatives quand un déploiement a été relancé.
L'historique des déploiements : conteneur, statut, 4 étapes, commit, branche, durée.

Déployer un commit précis

Le bouton de déploiement présent sur la carte de chaque conteneur est scindé en deux. L'action principale n'a pas changé : un clic construit et déploie la dernière version de la branche suivie, sans étape ni requête supplémentaire.

Le chevron qui lui est accolé ouvre une fenêtre listant les commits récents de cette branche. Une barre de recherche filtre la liste par message, par auteur ou par empreinte, sous sa forme courte comme complète. Chaque ligne affiche le message du commit, son empreinte courte et son auteur.

Sélectionner une ligne lance immédiatement le déploiement de cette version, à la place de la dernière. C'est le moyen de revenir à une version connue comme bonne sans toucher à votre dépôt, ou de livrer un correctif déjà validé alors que la branche a continué d'avancer.

Le commit choisi est enregistré sur le déploiement : c'est son empreinte que vous retrouvez dans l'historique, et c'est bien ce code qui est mis en ligne. Si le conteneur tourne déjà et que la dernière image construite correspond au commit choisi, elle est réutilisée plutôt que reconstruite.

La liste est chargée à l'ouverture de la fenêtre, jamais avant, et couvre les trente derniers commits de la branche suivie. Si elle ne peut pas être récupérée, par exemple quand aucun dépôt n'est lié au conteneur, la fenêtre l'indique et le déploiement de la dernière version reste disponible.

Où tourne le projet

L'onglet Déploiement porte le mode de déploiement du projet : sur l'infrastructure de Pierrr, le réglage par défaut, ou en self-hosted sur l'un de vos serveurs, que vous choisissez alors dans la liste des agents en ligne.

Mode accéléré

Par défaut, enchaîner plusieurs pushes fait patienter chaque déploiement derrière le précédent : la version que vous vouliez réellement mettre en ligne part en dernier, après des constructions devenues inutiles. L'interrupteur Mode accéléré change cela : un nouveau déploiement annule celui qui tourne encore pour ce conteneur et prend sa place.

L'effet reste borné au conteneur concerné : relancer votre conteneur api n'interrompt jamais la construction en cours de votre conteneur web. Le réglage est désactivé par défaut, et un déploiement écarté de cette façon porte son propre motif dans l'historique, à ne pas confondre avec une annulation manuelle.

Annuler, relancer, exporter

  • Annuler, tant que le déploiement est en attente ou en cours.
  • Relancer, sur un déploiement en échec. La nouvelle tentative repart de l'étape qui a échoué, les étapes déjà réussies sont réutilisées telles quelles.
  • Télécharger le journal complet d'une tentative, pour l'analyser hors de la console ou le joindre à une demande d'aide.

Les journaux de build sont conservés un temps qui dépend de votre plan, rappelé sur la page de détail du déploiement.

Détail d'un déploiement

Cliquez une ligne pour ouvrir le détail : la chronologie des étapes, chaque tentative avec son statut et sa durée, le motif d'échec le cas échéant, et les logs complets ligne par ligne (taggés par étape). C'est là que vous diagnostiquez un build cassé ou un conteneur qui ne démarre pas.

Le détail d'un déploiement : étapes, tentatives et logs complets.

Onglet Dépôts

L'onglet Dépôts liste les dépôts GitHub liés aux conteneurs du projet, avec la branche surveillée et le chemin du Dockerfile. C'est le lien entre votre code et chaque conteneur déployé depuis un push.

Chaque dépôt lié affiche un interrupteur Déploiement auto, activé par défaut. Tant qu'il reste activé, un push sur la branche surveillée déclenche un build et un déploiement pour ce conteneur. Le désactiver n'affecte que ce conteneur : les autres conteneurs du même projet ou du même dépôt continuent de se déployer normalement, et le webhook GitHub reste en place, il ne fait simplement plus rien tant que l'interrupteur est éteint.

Cliquez sur Modifier à côté de la branche surveillée pour pointer le conteneur vers une autre, par exemple pour promouvoir une feature branch en production, sans supprimer et recréer le conteneur. Cela change uniquement quels futurs push déclencheront un déploiement : le conteneur actuellement en cours d'exécution n'est pas redéployé pour autant. Déclenchez ensuite un déploiement avec un push sur la nouvelle branche, ou via le bouton Build du conteneur.

Les dépôts GitHub liés aux conteneurs du projet.

Onglet Logs

L'onglet Logs affiche les journaux des conteneurs. Choisissez le conteneur dans le sélecteur ; quand le projet n'a aucun conteneur, un état vide le signale.

Par défaut, les logs se rafraîchissent périodiquement. Activez Live pour les diffuser en temps réel à la place ; les deux modes ne fonctionnent jamais en même temps.

Les logs en direct, avec sélecteur de conteneur.

Onglet Secrets

L'onglet Secrets gère un coffre chiffré par projet (variables d'environnement, clés d'API…). Chaque secret peut être injecté dans les conteneurs selon trois modes :

  • Bound, un conteneur ne reçoit que les secrets que vous lui avez explicitement liés.
  • Detected, un conteneur reçoit les secrets du coffre dont la clé est déclarée dans son `.env.example`.
  • All, un conteneur reçoit TOUS les secrets du coffre (portée org + projet), indépendamment du binding ou du `.env.example`.

Le choix du mode est réservé aux plans payants. Sur le plan Free il est figé : tous les conteneurs reçoivent l'intégralité du coffre.

Le coffre de secrets chiffrés du projet et leur injection par conteneur.

Section « Géré par Pierrr »

Une section en lecture seule liste les variables que Pierrr injecte automatiquement dans vos conteneurs, sans configuration manuelle. Elles gagnent toujours sur le coffre et ne peuvent être ni éditées ni supprimées depuis le coffre tant que la ressource correspondante reste liée. Si vous tentez de créer manuellement un secret portant l'un de ces noms, Pierrr refuse et indique explicitement comment débloquer la variable : délier la ressource concernée.

  • Postgres managé (lié par défaut à chaque projet) : `DATABASE_URL`, `DATABASE_HOST`, `DATABASE_PORT`, `DATABASE_NAME`, `DATABASE_USER`, `DATABASE_PASSWORD`. Ces noms sont volontairement génériques plutôt que `PG*` : libpq ne les reconnaît pas automatiquement, donc un conteneur qui héberge son propre Postgres ne voit jamais son outillage détourné vers l'instance managée par accident. Un toggle « Utiliser le Postgres managé Pierrr », juste au-dessus de cette section dans l'onglet Secrets, permet de délier le projet sans détruire la base ni les identifiants. Une fois délié, ces noms se libèrent et vous pouvez les définir vous-même dans le coffre, par exemple pour pointer `DATABASE_URL` vers une base externe. Délier est réservé aux plans payants : sur le plan Free, le toggle ouvre une fenêtre d'upgrade.
  • Add-on Redis (une fois lié à ce projet depuis Facturation puis Add-ons) : `CACHE_URL`, `CACHE_HOST`, `CACHE_PORT`, `CACHE_PASSWORD`. Même logique que ci-dessus : `CACHE_*` plutôt que `REDIS_*`, pour que redis-cli ne s'y branche pas tout seul. Déliez-le depuis son nœud dans l'onglet Topologie pour libérer ces noms ; aucune restriction de plan ne s'applique.
  • Add-on Stockage objet, compatible S3 (une fois lié au projet, puis chaque conteneur connecté individuellement) : `STORAGE_ENDPOINT`, `STORAGE_PUBLIC_URL`, `STORAGE_REGION`, `STORAGE_BUCKET`, `STORAGE_ACCESS_KEY`, `STORAGE_SECRET_KEY`. `STORAGE_ENDPOINT` est l'adresse interne au réseau du projet ; `STORAGE_PUBLIC_URL` est l'origine que le navigateur atteint, et c'est elle que vos URLs présignées doivent porter, sinon leur signature ne sera pas validée. Le bucket créé d'office porte le slug du projet : c'est un défaut pratique, pas une limite, votre application peut en créer d'autres.
  • Extensions Postgres : `pgvector`, `pg_trgm`, `pgcrypto`, `uuid-ossp`, `unaccent`, `citext` et `btree_gin` s'activent projet par projet depuis l'onglet Topologie. Pierrr exécute la création avec les droits nécessaires ; le rôle de votre base reste volontairement restreint, donc une migration qui fait `CREATE EXTENSION IF NOT EXISTS` fonctionne une fois l'extension activée, sans que vous ayez à la modifier.

Prisma

Prisma a besoin d'une seconde variable en plus de `DATABASE_URL` : `DIRECT_URL`, utilisée uniquement pour les migrations. Elle sert normalement à contourner un connection pooler (PgBouncer, Supabase…) placé devant la base, qui ne supporte pas certaines commandes DDL exécutées par `prisma migrate`. La base Postgres managée par Pierrr est déjà une connexion directe, sans pooler devant elle : il suffit donc de faire pointer `DIRECT_URL` vers la même valeur que `DATABASE_URL`.

Dans votre `schema.prisma`, déclarez les deux variables sur le datasource :

prisma
datasource db {
  provider  = "postgresql"
  url       = env("DATABASE_URL")
  directUrl = env("DIRECT_URL")
}

Puis, dans le point d'entrée de votre conteneur (CMD du Dockerfile ou script de démarrage du `package.json`), exportez `DIRECT_URL` à partir de `DATABASE_URL` avant de lancer les migrations :

bash
export DIRECT_URL="$DATABASE_URL"
npx prisma migrate deploy

Aucune action n'est nécessaire côté Pierrr : `DIRECT_URL` n'est pas une variable gérée, elle vit entièrement dans le code de votre application.

Édition groupée (coller un .env)

Plutôt que d'ajouter vos variables une par une, l'édition groupée vous permet de coller tout un bloc au format .env d'un coup. Pierrr compare votre collage aux variables existantes du projet et applique uniquement les différences.

Le bouton Édition groupée, en haut à droite de l'onglet Secrets, à côté de Ajouter une variable.

Pas à pas :

  1. Ouvrez votre projet, puis l'onglet Secrets. En haut à droite de la carte, cliquez sur le bouton Édition groupée (à côté de Ajouter une variable).
  2. Dans la fenêtre qui s'ouvre, collez votre contenu .env dans la zone de texte : une variable par ligne, au format CLE=valeur. Les valeurs peuvent être entre guillemets.
  3. Pour supprimer une variable existante, ajoutez une ligne préfixée par un point d'exclamation, par exemple !OLD_FLAG.
  4. Lisez l'aperçu sous la zone de texte : il indique combien de variables seront ajoutées, remplacées et supprimées, et surligne en rouge les lignes invalides (le bouton Appliquer reste désactivé tant qu'une ligne est invalide).
  5. Cliquez sur Appliquer. Les variables sont enregistrées (les nouvelles sont masquées par défaut) et la liste se met à jour immédiatement.
On colle le bloc .env ; l'aperçu compte en direct les ajouts, remplacements et suppressions (et les suppressions ignorées) avant d'appliquer.

Exemple de contenu à coller :

DATABASE_URL=postgres://user:pass@db:5432/app
API_KEY=sk_live_123
# remplace une clé existante, ajoute une nouvelle
NODE_ENV=production
# supprime une variable qui existait
!OLD_FLAG

Règles de fusion appliquées à votre collage :

  • Une clé déjà présente est remplacée par la valeur collée.
  • Une clé absente est ajoutée (masquée par défaut).
  • Une ligne préfixée par ! (ex. !ANCIENNE_CLE) supprime la variable si elle existe.

L'aperçu en direct récapitule, avant d'appliquer, le nombre d'ajouts, de remplacements et de suppressions, et signale les lignes invalides à corriger.

Onglet Sauvegardes

Ouvrez Archiver pour créer ou restaurer une sauvegarde. Deux types sont disponibles :

  • Sauvegarde de données, un run unique pour tout le projet : chaque volume de chaque conteneur, plus un dump de la base managée liée. Donnez-lui un nom, sinon un nom est généré automatiquement ; l'historique liste chaque run par ce nom. La restauration écrase l'état courant du conteneur ; elle est destructive et demande une confirmation.
  • Export de projet Pierrr, exporte uniquement la structure du projet (conteneurs, liaisons de dépôts, groupes réseau et métadonnées des volumes), sans les données. Valider un export vis-à-vis d'une autre organisation vérifie qu'elle a une installation GitHub App correspondante pour chaque dépôt ; recréer le projet là-bas est une prochaine étape documentée, pas encore livrée.

L'export de projet se crée, se télécharge et se valide vis-à-vis d'une autre organisation. Sa réimportation n'est pas encore disponible : le bouton correspondant est visible mais inactif.

Les sauvegardes de données ne sont pas incluses sur le plan Free : l'onglet propose alors une montée en gamme. Sur les plans payants, la durée de conservation des archives dépend du plan, et les plus anciennes sont purgées automatiquement.

Planifier les sauvegardes

Un accordéon Planification règle une sauvegarde récurrente du projet : quotidienne ou hebdomadaire, avec le jour de la semaine et l'heure de passage en UTC, et une option pour recevoir un email après chaque passage. Les sauvegardes planifiées apparaissent dans le même historique que celles lancées à la main.

Restaurer une sauvegarde réécrit les volumes et la base du projet avec le contenu de l'archive, et redémarre le projet. L'opération est destructrice pour les données actuelles et demande donc une confirmation.

Une sauvegarde réussie se télécharge, pour garder une copie hors de Pierrr.

Importer mes données (restauration d'un dump SQL)

En haut de l'onglet Sauvegardes, dans son propre accordéon « Importer mes données », un bouton restaure un dump SQL existant directement dans la base managée du projet, sans passer par SSH ni `psql`.

  • Format : fichier `.sql` en texte brut uniquement, 15 Mo maximum. Le format binaire `pg_dump --format=custom` n'est pas accepté.
  • Un seul import peut tourner à la fois par projet ; relancez une fois le précédent terminé.
  • Tout ou rien : le dump s'exécute en une seule transaction. En cas de conflit avec l'existant (par exemple une table déjà présente), l'import échoue entièrement et rien n'est appliqué, vous pouvez réessayer sans risque.
  • Une liste d'historique affiche en direct chaque import (nom du fichier, taille, statut : en attente, en cours, réussi, échoué) avec le message d'erreur visible en cas d'échec.
  • Le contenu du fichier envoyé est chiffré au repos et n'est jamais conservé une fois la restauration terminée, qu'elle réussisse ou échoue.
L'accordéon Importer mes données, en haut de l'onglet Sauvegardes, avec l'historique des imports.
Une ligne par conteneur, pour chaque sauvegarde de données du projet.
La sauvegarde de données couvre chaque volume plus un dump de BDD, sans sélection à faire. L'export de projet Pierrr n'exporte que la structure.

Onglet Groupes réseau

Regroupez les conteneurs du projet dans des réseaux Docker isolés. Chaque projet démarre avec un groupe protégé internal qui ne peut être ni renommé ni supprimé. Créez des groupes supplémentaires avec Ajouter, puis utilisez Gérer les membres pour choisir quels conteneurs rejoignent chaque groupe. Disponible sur les plans dont la politique réseau est choice ; en Free, les projets restent verrouillés sur le seul groupe internal.

Le groupe par défaut internal plus les groupes personnalisés, avec leur nombre de conteneurs attachés.

Le menu d'actions d'un projet, le « ... » à côté de Démarrer, Arrêter et Redémarrer, propose Resynchroniser les réseaux : il rattache immédiatement chaque conteneur à sa configuration réseau, sans attendre le prochain déploiement. Utile pour dépanner un conteneur injoignable sur le réseau attendu. Disponible sur toutes les offres.

Comme pour les secrets, la création de groupes supplémentaires est réservée aux plans payants : sur le plan Free, le projet reste sur son unique groupe internal.

Ports TCP publiés

Certains protocoles ne se routent pas en HTTP. Une carte Ports TCP publiés, au bas de l'onglet Groupes réseau, expose un port de conteneur directement sur l'adresse publique du serveur. Choisissez le conteneur, le port interne, et éventuellement un port public différent.

Une plage contiguë est possible, pour un service qui en a besoin, comme le mode passif d'un serveur de fichiers.

Deux réserves. Chaque port ouvert est une surface d'exposition de plus : ne publiez que ce dont le service a réellement besoin. Et redéployer un conteneur qui publie un port coupe brièvement le service, un port ne pouvant pas être détenu par l'ancienne et la nouvelle instance en même temps.

Le nombre de ports publiables par conteneur dépend du plan, à partir du plan Starter. Le plan Free n'en publie aucun.

Panneau de base de données

Le menu d'actions d'un projet ouvre, quand l'instance en met un à disposition, un panneau d'administration de la base managée dans un nouvel onglet : de quoi inspecter vos tables et lancer une requête sans installer de client sur votre poste. Vous y arrivez déjà authentifié, et vous n'y voyez que la base de ce projet.