Backstage
Plateforme open-source de portail développeur interne par Spotify pour gérer le catalogue logiciel et l’expérience développeur.
Installation
Section intitulée « Installation »Création d’une nouvelle application
Section intitulée « Création d’une nouvelle application »| Commande | Description |
|---|---|
npx @backstage/create-app@latest | Créer une nouvelle application Backstage |
npx @backstage/create-app@latest --skip-install | Créer l’application sans installer les dépendances |
cd my-backstage-app && yarn install | Installer les dépendances |
yarn dev | Démarrer le frontend et le backend en mode développement |
yarn start | Démarrer le frontend uniquement |
yarn start-backend | Démarrer le backend uniquement |
yarn build:backend | Compiler le backend pour la production |
yarn build | Compiler tous les paquets |
node_modules/.bin/backstage-cli --version | Afficher la version du CLI Backstage |
Déploiement Docker
Section intitulée « Déploiement Docker »| Commande | Description |
|---|---|
yarn build:backend --config ../../app-config.yaml | Compiler le backend avec la config |
docker build -t backstage -f packages/backend/Dockerfile . | Construire l’image Docker |
docker run -p 7007:7007 backstage | Exécuter le conteneur Backstage |
Commandes CLI
Section intitulée « Commandes CLI »Gestion des paquets
Section intitulée « Gestion des paquets »| Commande | Description |
|---|---|
yarn backstage-cli package start | Démarrer un paquet en mode dev |
yarn backstage-cli package build | Compiler un paquet |
yarn backstage-cli package lint | Analyser le code source du paquet |
yarn backstage-cli package test | Exécuter les tests du paquet |
yarn backstage-cli repo build --all | Compiler tous les paquets du monorepo |
yarn backstage-cli repo lint --all | Analyser tous les paquets |
yarn backstage-cli versions:bump | Mettre à jour les dépendances Backstage vers la dernière version |
yarn backstage-cli versions:bump --release next | Mettre à jour vers la pré-version suivante |
yarn backstage-cli migrate package-roles | Migrer les paquets pour utiliser les rôles |
Création de plugins
Section intitulée « Création de plugins »| Commande | Description |
|---|---|
yarn backstage-cli create-plugin | Créer un nouveau plugin frontend |
yarn backstage-cli create-plugin --backend | Créer un nouveau plugin backend |
yarn backstage-cli create-plugin --id my-plugin | Créer un plugin avec un ID spécifique |
yarn new | Créer interactivement un composant à partir d’un template |
Catalogue logiciel
Section intitulée « Catalogue logiciel »Types d’entités
Section intitulée « Types d’entités »| Commande | Description |
|---|---|
Ajouter catalog-info.yaml à la racine du dépôt | Enregistrer un composant dans le catalogue |
kind: Component dans catalog-info.yaml | Définir un composant logiciel |
kind: API dans catalog-info.yaml | Définir une entité API |
kind: System dans catalog-info.yaml | Définir un regroupement système |
kind: Domain dans catalog-info.yaml | Définir un domaine métier |
kind: Resource dans catalog-info.yaml | Définir une ressource d’infrastructure |
kind: Group dans catalog-info.yaml | Définir une équipe/un groupe |
kind: User dans catalog-info.yaml | Définir un utilisateur |
kind: Location dans catalog-info.yaml | Référencer d’autres fichiers de catalogue |
Propriétés des entités
Section intitulée « Propriétés des entités »| Commande | Description |
|---|---|
Définir spec.owner: team-name | Définir la propriété de l’entité |
Définir spec.lifecycle: production | Définir l’étape du cycle de vie de l’entité |
Définir spec.type: service | Définir le type de composant (service, website, library) |
Définir spec.dependsOn: ['component:other'] | Définir les dépendances |
Définir spec.providesApis: ['api-name'] | Déclarer les APIs fournies |
Définir spec.consumesApis: ['api-name'] | Déclarer les APIs consommées |
Définir spec.system: system-name | Assigner à un système |
Définir metadata.annotations pour les intégrations | Connecter au CI/CD, monitoring, etc. |
Exemple de catalog-info.yaml
Section intitulée « Exemple de catalog-info.yaml »apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: payment-service
description: Handles payment processing and billing
annotations:
github.com/project-slug: org/payment-service
backstage.io/techdocs-ref: dir:.
jenkins.io/job-full-name: payment-service/main
pagerduty.com/service-id: PABC123
sonarqube.org/project-key: org_payment-service
tags:
- java
- payments
links:
- url: https://dashboard.example.com/payments
title: Monitoring Dashboard
icon: dashboard
- url: https://wiki.example.com/payment-service
title: Wiki
spec:
type: service
lifecycle: production
owner: team-payments
system: billing
providesApis:
- payment-api
consumesApis:
- user-api
- notification-api
dependsOn:
- resource:payments-db
- component:auth-service
Exemple d’entité API
Section intitulée « Exemple d’entité API »apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: payment-api
description: Payment processing REST API
tags:
- rest
- payments
spec:
type: openapi
lifecycle: production
owner: team-payments
system: billing
definition: |
openapi: "3.0.0"
info:
title: Payment API
version: 1.0.0
paths:
/payments:
post:
summary: Create a payment
responses:
"201":
description: Payment created
Exemple de System et Domain
Section intitulée « Exemple de System et Domain »apiVersion: backstage.io/v1alpha1
kind: System
metadata:
name: billing
description: Billing and payment processing system
spec:
owner: team-payments
domain: commerce
---
apiVersion: backstage.io/v1alpha1
kind: Domain
metadata:
name: commerce
description: E-commerce domain covering orders, payments, and fulfillment
spec:
owner: group:engineering-leadership
Templates
Section intitulée « Templates »Propriétés des templates
Section intitulée « Propriétés des templates »| Commande | Description |
|---|---|
kind: Template dans template.yaml | Définir un template logiciel |
Définir spec.type: service | Le template crée un service |
Définir spec.steps[] pour les actions du template | Définir les étapes de scaffolding |
action: fetch:template | Récupérer et rendre les fichiers du template |
action: publish:github | Publier le dépôt scaffoldé sur GitHub |
action: publish:github:pull-request | Créer une PR au lieu d’un nouveau dépôt |
action: catalog:register | Enregistrer l’entité créée dans le catalogue |
action: github:actions:dispatch | Déclencher un workflow GitHub Actions |
Utiliser ${{ parameters.name }} dans les templates | Référencer les paramètres de saisie utilisateur |
Définir spec.parameters[] pour les champs de formulaire | Définir le formulaire de saisie du template |
Utiliser ui:widget: textarea dans les paramètres | Personnaliser le widget de champ de formulaire |
Exemple de définition de template
Section intitulée « Exemple de définition de template »apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: microservice-template
title: Create a Microservice
description: Scaffold a new microservice with CI/CD, monitoring, and docs
tags:
- recommended
- microservice
spec:
owner: team-platform
type: service
parameters:
- title: Service Details
required:
- name
- description
- owner
properties:
name:
title: Service Name
type: string
description: Unique name of the service
ui:autofocus: true
ui:options:
rows: 5
description:
title: Description
type: string
owner:
title: Owner
type: string
description: Team that owns this service
ui:field: OwnerPicker
ui:options:
catalogFilter:
kind: Group
- title: Infrastructure
properties:
language:
title: Language
type: string
enum: ["go", "java", "python", "typescript"]
default: go
database:
title: Database
type: string
enum: ["postgres", "mysql", "none"]
default: postgres
enableMonitoring:
title: Enable Monitoring
type: boolean
default: true
steps:
- id: fetch-base
name: Fetch Base Template
action: fetch:template
input:
url: ./skeleton
values:
name: ${{ parameters.name }}
description: ${{ parameters.description }}
owner: ${{ parameters.owner }}
language: ${{ parameters.language }}
- id: publish
name: Publish to GitHub
action: publish:github
input:
allowedHosts: ["github.com"]
repoUrl: github.com?owner=my-org&repo=${{ parameters.name }}
description: ${{ parameters.description }}
defaultBranch: main
repoVisibility: internal
- id: register
name: Register in Catalog
action: catalog:register
input:
repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml
output:
links:
- title: Repository
url: ${{ steps['publish'].output.remoteUrl }}
- title: Open in Catalog
icon: catalog
entityRef: ${{ steps['register'].output.entityRef }}
Installation de plugins
Section intitulée « Installation de plugins »| Commande | Description |
|---|---|
yarn add @backstage/plugin-catalog | Installer le plugin catalogue |
yarn add @backstage/plugin-techdocs | Installer le plugin TechDocs |
yarn add @backstage/plugin-kubernetes | Installer le plugin Kubernetes |
yarn add @backstage/plugin-github-actions | Installer le plugin GitHub Actions |
yarn add @backstage/plugin-search | Installer le plugin recherche |
yarn add @backstage/plugin-scaffolder | Installer le plugin scaffolder |
yarn add @backstage/plugin-api-docs | Installer le plugin documentation API |
yarn add @backstage/plugin-cost-insights | Installer le plugin analyse des coûts |
Enregistrement de plugins
Section intitulée « Enregistrement de plugins »Enregistrer les plugins frontend dans packages/app/src/App.tsx :
import { CatalogGraphPage } from '@backstage/plugin-catalog-graph';
import { TechDocsReaderPage } from '@backstage/plugin-techdocs';
import { SearchPage } from '@backstage/plugin-search';
const routes = (
<FlatRoutes>
<Route path="/catalog" element={<CatalogIndexPage />} />
<Route path="/catalog/:namespace/:kind/:name" element={<CatalogEntityPage />}>
<EntityLayout>
<EntityLayout.Route path="/" title="Overview">
<EntityOverviewContent />
</EntityLayout.Route>
<EntityLayout.Route path="/api" title="API">
<EntityApiContent />
</EntityLayout.Route>
<EntityLayout.Route path="/docs" title="Docs">
<EntityTechDocsContent />
</EntityLayout.Route>
</EntityLayout>
</Route>
<Route path="/docs" element={<TechDocsReaderPage />} />
<Route path="/search" element={<SearchPage />} />
<Route path="/catalog-graph" element={<CatalogGraphPage />} />
</FlatRoutes>
);
Enregistrer les plugins backend dans packages/backend/src/index.ts :
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
backend.add(import('@backstage/plugin-app-backend'));
backend.add(import('@backstage/plugin-catalog-backend'));
backend.add(import('@backstage/plugin-catalog-backend-module-github-org'));
backend.add(import('@backstage/plugin-scaffolder-backend'));
backend.add(import('@backstage/plugin-techdocs-backend'));
backend.add(import('@backstage/plugin-search-backend'));
backend.add(import('@backstage/plugin-search-backend-module-catalog'));
backend.add(import('@backstage/plugin-search-backend-module-techdocs'));
backend.add(import('@backstage/plugin-auth-backend'));
backend.add(import('@backstage/plugin-auth-backend-module-github-provider'));
backend.add(import('@backstage/plugin-kubernetes-backend'));
backend.start();
TechDocs
Section intitulée « TechDocs »Opérations TechDocs
Section intitulée « Opérations TechDocs »| Commande | Description |
|---|---|
npx @techdocs/cli serve | Prévisualiser TechDocs localement |
npx @techdocs/cli serve --docker-image techdocs-container | Servir avec une image Docker personnalisée |
npx @techdocs/cli generate | Générer le site statique TechDocs |
npx @techdocs/cli generate --source-dir . | Générer depuis un répertoire spécifique |
npx @techdocs/cli publish --publisher-type googleGcs | Publier TechDocs sur GCS |
npx @techdocs/cli publish --publisher-type awsS3 | Publier TechDocs sur S3 |
Ajouter l’annotation backstage.io/techdocs-ref | Activer TechDocs pour une entité |
Créer un répertoire docs/ avec mkdocs.yml | Configurer la source TechDocs |
Définir techdocs.builder: 'local' dans la config | Utiliser le builder TechDocs local |
Définir techdocs.builder: 'external' dans la config | Utiliser un builder CI/CD externe |
Exemple de mkdocs.yml TechDocs
Section intitulée « Exemple de mkdocs.yml TechDocs »site_name: Payment Service
nav:
- Home: index.md
- Architecture: architecture.md
- API Reference: api-reference.md
- Runbooks:
- Deployment: runbooks/deployment.md
- Incident Response: runbooks/incident-response.md
plugins:
- techdocs-core
markdown_extensions:
- admonition
- pymdownx.highlight
- pymdownx.superfences
Recherche
Section intitulée « Recherche »Configuration de la recherche
Section intitulée « Configuration de la recherche »| Commande | Description |
|---|---|
yarn add @backstage/plugin-search | Installer le frontend de recherche |
yarn add @backstage/plugin-search-backend | Installer le backend de recherche |
yarn add @backstage/plugin-search-backend-module-catalog | Ajouter le collator de recherche du catalogue |
yarn add @backstage/plugin-search-backend-module-techdocs | Ajouter le collator de recherche TechDocs |
Configurer le moteur de recherche dans app-config.yaml | Configurer Lunr, Elasticsearch ou PgStore |
Définir search.pg dans la config | Utiliser PostgreSQL pour la recherche |
Définir search.elasticsearch dans la config | Utiliser Elasticsearch pour la recherche |
Configuration
Section intitulée « Configuration »Paramètres principaux
Section intitulée « Paramètres principaux »| Commande | Description |
|---|---|
Modifier app-config.yaml | Fichier de configuration principal |
Modifier app-config.local.yaml | Surcharges de développement local |
Modifier app-config.production.yaml | Configuration de production |
Définir app.baseUrl dans la config | Configurer l’URL du frontend |
Définir backend.baseUrl dans la config | Configurer l’URL du backend |
Définir backend.database dans la config | Configurer la connexion à la base de données |
Définir backend.cors.origin dans la config | Configurer les origines CORS |
Définir auth.providers dans la config | Configurer les fournisseurs d’authentification |
Définir catalog.locations[] dans la config | Ajouter des sources d’entités au catalogue |
Définir catalog.rules[] dans la config | Définir les règles de validation des entités |
Définir integrations.github[] dans la config | Configurer le token d’intégration GitHub |
Exemple de app-config.yaml
Section intitulée « Exemple de app-config.yaml »app:
title: My Company Developer Portal
baseUrl: http://localhost:3000
organization:
name: My Company
backend:
baseUrl: http://localhost:7007
listen:
port: 7007
cors:
origin: http://localhost:3000
methods: [GET, HEAD, PATCH, POST, PUT, DELETE]
database:
client: pg
connection:
host: ${POSTGRES_HOST}
port: ${POSTGRES_PORT}
user: ${POSTGRES_USER}
password: ${POSTGRES_PASSWORD}
integrations:
github:
- host: github.com
token: ${GITHUB_TOKEN}
auth:
environment: development
providers:
github:
development:
clientId: ${GITHUB_CLIENT_ID}
clientSecret: ${GITHUB_CLIENT_SECRET}
catalog:
import:
entityFilename: catalog-info.yaml
pullRequestBranchName: backstage-integration
rules:
- allow: [Component, System, API, Resource, Location, Domain, Group, User]
locations:
- type: url
target: https://github.com/my-org/backstage-catalog/blob/main/all-components.yaml
- type: github-discovery
target: https://github.com/my-org
- type: github-org
target: https://github.com/my-org
techdocs:
builder: local
generator:
runIn: local
publisher:
type: local
kubernetes:
serviceLocatorMethod:
type: multiTenant
clusterLocatorMethods:
- type: config
clusters:
- url: ${K8S_CLUSTER_URL}
name: production
authProvider: serviceAccount
serviceAccountToken: ${K8S_TOKEN}
Diagramme des relations entre entités
Section intitulée « Diagramme des relations entre entités »| Relation | De | Vers | Description |
|---|---|---|---|
ownerOf | Group/User | Component/API | Le groupe possède l’entité |
ownedBy | Component/API | Group/User | L’entité est possédée par le groupe |
consumesApi | Component | API | Le composant utilise une API |
providesApi | Component | API | Le composant expose une API |
dependsOn | Component | Component/Resource | Le composant dépend d’un autre |
dependencyOf | Component/Resource | Component | Est une dépendance de |
partOf | Component | System | Le composant appartient au système |
hasPart | System | Component | Le système contient le composant |
parentOf | Group | Group | Relation d’équipe parente |
childOf | Group | Group | Relation d’équipe enfant |
memberOf | User | Group | L’utilisateur appartient au groupe |
hasMember | Group | User | Le groupe contient l’utilisateur |
Bonnes pratiques
Section intitulée « Bonnes pratiques »-
Utiliser catalog-info.yaml dans chaque dépôt — assurez-vous que tous les services, bibliothèques et APIs sont enregistrés dans le catalogue pour une visibilité complète.
-
Définir une propriété significative — chaque entité devrait avoir un champ
ownerpointant vers un Group valide, permettant la responsabilisation et le routage. -
Annoter richement les entités — ajoutez des annotations pour le CI/CD, le monitoring, PagerDuty et la documentation pour faire du catalogue un véritable hub.
-
Créer des templates pour les golden paths — utilisez le scaffolder pour définir des manières standardisées de créer de nouveaux services, garantissant la cohérence.
-
Implémenter TechDocs — gardez la documentation à côté du code en utilisant le plugin TechDocs et
mkdocs.ymlpour une documentation vivante. -
Utiliser la découverte GitHub — configurez
github-discoverydans les emplacements du catalogue pour découvrir et enregistrer automatiquement les dépôts. -
Modéliser votre organisation — définissez les Groups et Users pour refléter la structure de votre équipe, permettant le suivi de la propriété et les pages d’équipe.
-
Garder app-config.yaml sensible à l’environnement — utilisez
app-config.local.yamlpour le développement et des variables d’environnement pour les secrets de production. -
Construire un écosystème de plugins — créez des plugins frontend et backend personnalisés pour étendre Backstage avec les outils spécifiques de votre organisation.
-
Définir des Systems et Domains — modélisez l’architecture de haut niveau en utilisant Systems et Domains pour donner aux développeurs une carte de votre plateforme.