Azure Container Instance (ACI) — Installation Standalone

Support DQE
Support DQE
  • Mise à jour

Déployez DQE One Standalone en tant que groupe Azure Container Instance (ACI) autonome avec NGINX, Redis et PostgreSQL, exposé via une Application Gateway.

Remarque : tous les éléments décrits ci-dessous sont des recommandations de DQE, basées sur l'expérience de déploiement auprès de différents clients. Le client est responsable de l'intégration de la solution dans sa propre architecture. Un architecte connaissant le contexte client et l'infrastructure interne doit aligner les recommandations de DQE avec l'infrastructure du client.

1. Architecture

Ce document décrit comment déployer le backend DQE One Standalone en tant que groupe de conteneurs Azure Container Instance (ACI). Tous les conteneurs du groupe partagent le même espace de noms réseau et communiquent via localhost. Une Application Gateway expose l'application en HTTPS et redirige le trafic vers l'ACI à travers un VNET privé.

Architecture recommandée

Internet (HTTPS port 443)
         |
Application Gateway (public IP + WAF)
         |
    Private VNET subnet
         |
ACI Container Group (private IP)
         |
    NGINX sidecar (port 443)
         |
  DQE One Standalone (port 8000, internal)
         |
  Redis - PostgreSQL (internal)

Mesures de sécurité

  • Application Gateway : termine le HTTPS et redirige le trafic vers l'ACI à travers le VNET privé. Utilisez le WAF pour restreindre les plages IP entrantes.
  • VNET : isole l'ACI de tout accès direct depuis internet public. Tout le trafic provenant de l'Application Gateway transite par un sous-réseau privé.
  • Certificat SSL : géré au niveau de l'Application Gateway ou au niveau de NGINX à l'intérieur de l'ACI.
  • Secrets : utilisez secureValue dans le YAML du groupe de conteneurs pour toutes les valeurs sensibles (mots de passe, clés de licence, clés de chiffrement).

Dimensionnement recommandé

Conteneur CPU Mémoire
nginx 0,25 vCPU 0,5 Go
redis 0,5 vCPU 1,0 Go
postgres 0,5 vCPU 1,0 Go
dqeone 1,0 vCPU 2,0 Go
Total 2,25 vCPU 4,5 Go

Les groupes de conteneurs ACI sont limités à 4 vCPU et 16 Go de mémoire par groupe.

2. Installation

2.1. Azure CLI

Azure CLI doit être installé sur votre machine locale.

Linux / macOS

curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

Windows

Reportez-vous à la documentation Microsoft.

2.2. Créer une Application Gateway

L'Application Gateway expose l'ACI avec une adresse IP publique et un nom DNS. Elle gère également la terminaison HTTPS et le filtrage IP via le WAF.

Pour les détails complets de configuration, reportez-vous à la documentation Microsoft Application Gateway.

Onglet Basic

Sélectionnez votre abonnement, votre groupe de ressources et votre région. Choisissez le niveau WAF V2 pour activer le Web Application Firewall.

Stratégie WAF

Créez une nouvelle stratégie WAF depuis le champ WAF policy. Utilisez le WAF pour définir les plages IP entrantes autorisées à appeler l'Application Gateway (par exemple, votre réseau d'entreprise ou des plages IP partenaires spécifiques).

VNET

Créez un nouveau réseau virtuel (VNET) depuis le champ Virtual network. Ce VNET relie l'Application Gateway à l'ACI. Tout le trafic entre les deux transite par ce réseau privé.

Frontends

Créez une nouvelle adresse IP publique. C'est l'adresse IP exposée en externe et utilisée pour router le trafic vers l'ACI.

Backends

Créez un nouveau pool de backends. Laissez-le vide pour l'instant — l'adresse IP privée de l'ACI y sera ajoutée après le déploiement de l'ACI (section 3.3).

Configuration — Règles de routage

Créez une règle de routage avec :

  • Listener : HTTPS sur le port 443, avec votre certificat SSL.
  • Cible backend : le pool de backends créé ci-dessus.
  • Paramètre backend : HTTP sur le port 80 (le trafic entre l'Application Gateway et l'ACI transite par le VNET privé et ne nécessite pas de HTTPS en interne).

Cliquez sur Review + create pour déployer l'Application Gateway.

2.3. Ajouter un sous-réseau VNET pour l'ACI

