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
secureValuedans 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 bashWindows
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_NAME2.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_ACCOUNTRemarque 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 tsvConservez 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.conf2.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_IDImportant : 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 login3.2. Déployer le groupe de conteneurs
az container create -g MY_RESOURCE_GROUP -f container-group.yamlUne 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 tsvCette 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 tableRésultat attendu :
Name State
-------- -------
nginx Running
redis Running
postgres Running
dqeone RunningRemarque : 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_NAMEErreur unauthorized lors du téléchargement des images
Vérifiez que :
- la section
imageRegistryCredentialscontient 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
postgreset le volumepostgresdatadu YAML. - Définissez
DB_HOSTsur le nom d'hôte du serveur managé (par exemple :myserver.postgres.database.azure.com). - Mettez à jour
DB_USER,DB_PASSWORDetDB_NAMEpour 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.