Registre et déploiement
- Leçon 13
- 50 min
- Module 5 : Déployer et nettoyer
Leçon 13 sur 15 · L'essentiel de Docker et du nuage pour les développeurs en IARegistre et déploiement
1. Comprendre les conteneurs
2. Construire l'image de l'application
3. Réseau, configuration et persistance
4. Les services de base du nuage
5. Déployer et nettoyer
Ce que vous saurez faire
Placez l’image là où un service infonuagique peut la récupérer, avec un numéro de version dont le sens ne change jamais. Puis lancez-la sur un service de conteneurs géré que vous pouvez supprimer en une étape.
Avant de commencerCe qu’il faut savoir et avoir sous la main
Ce que vous devez savoir
- Les étiquettes, et pourquoi
latest(la plus récente) n’est pas une version, dans L’essentiel du Dockerfile : les étiquettes et pourquoi latest n’est pas une version. - Les architectures de processeur (
linux/arm64etlinux/amd64), dans Installer et vérifier : L’architecture du processeur de votre ordinateur. - Les paramètres et les fichiers secrets à l’exécution, dans Configuration à l’exécution : un fichier de paramètres et Fichiers secrets.
- Le groupe de ressources, dans Régions et types de services : groupes de ressources, abonnements et locataires.
- L’identité gérée et le rôle
AcrPull, dans Identité et secrets : identités et Rôles et portée. - Le coût possible de chaque ressource, dans Connaître les coûts : ce qui peut entraîner des frais.
Ce qu’il vous faut sur votre ordinateur
- Le projet
~/projects/ticket-api(Windows :$HOME\projects\ticket-api) à la version 1.1.0, aveccompose.yamletsecrets/api_key.txt, ignoré par Git. Ils viennent de Données persistantes : exercice guidé : l’API et sa base de données et Configuration à l’exécution : fichiers secrets. - Votre conception infonuagique avec son inventaire des ressources,
docs/cloud-design.md, dans Connaître les coûts : Exercice du module. Ce module la compare à ce que vous créez réellement. - Docker Desktop (ou Docker Engine sous Linux) avec Buildx, dans Installer et vérifier : installer Docker.
- Option réelle seulement : un abonnement Azure permettant de créer des ressources, et l’interface en ligne de commande Azure avec l’extension
containerapp. L’option réelle coûte quelques cents si vous supprimez tout le jour même (Vérifier et supprimer s’en charge). Option simulée : rien de plus. Elle est gratuite. - Si votre projet manque ou ne fonctionne plus, copiez l’instantané
end-of-m04, comme dans Utiliser un instantané. Puis recréezsecrets/api_key.txt, selon le README de l’instantané.
Testé avec Docker Desktop 4.81.0 (Docker Engine 29.6.1, Buildx 0.35.0) sur macOS, avec une puce Apple. Les étapes Azure ont été exécutées avec Azure CLI 2.88.0 et l’extension containerapp 1.3.0b5, dans la région canadacentral. Les étapes Windows et Linux n’ont pas été testées.
Deux options, les mêmes idées
Section intitulée « Deux options, les mêmes idées »Ce module propose deux options. Choisissez-en une avant de commencer, et gardez-la pour les trois leçons.
| Réelle | Simulée | |
|---|---|---|
| Où l’API s’exécute | Azure Container Apps, avec une adresse HTTPS publique | Un conteneur sur votre ordinateur, à partir de deploy/local-cloud.yaml |
| Registre | Azure Container Registry | Un conteneur de registre sur 127.0.0.1:5000 |
| Coût | Quelques cents, si vous supprimez tout le jour même | Gratuit |
| Il vous faut | Un abonnement Azure | Seulement Docker |
Chaque sortie de ces leçons porte une indication. Les sorties réelles viennent de l’exécution sur Azure. Les sorties simulées viennent de Docker sur un Mac, le même jour. Une sortie simulée ne prétend jamais qu’une exécution a eu lieu dans un nuage. Les deux options fournissent les preuves pour l’exercice du module et le travail final.
Registre, dépôt et étiquette
Section intitulée « Registre, dépôt et étiquette »Amira commence par une petite expérience sur son ordinateur. Elle lance un registre : un serveur qui stocke des images pour que d’autres ordinateurs puissent les télécharger. L’image officielle registry de Docker en est un exemple. Elle s’exécute sur son ordinateur comme tout autre conteneur :
docker run -d --name ticket-api-registry -p 127.0.0.1:5000:5000 -v ticket-api-registry-data:/var/lib/registry registry:3.1.2Elle donne un deuxième nom à son image, qui commence par l’adresse du registre, puis l’envoie au registre :
docker tag ticket-api:1.1.0 127.0.0.1:5000/ticket-api:1.1.0docker push 127.0.0.1:5000/ticket-api:1.1.0La sortie (simulée, abrégée) :
The push refers to repository [127.0.0.1:5000/ticket-api]0b13ca62e0be: Pushed4732e419703d: Pushed...bbeda6b4abb7: Pushed1.1.0: digest: sha256:1ba724a2b1215f0d2225b7276fa6ab5f5226c1e10c46c98ee9845af3fec459ee size: 856Puis elle demande au registre ce qu’il contient. Un registre répond aux requêtes HTTP, donc curl peut l’interroger :
curl -s http://127.0.0.1:5000/v2/_catalogcurl -s http://127.0.0.1:5000/v2/ticket-api/tags/listLa sortie (simulée) :
{"repositories":["ticket-api"]}{"name":"ticket-api","tags":["1.1.0"]}Passons aux noms. Un nom d’image complet comporte trois parties : <registry>/<repository>:<tag>.
| Partie | Ici | Option réelle |
|---|---|---|
| Registre : le serveur | 127.0.0.1:5000 |
ticketapi4821.azurecr.io |
| Dépôt : les versions d’une image, réunies | ticket-api |
ticket-api |
| Étiquette : une version | 1.1.0 |
1.1.0 |
Un nom sans registre, comme ticket-api:1.1.0, désigne Docker Hub, ou seulement votre ordinateur si l’image n’a jamais été envoyée. L’empreinte (sha256:1ba7…) désigne le contenu exact. Une étiquette pointe vers une empreinte. Toute personne autorisée à envoyer des images peut la déplacer vers une autre empreinte. C’est pourquoi chaque changement reçoit un nouveau numéro de version : 1.1.0, puis 1.1.1. Ne déployez jamais seulement latest. Dans un mois, personne ne pourra dire quel code latest désignait.
Chaque ligne Pushed (envoyée) correspond à une couche. Le registre stocke des couches, pas des images entières. Un deuxième envoi d’une image semblable transmet donc seulement les couches modifiées. L’envoi transfère les couches compressées : la colonne content size (taille du contenu) de docker image ls (73 Mo pour ticket-api:1.1.0), et non l’espace disque utilisé (345 Mo).
Le flux de travail et ses points d’échec
Section intitulée « Le flux de travail et ses points d’échec »Un déploiement comporte quatre actions : construire, envoyer, déployer, vérifier. Chacune peut échouer d’une façon visible, si vous savez où regarder.
Description textuelle du diagramme
La construction produit une image pour linux/amd64, le type de processeur des serveurs du nuage. Vérifiez la plateforme avant l’envoi. L’envoi place l’image dans le registre sous une étiquette versionnée. Le déploiement crée une nouvelle révision : une copie fixe des paramètres et de l’image de l’application. Si la révision ne démarre pas, l’ancienne garde le trafic. Vous lisez les journaux (logs) système, corrigez la cause et redéployez. Si elle démarre, le trafic passe à cette révision, et vous lancez les vérifications de bon fonctionnement. Lorsqu’elles réussissent, vous consignez ce que vous avez déployé. Cette leçon couvre les étapes 1 à 4. Configuration opérationnelle couvre l’étape 5, et Vérifier et supprimer couvre les étapes 6 et 7.
Construire pour le processeur du nuage
Section intitulée « Construire pour le processeur du nuage »Azure Container Apps exécute seulement des images linux/amd64. Un simple docker build sur un Mac à puce Apple produit une image linux/arm64. Amira vérifie ce que contient son image :
docker buildx imagetools inspect 127.0.0.1:5000/ticket-api:1.1.0La sortie (simulée, abrégée) :
Name: 127.0.0.1:5000/ticket-api:1.1.0MediaType: application/vnd.oci.image.index.v1+jsonDigest: sha256:1ba724a2b1215f0d2225b7276fa6ab5f5226c1e10c46c98ee9845af3fec459ee
Manifests: Name: 127.0.0.1:5000/ticket-api:1.1.0@sha256:97dd1c69... Platform: linux/arm64
Name: 127.0.0.1:5000/ticket-api:1.1.0@sha256:c66bcb26... Platform: unknown/unknownSeulement linux/arm64. L’entrée unknown/unknown (inconnu/inconnu) est l’attestation de construction : une trace de la façon dont l’image a été construite, pas une deuxième image. Sur un ordinateur Intel ou AMD, vous voyez linux/amd64 ici. La prochaine construction sera alors identique à la vôtre.
Prédisez : que se passe-t-il si un ordinateur avec un processeur amd64 demande cette image? Amira la demande comme le ferait un ordinateur amd64 :
docker pull --platform linux/amd64 127.0.0.1:5000/ticket-api:1.1.0-arm64La sortie (simulée; elle a d’abord envoyé la même image arm64 avec l’étiquette 1.1.0-arm64) :
Error response from daemon: no matching manifest for linux/amd64 in the manifest list entries: no match for platform in manifest: not foundDocker le dit clairement. Azure ne le fait pas, comme vous le verrez dans Configuration opérationnelle. Amira construit donc pour le nuage avec --platform :
docker buildx build --platform linux/amd64 -t 127.0.0.1:5000/ticket-api:1.1.0 --push .La sortie (simulée, la fin) :
#12 naming to 127.0.0.1:5000/ticket-api:1.1.0 done#12 pushing layers 0.0s done#12 pushing manifest for 127.0.0.1:5000/ticket-api:1.1.0@sha256:204c4f72f635011840ac1cb898cbd2de5e1aa6c189905078971cfe8283f002f6 0.1s done#12 DONE 0.2sLes couches amd64 étaient dans le cache de construction depuis une construction précédente. Cela a donc pris moins d’une seconde. Sans le cache, la même construction a pris 23 secondes, et RUN pip install a pris 19,7 secondes plutôt que 11,8 secondes. Un Mac à puce Apple exécute les programmes amd64 par émulation : un programme traduit les instructions de l’autre processeur. --push envoie immédiatement le résultat au registre. Maintenant, imagetools inspect indique Platform: linux/amd64 (plateforme : linux/amd64).
Regardez l’empreinte : ce n’est plus 1ba724…. La même étiquette, 1.1.0, pointe maintenant vers un contenu différent. Gardez cela en tête pour l’erreur courante à la fin de la leçon.
L’option réelle : créer le déploiement
Section intitulée « L’option réelle : créer le déploiement »Description textuelle du diagramme
Les numéros indiquent l’ordre des étapes ci-dessous. Le groupe de ressources contient tout; le supprimer supprime donc tout. Il y a une exception, le Key Vault, traitée dans Vérifier et supprimer. L’identité peut récupérer des images seulement de ce registre. L’environnement crée un espace de travail Log Analytics que vous n’avez pas demandé. Celui-ci peut facturer les données de journaux.
Amira suit la conception du module 4. Elle place d’abord les noms dans des variables de l’interpréteur de commandes. Chaque commande est ainsi plus courte, et elle ne peut pas mal saisir un nom. Choisissez votre propre nom de registre : il doit être unique dans tout Azure, avec 5 à 50 lettres et chiffres, sans traits d’union. Ajoutez vos propres chiffres à ticketapi.
RG=rg-ticket-api-practiceLOCATION=canadacentralACR=ticketapi4821$RG = "rg-ticket-api-practice"$LOCATION = "canadacentral"$ACR = "ticketapi4821"Les variables existent seulement dans cette fenêtre de terminal. Si vous en ouvrez une nouvelle, définissez-les de nouveau. Les commandes ci-dessous utilisent $RG, $ACR et les autres, de la même façon dans les deux interpréteurs de commandes. Quand une commande diffère, des onglets sont proposés.
Avant l’étape 1 : se connecter et préparer l’abonnement
Section intitulée « Avant l’étape 1 : se connecter et préparer l’abonnement »az loginaz extension add --name containerapp --upgradeaz provider register --namespace Microsoft.Appaz provider register --namespace Microsoft.OperationalInsightsaz provider register --namespace Microsoft.ContainerRegistryaz login ouvre le navigateur pour votre connexion à Azure. L’extension ajoute les commandes az containerapp. Un fournisseur de ressources est la partie d’Azure qui crée un type de ressource. Un nouvel abonnement doit inscrire chaque fournisseur une fois. Cela peut prendre quelques minutes. Vérifiez avec az provider show -n Microsoft.App --query registrationState -o tsv : la réponse doit être Registered (inscrit). Dans l’abonnement de test, les trois étaient déjà inscrits.
L’extension affiche WARNING: The behavior of this command has been altered by the following extension: containerapp (avertissement : cette extension a modifié le comportement de la commande) pour chaque commande az containerapp. Cet avertissement est sans conséquence. Les sorties ci-dessous l’omettent.
Étape 1 : le groupe de ressources, avec des étiquettes
Section intitulée « Étape 1 : le groupe de ressources, avec des étiquettes »az group create --name $RG --location $LOCATION --tags purpose=practice course=C18 -o tableLa sortie (réelle) :
Location Name------------- ----------------------canadacentral rg-ticket-api-practiceLes étiquettes indiquent pourquoi le groupe existe. Elles aident la personne qui consulte plus tard la liste de l’abonnement. Elles n’aident pas à rechercher ses ressources, comme le montre Vérifier et supprimer.
Étape 2 : le registre
Section intitulée « Étape 2 : le registre »az acr create --resource-group $RG --name $ACR --sku Basic -o tableLa sortie (réelle) :
NAME RESOURCE GROUP LOCATION SKU LOGIN SERVER CREATION DATE ADMIN ENABLED------------- ---------------------- ------------- ----- ------------------------ -------------------- ---------------ticketapi4821 rg-ticket-api-practice canadacentral Basic ticketapi4821.azurecr.io 2026-10-07T16:10:57Z FalseLOGIN SERVER (serveur de connexion) est la partie registre du nom de l’image. ADMIN ENABLED False (administrateur désactivé) : le compte administrateur du registre, qui utilise un mot de passe partagé, est désactivé. Gardez-le désactivé. L’application récupère les images avec son identité; elle n’a donc pas besoin de mot de passe.
Étape 3 : construire pour amd64 et envoyer
Section intitulée « Étape 3 : construire pour amd64 et envoyer »az acr login --name $ACRdocker buildx build --platform linux/amd64 -t $ACR.azurecr.io/ticket-api:1.1.0 --push .Lancez la construction dans le dossier du projet : le . final est le contexte de construction. La sortie (réelle, abrégée) :
Login Succeeded...#13 exporting to image#13 pushing layers 11.8s done#13 pushing manifest for ticketapi4821.azurecr.io/ticket-api:1.1.0@sha256:cfd04194eb1be66f49a40575f75a0b2105a74e172f953df26a355291a5191afd 1.0s done#13 DONE 14.7saz acr login donne à Docker un jeton (token) pour ce registre. Le jeton expire après quelques heures. Si un envoi ultérieur indique unauthorized (non autorisé), relancez az acr login. La construction et l’envoi ont pris 27 secondes au total. Vérifiez l’étiquette et la plateforme :
az acr repository show-tags -n $ACR --repository ticket-api -o tabledocker buildx imagetools inspect $ACR.azurecr.io/ticket-api:1.1.0La sortie (réelle, abrégée) :
Result--------1.1.0
Name: ticketapi4821.azurecr.io/ticket-api:1.1.0MediaType: application/vnd.oci.image.index.v1+jsonDigest: sha256:cfd04194eb1be66f49a40575f75a0b2105a74e172f953df26a355291a5191afd
Manifests: Name: ticketapi4821.azurecr.io/ticket-api:1.1.0@sha256:b08764e2... Platform: linux/amd64
Name: ticketapi4821.azurecr.io/ticket-api:1.1.0@sha256:eaa1e2c6... Platform: unknown/unknownlinux/amd64 : le nuage peut l’exécuter.
Étape 4 : l’identité et son seul rôle
Section intitulée « Étape 4 : l’identité et son seul rôle »az identity create --resource-group $RG --name id-ticket-api -o tableIDENTITY_ID=$(az identity show -g $RG -n id-ticket-api --query id -o tsv)PRINCIPAL_ID=$(az identity show -g $RG -n id-ticket-api --query principalId -o tsv)REGISTRY_ID=$(az acr show -n $ACR --query id -o tsv)az role assignment create --assignee-object-id $PRINCIPAL_ID --assignee-principal-type ServicePrincipal --role AcrPull --scope $REGISTRY_ID -o tableaz identity create --resource-group $RG --name id-ticket-api -o table$IDENTITY_ID = az identity show -g $RG -n id-ticket-api --query id -o tsv$PRINCIPAL_ID = az identity show -g $RG -n id-ticket-api --query principalId -o tsv$REGISTRY_ID = az acr show -n $ACR --query id -o tsvaz role assignment create --assignee-object-id $PRINCIPAL_ID --assignee-principal-type ServicePrincipal --role AcrPull --scope $REGISTRY_ID -o tableLa sortie (réelle, colonnes abrégées) :
ClientId Location Name PrincipalId ResourceGroup-------------- ------------- ------------- -------------- ----------------------faf6b35b-... canadacentral id-ticket-api d2066809-... rg-ticket-api-practice
CreatedOn PrincipalType Scope-------------------------------- ---------------- ---------------------------------------------------------------------------------------2026-10-07T16:12:09.352851+00:00 ServicePrincipal /subscriptions/.../resourceGroups/rg-ticket-api-practice/providers/Microsoft.ContainerRegistry/registries/ticketapi4821La portée est le registre, pas le groupe ni l’abonnement. L’identité peut récupérer des images de ce registre seulement, et ne peut rien faire d’autre. C’est le principe du moindre privilège, comme au module 4. --assignee-principal-type ServicePrincipal évite une erreur lorsque le service de rôles ne connaît pas encore la nouvelle identité.
Étape 5 : l’environnement Container Apps
Section intitulée « Étape 5 : l’environnement Container Apps »az containerapp env create --resource-group $RG --name cae-ticket-api --location $LOCATION -o tableLa sortie (réelle, abrégée) :
WARNING: No Log Analytics workspace provided.WARNING: Generating a Log Analytics workspace with name "workspace-rgticketapipracticeXXXX"...Container Apps environment created. To deploy a container app, use: az containerapp create --help
Location Name ResourceGroup-------------- -------------- ----------------------Canada Central cae-ticket-api rg-ticket-api-practiceL’environnement est l’espace partagé où s’exécutent les applications conteneurisées : un réseau et un endroit pour les journaux. Cela a pris environ 2 à 3 minutes. Lisez les deux avertissements : Azure a créé un espace de travail Log Analytics pour les journaux. Vous ne l’avez pas demandé, et il peut facturer les données de journaux. Vos caractères aléatoires diffèrent de XXXX. Ajoutez-le maintenant à votre inventaire :
az resource list -g $RG -o tableLa sortie (réelle) :
Name ResourceGroup Location Type Status--------------------------------- ---------------------- ------------- ------------------------------------------------ ---------ticketapi4821 rg-ticket-api-practice canadacentral Microsoft.ContainerRegistry/registries Succeededid-ticket-api rg-ticket-api-practice canadacentral Microsoft.ManagedIdentity/userAssignedIdentities Succeededworkspace-rgticketapipracticeXXXX rg-ticket-api-practice canadacentral Microsoft.OperationalInsights/workspaces Succeededcae-ticket-api rg-ticket-api-practice canadacentral Microsoft.App/managedEnvironments SucceededQuatre ressources, alors que vous en avez demandé trois. L’attribution de rôle de l’étape 4 n’apparaît pas dans la liste : az resource list n’affiche pas les attributions de rôles.
Étape 6 : créer l’application conteneurisée
Section intitulée « Étape 6 : créer l’application conteneurisée »KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(24))")az containerapp create --resource-group $RG --name ticket-api --environment cae-ticket-api \ --image $ACR.azurecr.io/ticket-api:1.1.0 \ --user-assigned $IDENTITY_ID --registry-server $ACR.azurecr.io --registry-identity $IDENTITY_ID \ --ingress external --target-port 8000 \ --cpu 0.25 --memory 0.5Gi --min-replicas 0 --max-replicas 2 \ --secrets api-key="$KEY" \ --env-vars API_KEY=secretref:api-key REQUIRE_API_KEY=true SHOW_DOCS=false$KEY = python -c "import secrets; print(secrets.token_urlsafe(24))"az containerapp create --resource-group $RG --name ticket-api --environment cae-ticket-api ` --image "$ACR.azurecr.io/ticket-api:1.1.0" ` --user-assigned $IDENTITY_ID --registry-server "$ACR.azurecr.io" --registry-identity $IDENTITY_ID ` --ingress external --target-port 8000 ` --cpu 0.25 --memory 0.5Gi --min-replicas 0 --max-replicas 2 ` --secrets "api-key=$KEY" ` --env-vars API_KEY=secretref:api-key REQUIRE_API_KEY=true SHOW_DOCS=falseL’historique de l’interpréteur de commandes garde $KEY, le nom de la variable, pas la clé. Les options, une par une :
| Option | Ce qu’elle fait |
|---|---|
--environment cae-ticket-api |
Exécute l’application dans l’environnement de l’étape 5. |
--image …/ticket-api:1.1.0 |
La version exacte à exécuter. |
--user-assigned $IDENTITY_ID |
Donne à l’application l’identité de l’étape 4. |
--registry-server, --registry-identity |
Récupère l’image du registre avec cette identité : aucun mot de passe. |
--ingress external --target-port 8000 |
Donne à l’application une adresse HTTPS publique et envoie les requêtes au port 8000 du conteneur. |
--cpu 0.25 --memory 0.5Gi |
La taille de chaque réplica. La plus petite taille. |
--min-replicas 0 --max-replicas 2 |
Aucun réplica quand personne ne fait d’appel; au plus deux. |
--secrets api-key="$KEY" |
Stocke la clé comme secret api-key de l’application. |
--env-vars API_KEY=secretref:api-key … |
Définit API_KEY à partir du secret, et deux paramètres ordinaires. |
La sortie (réelle) :
WARNING: User identity /subscriptions/.../userassignedidentities/id-ticket-api is already assigned to containerappContainer app created. Access your app at https://ticket-api.nicewater-a307f95a.canadacentral.azurecontainerapps.io/23 secondes. L’avertissement est sans conséquence : --user-assigned et --registry-identity désignent la même identité. Votre adresse a une partie centrale différente. Vérifiez l’état :
az containerapp show -g $RG -n ticket-api --query "{rev:properties.latestRevisionName, status:properties.runningStatus, prov:properties.provisioningState}" -o tableLa sortie (réelle) :
Rev Status Prov------------------- -------- ---------ticket-api--nz14cir Running SucceededLa première révision est ticket-api--nz14cir. Succeeded (réussi) signifie qu’Azure a accepté les paramètres. Cela ne prouve pas que l’API répond : les deux prochaines leçons le vérifieront.
Le parcours simulé : les mêmes étapes sur votre ordinateur
Section intitulée « Le parcours simulé : les mêmes étapes sur votre ordinateur »Le parcours simulé garde les idées, sans nécessiter de compte. Le tableau associe chaque élément réel à sa version locale :
| Réel (Azure) | Simulé (votre ordinateur) |
|---|---|
Registre ticketapi4821.azurecr.io |
Le conteneur registry sur 127.0.0.1:5000 |
az acr login |
Inutile : seul votre ordinateur peut accéder à ce registre |
L’image pour linux/amd64 |
La même construction, envoyée au registre local |
Application conteneurisée ticket-api |
Le service api dans deploy/local-cloud.yaml |
Le secret api-key, secretref: |
Un secret Compose provenant de secrets/api_key.txt, lu avec API_KEY_FILE |
--cpu 0.25 --memory 0.5Gi |
cpus: 0.25 et mem_limit: 512m |
| Adresse HTTPS, accès entrant externe | http://127.0.0.1:8080 : sans HTTPS |
| Révisions, mise à l’échelle, récupération depuis le registre | Non simulées |
La simulation exécute l’image que vous avez construite pour votre ordinateur, ticket-api:1.1.0. Elle ne peut pas exécuter rapidement l’image amd64 sur une puce Apple : l’émulation fonctionne, mais elle est lente. deploy/local-cloud.yaml se trouve dans le projet :
name: ticket-api-cloud-sim
services: api: image: ticket-api:1.1.0 ports: - "127.0.0.1:8080:8000" environment: API_KEY_FILE: /run/secrets/api_key REQUIRE_API_KEY: "true" SHOW_DOCS: "false" secrets: - api_key cpus: 0.25 mem_limit: 512m restart: on-failure healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2)"] interval: 10s timeout: 3s retries: 3 start_period: 5s
secrets: api_key: file: ../secrets/api_key.txtLe chemin du secret est ../secrets/api_key.txt, car Compose lit les chemins à partir du dossier du fichier Compose, deploy/. Configuration opérationnelle explique la vérification de l’état de santé et la politique de redémarrage. Démarrez le service depuis le dossier du projet :
docker compose -f deploy/local-cloud.yaml up -ddocker compose -f deploy/local-cloud.yaml psLa sortie (simulée) :
Network ticket-api-cloud-sim_default Creating Network ticket-api-cloud-sim_default Created Container ticket-api-cloud-sim-api-1 Creating Container ticket-api-cloud-sim-api-1 Created Container ticket-api-cloud-sim-api-1 Starting Container ticket-api-cloud-sim-api-1 StartedNAME IMAGE COMMAND SERVICE CREATED STATUS PORTSticket-api-cloud-sim-api-1 ticket-api:1.1.0 "fastapi run --host …" api 13 seconds ago Up 12 seconds (healthy) 127.0.0.1:8080->8000/tcp-f indique le fichier Compose, car ce n’est pas compose.yaml. Le nom ticket-api-cloud-sim le distingue du projet de base de données du module 3. Les deux peuvent donc coexister. L’état passe de health: starting (vérification en cours) à healthy (en bon état) après la première vérification. Cela prend environ 10 secondes après le démarrage.
Exercice guidé : envoyer une version et la déployer
Section intitulée « Exercice guidé : envoyer une version et la déployer »Suivez votre parcours. Travaillez dans le dossier du projet.
- Écrivez dans
docs/cloud-design.mdquel parcours vous utilisez. - Parcours simulé : démarrez le registre local avec la commande
docker run … registry:3.1.2de Registre, dépôt et étiquette. Parcours réel : connectez-vous, puis suivez les étapes 1 et 2 du parcours réel. - Construisez pour
linux/amd64avec--push, vers votre registre, avec l’étiquette1.1.0. - Vérifiez la plateforme avec
docker buildx imagetools inspect. Résultat attendu :Platform: linux/amd64(plateforme : linux/amd64), et une entréeunknown/unknown(inconnu/inconnu). - Vérifiez la liste des étiquettes. Simulé :
curl -s http://127.0.0.1:5000/v2/ticket-api/tags/listaffiche"tags":["1.1.0"](étiquettes : 1.1.0). Réel :az acr repository show-tagsaffiche1.1.0. - Parcours simulé : démarrez
deploy/local-cloud.yamlet attendez(healthy)(en bon état). Parcours réel : suivez les étapes 4 à 6 et attendezRunning(en cours d’exécution) etSucceeded(réussi). - Notez le nom de l’image avec son empreinte et, pour le parcours réel, l’adresse et le nom de la première révision. Vous en aurez besoin dans les deux prochaines leçons.
Afficher le résultat attendu
Simulé : docker compose -f deploy/local-cloud.yaml ps affiche ticket-api-cloud-sim-api-1 avec Up … (healthy) (en cours d’exécution, en bon état) sur 127.0.0.1:8080->8000/tcp. Le registre local contient aussi ticket-api avec l’étiquette 1.1.0 pour linux/amd64.
Réel : az resource list -g rg-ticket-api-practice -o table liste cinq ressources : le registre, l’identité, l’espace de travail, l’environnement et l’application conteneurisée. az containerapp show indique Running et Succeeded. Vos notes ressemblent à ceci :
Image: ticketapi4821.azurecr.io/ticket-api:1.1.0@sha256:cfd04194eb1b...Address: https://ticket-api.nicewater-a307f95a.canadacentral.azurecontainerapps.ioRevision: ticket-api--nz14cirÀ vous de jouer : construire sans --platform
Section intitulée « À vous de jouer : construire sans --platform »Construisez l’image à nouveau, mais omettez --platform, puis envoyez-la avec l’étiquette 1.1.0-native :
docker buildx build -t 127.0.0.1:5000/ticket-api:1.1.0-native --push .Avant d’exécuter imagetools inspect sur cette image, prédisez la plateforme. Répondez ensuite : sur quels ordinateurs cette étiquette peut-elle fonctionner? Azure Container Apps pourrait-il l’exécuter?
Afficher la réponse
Sans --platform, Buildx construit pour l’ordinateur qui effectue la construction. Sur une puce Apple, imagetools inspect affiche Platform: linux/arm64 (plateforme : linux/arm64). Sur un ordinateur Intel ou AMD, il affiche linux/amd64. Une image uniquement arm64 fonctionne sur les ordinateurs arm64, et un ordinateur amd64 ne peut pas la récupérer. docker pull --platform linux/amd64 donne no matching manifest for linux/amd64 (aucun manifeste correspondant pour linux/amd64). Azure Container Apps exécute uniquement amd64. Il ne pourrait donc pas exécuter cette étiquette construite sur un Mac avec une puce Apple. Écrivez toujours --platform linux/amd64 pour une construction destinée au nuage, même sur un ordinateur où c’est la valeur par défaut. La commande fait alors la même chose sur chaque ordinateur.
Erreur courante
La même étiquette, un contenu différent
Symptôme : Amira a envoyé 127.0.0.1:5000/ticket-api:1.1.0 deux fois : d’abord la construction arm64, puis la construction amd64. La liste des étiquettes affiche toujours seulement "tags":["1.1.0"], et aucun avertissement ne l’a prévenue. Mais l’empreinte est passée de sha256:1ba724a2… à sha256:204c4f72…. Un déploiement qui indique 1.1.0 exécute maintenant un contenu différent du déploiement d’hier portant le même nom.
Cause : une étiquette pointe vers une empreinte. Un envoi avec une étiquette existante déplace l’étiquette. La plupart des registres le permettent par défaut, y compris Azure Container Registry.
Solution :
- Donnez une nouvelle version à chaque changement :
1.1.1pour une correction,1.2.0pour une nouvelle fonctionnalité. N’envoyez jamais une construction différente sous une version déjà déployée. - Notez l’empreinte avec l’étiquette dans
DEPLOY.md. L’empreinte prouve ce qui a été exécuté. - Pour fixer la version le plus strictement possible, déployez par empreinte :
ticketapi4821.azurecr.io/ticket-api@sha256:cfd04194…. Personne ne peut déplacer une empreinte.
Pour un vrai service d’IA : une image contient souvent un modèle entraîné. Si quelqu’un déplace l’étiquette 2.0.0 vers un nouveau modèle, les prédictions du service changent. Le registre des déploiements indique pourtant toujours 2.0.0. Personne ne peut alors expliquer pourquoi les résultats ont changé. Une version doit correspondre à un seul modèle et à un seul code.
Vérifiez votre compréhension
Nommez les trois parties de ticketapi4821.azurecr.io/ticket-api:1.1.0 et indiquez quelle partie un envoi peut changer sans avertissement.
Afficher la réponse
ticketapi4821.azurecr.io est le registre, le serveur qui stocke les images. ticket-api est le dépôt, qui regroupe les versions d’une image. 1.1.0 est l’étiquette, une version. Un envoi avec le même nom déplace l’étiquette vers un nouveau contenu sans avertissement. Seule l’empreinte (sha256:…) correspond toujours au même contenu. C’est pourquoi chaque changement reçoit un nouveau numéro de version et pourquoi DEPLOY.md consigne aussi l’empreinte.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Prédisez : sur un Mac avec une puce Apple, vous exécutez docker build -t ticket-api:1.1.0 . et envoyez l'image au registre Azure. Azure Container Apps pourra-t-il l'exécuter? Que changez-vous?
Afficher la réponse
Non. Une construction ordinaire sur une puce Apple produit une image linux/arm64, et Azure Container Apps exécute uniquement linux/amd64. Construisez avec docker buildx build --platform linux/amd64 -t ticketapi4821.azurecr.io/ticket-api:1.1.0 --push .. Vérifiez ensuite avec docker buildx imagetools inspect que la plateforme est linux/amd64 avant de déployer.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
L'application conteneurisée a besoin d'images du registre. Pourquoi le cours lui donne-t-il une identité avec AcrPull sur le registre, plutôt que le compte administrateur du registre?
Afficher la réponse
Le compte administrateur utilise un seul mot de passe partagé qui donne tous les droits sur le registre. Quiconque le voit peut envoyer et supprimer des images. Il faut aussi le stocker et le changer manuellement. L’identité n’a pas besoin de mot de passe : Azure donne ses jetons à l’application. Son rôle, AcrPull, permet seulement de récupérer des images, et sa portée se limite à ce registre. Si quelqu’un détourne l’application, cette personne ne peut pas envoyer une image modifiée ni accéder à autre chose. C’est le principe du moindre privilège.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Récapitulatif
- Un registre stocke des images. Un nom complet est
<registry>/<repository>:<tag>. Une étiquette peut se déplacer; une empreinte ne le peut pas. - Donnez une nouvelle version à chaque changement, et ne déployez jamais uniquement
latest. - Construisez pour le nuage avec
--platform linux/amd64, et vérifiez avecdocker buildx imagetools inspectavant de déployer. - Réel : un groupe de ressources avec des étiquettes, un registre (avec le compte administrateur désactivé), un environnement (qui crée un espace de travail Log Analytics), une identité avec
AcrPullsur le registre et l’application conteneurisée avec une nouvelle clé comme secret. - Simulé : un registre local sur
127.0.0.1:5000, etdeploy/local-cloud.yamlavec les mêmes paramètres et limites.
L’application fonctionne, mais la plateforme sait seulement que quelque chose écoute sur le port 8000. La prochaine leçon lui indique comment vérifier l’application et jusqu’où elle peut grandir. Elle indique aussi ce qui doit se passer lorsqu’une nouvelle version ne peut pas démarrer.
Leçon suivante : Configuration opérationnelle