Dans le VNET créé à la section 2.2, créez un nouveau sous-réseau dédié à l'ACI. Déléguez ce sous-réseau à Microsoft.ContainerInstance/containerGroups.

Notez l'ID de ressource complet du sous-réseau — il est requis dans le YAML du groupe de conteneurs :

/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME

2.4. Configurer Azure Storage

Les conteneurs ACI utilisent des partages de fichiers Azure (Azure File Shares) pour le stockage persistant. Créez un compte de stockage, puis créez les partages de fichiers suivants :

Partage de fichiers Usage
nginxconf Fichiers de configuration NGINX et certificat SSL
redisdata Données persistantes Redis
postgresdata Répertoire de données PostgreSQL

Étape 1 — Créer le compte de stockage :

az storage account create \
  --name MY_STORAGE_ACCOUNT \
  --resource-group MY_RESOURCE_GROUP \
  --location MY_LOCATION \
  --sku Standard_LRS

Étape 2 — Récupérer la clé du compte de stockage :

az storage account keys list \
  --account-name MY_STORAGE_ACCOUNT \
  --resource-group MY_RESOURCE_GROUP \
  --query "[0].value" -o tsv

Étape 3 — Créer les partages de fichiers :

az storage share create --name nginxconf --account-name MY_STORAGE_ACCOUNT
az storage share create --name redisdata --account-name MY_STORAGE_ACCOUNT
az storage share create --name postgresdata --account-name MY_STORAGE_ACCOUNT

Remarque sur le stockage PostgreSQL : les partages de fichiers Azure utilisent le protocole SMB, qui peut ne pas prendre en charge toutes les opérations de système de fichiers POSIX requises par PostgreSQL. Si le conteneur postgres ne démarre pas, reportez-vous à la section 5 pour l'alternative recommandée utilisant Azure Database for PostgreSQL.

2.5. Créer un espace de travail Log Analytics

Un espace de travail Log Analytics centralise les logs des conteneurs et permet la supervision via Azure Monitor. Les logs sont conservés 30 jours par défaut.

Étape 1 — Créer l'espace de travail :

az monitor log-analytics workspace create \
  --resource-group MY_RESOURCE_GROUP \
  --workspace-name dqe-standalone-logs \
  --location MY_LOCATION

Étape 2 — Récupérer l'ID de l'espace de travail :

az monitor log-analytics workspace show \
  --resource-group MY_RESOURCE_GROUP \
  --workspace-name dqe-standalone-logs \
  --query customerId -o tsv

Étape 3 — Récupérer la clé principale de l'espace de travail :

az monitor log-analytics workspace get-shared-keys \
  --resource-group MY_RESOURCE_GROUP \
  --workspace-name dqe-standalone-logs \
  --query primarySharedKey -o tsv

Conservez l'ID de l'espace de travail et la clé principale — ils sont requis dans le YAML du groupe de conteneurs (section 2.7).

2.6. Configurer NGINX

NGINX agit comme un reverse proxy à l'intérieur du groupe de conteneurs ACI, redirigeant les requêtes entrantes vers le conteneur dqeone sur le port 8000. Comme tous les conteneurs d'un groupe ACI partagent le même espace de noms réseau, la cible du proxy utilise localhost.

Créez un fichier nommé default.conf avec le contenu suivant :

server {
    listen 80;

    location / {
        proxy_pass         http://localhost:8000;
        proxy_read_timeout 300s;
    }
}

Si le HTTPS est géré directement au niveau de l'ACI (sans déchargement SSL par l'Application Gateway), ajoutez un second bloc server pour le port 443 et téléversez les fichiers de certificat SSL et de clé dans le partage de fichiers nginxconf sous un sous-répertoire ssl/.

Téléversez default.conf vers le partage de fichiers nginxconf :

az storage file upload \
  --account-name MY_STORAGE_ACCOUNT \
  --share-name nginxconf \
  --source ./default.conf \
  --path default.conf

2.7. Fichier YAML du groupe de conteneurs

Créez un fichier nommé container-group.yaml. Remplacez tous les placeholders avant le déploiement. Le tableau ci-dessous liste toutes les valeurs requises.

Placeholder Description
MY_LOCATION Région Azure, par exemple westeurope
DQE_REGISTRY_LOGIN Nom d'utilisateur du registre fourni par DQE
DQE_REGISTRY_PASSWORD Mot de passe du registre fourni par DQE
MY_STORAGE_ACCOUNT Nom du compte de stockage créé à la section 2.4
MY_STORAGE_ACCOUNT_KEY Clé du compte de stockage récupérée à la section 2.4, étape 2
LOG_ANALYTICS_WORKSPACE_ID ID de l'espace de travail récupéré à la section 2.5, étape 2
LOG_ANALYTICS_WORKSPACE_KEY Clé principale récupérée à la section 2.5, étape 3
SUBNET_RESOURCE_ID ID de ressource complet du sous-réseau noté à la section 2.3
name: dqe-standalone
apiVersion: '2021-10-01'
location: MY_LOCATION
tags: {"docker-compose-application": "docker-compose-application"}

properties:
  containers:

    - name: nginx
      properties:
        image: nginx:latest
        ports:
          - protocol: TCP
            port: 80
        resources:
          requests:
            memoryInGB: 0.5
            cpu: 0.25
        volumeMounts:
          - name: nginxconf
            mountPath: /etc/nginx/conf.d

    - name: redis
      properties:
        image: dqeone.azurecr.io/dqe-one-redis:v1.0
        resources:
          requests:
            memoryInGB: 1.0
            cpu: 0.5
        volumeMounts:
          - name: redisdata
            mountPath: /data

    - name: postgres
      properties:
        image: dqeone.azurecr.io/dqe-one-postgres:v1.0
        resources:
          requests:
            memoryInGB: 1.0
            cpu: 0.5
        environmentVariables:
          - name: POSTGRES_USER
            value: dqeone
          - name: POSTGRES_PASSWORD
            secureValue: DATABASE_PASSWORD
          - name: POSTGRES_DB
            value: dqeone
        volumeMounts:
          - name: postgresdata
            mountPath: /var/lib/postgresql/data

    - name: dqeone
      properties:
        image: dqeone.azurecr.io/standalone:v1.4.0
        command:
          - "bash"
          - "./entrypoint.sh"
        ports:
          - protocol: TCP
            port: 8000
        resources:
          requests:
            memoryInGB: 2.0
            cpu: 1.0
        environmentVariables:
          - name: SFAPIVERSION
            value: v65.0
          - name: CREATE_SUPERUSER
            value: "true"
          - name: RUN_COLLECTSTATIC
            value: "false"
          - name: DQE_ONE_SERVER_ADMIN_USER
            value: ADMIN_USER
          - name: DQE_ONE_SERVER_ADMIN_PASSWORD
            secureValue: ADMIN_PASSWORD
          - name: DQE_CLIENT_LICENCE
            value: CLIENT_LICENCE
          - name: WEBSITE_HOSTNAME
            value: https://YOUR_DNS_NAME
          - name: SECRET_ENCRYPTION_KEY
            secureValue: SECRET_ENCRYPTION_KEY_VALUE
          - name: WAIT_HOSTS
            value: "localhost:6379"
          - name: WAIT_HOSTS_TIMEOUT
            value: "300"
          - name: WAIT_SLEEP_INTERVAL
            value: "5"
          - name: WAIT_HOST_CONNECT_TIMEOUT
            value: "30"
          - name: REDIS_URL
            value: redis://localhost:6379
          - name: PORT
            value: "8000"
          - name: DEBUG
            value: "false"
          - name: DB_USER
            value: dqeone
          - name: DB_PASSWORD
            secureValue: DATABASE_PASSWORD
          - name: DB_NAME
            value: dqeone
          - name: DB_HOST
            value: localhost
          - name: DB_VOLUME_PATH
            value: ./db/
          - name: DB_MAX_CAPACITY
            value: "8000000000"
          - name: AUTHORIZED_SFTP_HOSTS
            value: AUTHORIZED_SFTP_HOSTS

  imageRegistryCredentials:
    - server: dqeone.azurecr.io
      username: DQE_REGISTRY_LOGIN
      password: DQE_REGISTRY_PASSWORD

  diagnostics:
    logAnalytics:
      workspaceId: LOG_ANALYTICS_WORKSPACE_ID
      workspaceKey: LOG_ANALYTICS_WORKSPACE_KEY

  restartPolicy: Always

  ipAddress:
    ports:
      - protocol: TCP
        port: 80
    type: Private

  osType: Linux

  volumes:
    - name: nginxconf
      azureFile:
        shareName: nginxconf
        readOnly: false
        storageAccountName: MY_STORAGE_ACCOUNT
        storageAccountKey: MY_STORAGE_ACCOUNT_KEY
    - name: redisdata
      azureFile:
        shareName: redisdata
        readOnly: false
        storageAccountName: MY_STORAGE_ACCOUNT
        storageAccountKey: MY_STORAGE_ACCOUNT_KEY
    - name: postgresdata
      azureFile:
        shareName: postgresdata
        readOnly: false
        storageAccountName: MY_STORAGE_ACCOUNT
        storageAccountKey: MY_STORAGE_ACCOUNT_KEY

  subnetIds:
    - id: SUBNET_RESOURCE_ID

Important : utilisez les versions d'images fournies par DQE. Ne les remplacez pas par le tag latest.

Point clé sur le réseau ACI : tous les conteneurs partagent le même espace de noms réseau. La communication entre conteneurs utilise localhost — c'est pourquoi REDIS_URL vaut redis://localhost:6379 et DB_HOST vaut localhost, contrairement à une configuration Docker Compose où les noms de service sont utilisés.

2.8. Variables d'environnement

Variable Exemple de valeur Description
SFAPIVERSION v65.0 Version de l'API Salesforce utilisée par l'application.
CREATE_SUPERUSER true Crée le compte administrateur initial lors du premier démarrage.
RUN_COLLECTSTATIC false Exécute la commande Django collectstatic au démarrage. Laissez à false sauf si explicitement requis.
DQE_ONE_SERVER_ADMIN_USER Nom d'utilisateur du compte administrateur initial.
DQE_ONE_SERVER_ADMIN_PASSWORD Mot de passe du compte administrateur initial. Utilisez secureValue.
DQE_CLIENT_LICENCE Clé de licence client fournie par DQE.
WEBSITE_HOSTNAME https://myapp.example.com URL HTTPS publique. Doit correspondre au nom DNS pointant vers l'Application Gateway.
SECRET_ENCRYPTION_KEY Clé de chiffrement pour les données sensibles. À générer une seule fois, ne jamais modifier après le déploiement. Utilisez secureValue.
WAIT_HOSTS localhost:6379 Service à attendre avant le démarrage. Utilise localhost dans l'ACI.
WAIT_HOSTS_TIMEOUT 300 Délai d'attente maximal, en secondes, pour les services dépendants.
WAIT_SLEEP_INTERVAL 5 Délai, en secondes, entre deux vérifications de disponibilité.
WAIT_HOST_CONNECT_TIMEOUT 30 Délai d'expiration, en secondes, pour chaque tentative de connexion.
REDIS_URL redis://localhost:6379 URL de connexion Redis. Utilise localhost dans l'ACI.
PORT 8000 Port d'écoute interne de l'application.
DEBUG false Mode debug. Doit être false en production.
DB_USER dqeone Nom d'utilisateur PostgreSQL.
DB_PASSWORD Mot de passe PostgreSQL. Doit correspondre à POSTGRES_PASSWORD dans le conteneur postgres. Utilisez secureValue.
DB_NAME dqeone Nom de la base de données PostgreSQL.
DB_HOST localhost Nom d'hôte PostgreSQL. Utilise localhost dans l'ACI. À définir sur le nom d'hôte du serveur managé si vous utilisez Azure Database for PostgreSQL.
DB_VOLUME_PATH ./db/ Chemin utilisé pour le stockage lié à la base de données.
DB_MAX_CAPACITY 8000000000 Capacité maximale de la base de données, en octets.
AUTHORIZED_SFTP_HOSTS depot-1.dqe-software.net Liste d'hôtes SFTP autorisés, séparés par des virgules.

Important : la SECRET_ENCRYPTION_KEY doit être générée une seule fois et conservée pendant toute la durée de vie du déploiement. Pour générer une clé compatible :

python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

3. Lancement

3.1. Se connecter à Azure

az login

3.2. Déployer le groupe de conteneurs

az container create -g MY_RESOURCE_GROUP -f container-group.yaml

Une fois l'opération terminée, récupérez l'adresse IP privée attribuée au groupe de conteneurs :

az container show \
  --resource-group MY_RESOURCE_GROUP \
  --name dqe-standalone \
  --query "ipAddress.ip" -o tsv

Cette adresse IP privée n'est accessible que depuis l'intérieur du VNET Azure.

3.3. Configurer le pool de backends de l'Application Gateway

Une fois l'ACI déployé, allez dans Azure Portal > Application Gateway > Backend pools > votre pool de backends > Edit.

Ajoutez l'adresse IP privée de l'ACI récupérée à l'étape 3.2. Cliquez sur Save.

3.4. Configurer la sonde d'intégrité de l'Application Gateway

La sonde d'intégrité (health probe) permet à l'Application Gateway de vérifier que l'application fonctionne. Allez dans Azure Portal > Application Gateway > Health probes > Add.

Configurez la sonde pour appeler le chemin racine de l'application en HTTP. Cliquez sur Test. Si le statut affiche Healthy, l'ACI est correctement configuré et l'Application Gateway peut lui rediriger le trafic.

Cliquez sur Add pour enregistrer la sonde d'intégrité.

3.5. Configurer le DNS

Contactez vos administrateurs DNS pour créer un enregistrement DNS pointant vers l'adresse IP publique de l'Application Gateway :

Type d'enregistrement Nom Valeur
A standalone.yourdomain.com IP publique de l'Application Gateway

3.6. Vérifier l'installation

Vérifiez que tous les conteneurs sont en cours d'exécution :

az container show \
  --resource-group MY_RESOURCE_GROUP \
  --name dqe-standalone \
  --query "containers[].{Name:name, State:instanceView.currentState.state}" \
  -o table

Résultat attendu :

Name        State
--------    -------
nginx       Running
redis       Running
postgres    Running
dqeone      Running

Remarque : l'ACI démarre tous les conteneurs simultanément. Le mécanisme WAIT_HOSTS gère l'ordre de démarrage en réessayant la connexion. Un délai de 1 à 2 minutes avant que l'application soit pleinement opérationnelle est normal au premier démarrage.

Une fois tous les conteneurs en cours d'exécution et le DNS propagé, accédez à https://standalone.yourdomain.com.

4. Adresses IP à autoriser

Une fois l'application en cours d'exécution, configurez le WAF ou le pare-feu en amont pour autoriser les plages IP entrantes suivantes :

  • DQE Software Office Server : contactez le support DQE Software pour obtenir l'adresse IP à autoriser.
  • DQE Deduplication Service : contactez le support DQE Software pour obtenir l'adresse IP à autoriser.
  • DQE Quality Service : contactez le support DQE Software pour obtenir l'adresse IP à autoriser.

Action requise : fournissez à DQE Software l'adresse IP publique sortante utilisée par votre infrastructure Azure (NAT Gateway, Azure Firewall, ou équivalent) afin qu'elle puisse être autorisée sur les services DQE.

5. Dépannage

Consulter les logs des conteneurs

Les logs des conteneurs sont disponibles dans Azure Monitor sous la table ContainerInstanceLog_CL. Vous pouvez également les récupérer directement via la CLI :

az container logs \
  --resource-group MY_RESOURCE_GROUP \
  --name dqe-standalone \
  --container-name CONTAINER_NAME

Erreur unauthorized lors du téléchargement des images

Vérifiez que :

  • la section imageRegistryCredentials contient le bon login et mot de passe fournis par DQE ;
  • toutes les images référencent le registre de production DQE dqeone.azurecr.io ;
  • les versions d'images correspondent à celles fournies par DQE.

Le conteneur PostgreSQL ne démarre pas

Les partages de fichiers Azure utilisent le protocole SMB, qui peut ne pas prendre en charge les opérations de système de fichiers POSIX requises par PostgreSQL. Si le conteneur postgres redémarre en boucle avec des erreurs de permission, utilisez Azure Database for PostgreSQL — Flexible Server à la place :

  • Supprimez le conteneur postgres et le volume postgresdata du YAML.
  • Définissez DB_HOST sur le nom d'hôte du serveur managé (par exemple : myserver.postgres.database.azure.com).
  • Mettez à jour DB_USER, DB_PASSWORD et DB_NAME pour correspondre aux identifiants du serveur managé.

La sonde d'intégrité de l'Application Gateway échoue

Vérifiez que :

  • tous les conteneurs ACI affichent l'état Running ;
  • le pool de backends contient la bonne adresse IP privée de l'ACI ;
  • le sous-réseau est correctement délégué à Microsoft.ContainerInstance/containerGroups ;
  • le NSG associé au sous-réseau autorise le trafic entrant sur le port 80 depuis le sous-réseau de l'Application Gateway.

Cet article vous a-t-il été utile ?

Utilisateurs qui ont trouvé cela utile : 0 sur 0