Despliegue DQE One Standalone como un grupo autónomo de Azure Container Instance (ACI) con NGINX, Redis y PostgreSQL, expuesto a través de un Application Gateway.
Nota: todos los elementos descritos a continuación son recomendaciones de DQE, basadas en la experiencia de despliegue con distintos clientes. El cliente es responsable de integrar la solución en su propia arquitectura. Un arquitecto familiarizado con el contexto del cliente y la infraestructura interna debe alinear las recomendaciones de DQE con la infraestructura del cliente.
1. Arquitectura
Este documento describe cómo desplegar el backend de DQE One Standalone como un grupo de contenedores de Azure Container Instance (ACI). Todos los contenedores del grupo comparten el mismo espacio de nombres de red y se comunican a través de localhost. Un Application Gateway expone la aplicación mediante HTTPS y enruta el tráfico hacia el ACI a través de una VNET privada.
Arquitectura recomendada
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)Medidas de seguridad
- Application Gateway: termina el tráfico HTTPS y lo enruta hacia el ACI a través de la VNET privada. Utilice el WAF para restringir los rangos de IP entrantes.
- VNET: aísla el ACI del acceso directo a internet público. Todo el tráfico proveniente del Application Gateway pasa a través de una subred privada.
- Certificado SSL: gestionado a nivel del Application Gateway o a nivel de NGINX dentro del ACI.
-
Secretos: utilice
secureValueen el YAML del grupo de contenedores para todos los valores sensibles (contraseñas, claves de licencia, claves de cifrado).
Dimensionamiento recomendado
| Contenedor | CPU | Memoria |
|---|---|---|
nginx |
0.25 vCPU | 0.5 GB |
redis |
0.5 vCPU | 1.0 GB |
postgres |
0.5 vCPU | 1.0 GB |
dqeone |
1.0 vCPU | 2.0 GB |
| Total | 2.25 vCPU | 4.5 GB |
Los grupos de contenedores ACI están limitados a 4 vCPU y 16 GB de memoria por grupo.
2. Instalación
2.1. Azure CLI
Azure CLI debe estar instalado en su máquina local.
Linux / macOS
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bashWindows
Consulte la documentación de Microsoft.
2.2. Crear un Application Gateway
El Application Gateway expone el ACI con una dirección IP pública y un nombre DNS. También gestiona la terminación HTTPS y el filtrado de IP mediante el WAF.
Para obtener información completa sobre la configuración, consulte la documentación de Microsoft Application Gateway.
Pestaña Basic
Seleccione su suscripción, grupo de recursos y región. Elija el nivel WAF V2 para habilitar el Web Application Firewall.
Política WAF
Cree una nueva política WAF desde el campo WAF policy. Utilice el WAF para definir los rangos de IP entrantes autorizados a llamar al Application Gateway (por ejemplo, su red corporativa o rangos de IP específicos de socios).
VNET
Cree una nueva red virtual (VNET) desde el campo Virtual network. Esta VNET conecta el Application Gateway con el ACI. Todo el tráfico entre ambos pasa a través de esta red privada.
Frontends
Cree una nueva dirección IP pública. Esta es la dirección IP expuesta externamente y utilizada para enrutar el tráfico hacia el ACI.
Backends
Cree un nuevo grupo de backend. Déjelo vacío por ahora — la dirección IP privada del ACI se añade después de que este haya sido desplegado (sección 3.3).
Configuración — Reglas de enrutamiento
Cree una regla de enrutamiento con:
- Listener: HTTPS en el puerto 443, con su certificado SSL.
- Backend target: el grupo de backend creado anteriormente.
- Backend setting: HTTP en el puerto 80 (el tráfico entre el Application Gateway y el ACI viaja a través de la VNET privada y no requiere HTTPS internamente).
Haga clic en Review + create para desplegar el Application Gateway.
2.3. Añadir una subred VNET para el ACI
En la VNET creada en la sección 2.2, cree una nueva subred dedicada al ACI. Delegue esta subred a Microsoft.ContainerInstance/containerGroups.
Anote el ID de recurso completo de la subred — es necesario en el YAML del grupo de contenedores:
/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME2.4. Configurar Azure Storage
Los contenedores ACI utilizan Azure File Shares para el almacenamiento persistente. Cree una cuenta de almacenamiento y, a continuación, cree los siguientes recursos compartidos de archivos:
| Recurso compartido de archivos | Propósito |
|---|---|
nginxconf |
Archivos de configuración de NGINX y certificado SSL |
redisdata |
Datos persistentes de Redis |
postgresdata |
Directorio de datos de PostgreSQL |
Paso 1 — Crear la cuenta de almacenamiento:
az storage account create \
--name MY_STORAGE_ACCOUNT \
--resource-group MY_RESOURCE_GROUP \
--location MY_LOCATION \
--sku Standard_LRSPaso 2 — Recuperar la clave de la cuenta de almacenamiento:
az storage account keys list \
--account-name MY_STORAGE_ACCOUNT \
--resource-group MY_RESOURCE_GROUP \
--query "[0].value" -o tsvPaso 3 — Crear los recursos compartidos de archivos:
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_ACCOUNTNota sobre el almacenamiento de PostgreSQL: Azure File Shares utiliza el protocolo SMB, que puede no admitir todas las operaciones del sistema de archivos POSIX requeridas por PostgreSQL. Si el contenedor postgres no logra iniciarse, consulte la sección 5 para conocer la alternativa recomendada utilizando Azure Database for PostgreSQL.
2.5. Crear un Log Analytics Workspace
Un Log Analytics workspace centraliza los registros de los contenedores y permite la supervisión mediante Azure Monitor. Los registros se almacenan durante 30 días de forma predeterminada.
Paso 1 — Crear el workspace:
az monitor log-analytics workspace create \
--resource-group MY_RESOURCE_GROUP \
--workspace-name dqe-standalone-logs \
--location MY_LOCATIONPaso 2 — Recuperar el Workspace ID:
az monitor log-analytics workspace show \
--resource-group MY_RESOURCE_GROUP \
--workspace-name dqe-standalone-logs \
--query customerId -o tsvPaso 3 — Recuperar la Workspace Primary Key:
az monitor log-analytics workspace get-shared-keys \
--resource-group MY_RESOURCE_GROUP \
--workspace-name dqe-standalone-logs \
--query primarySharedKey -o tsvConserve el Workspace ID y la Primary Key — se necesitan en el YAML del grupo de contenedores (sección 2.7).
2.6. Configurar NGINX
NGINX actúa como proxy inverso dentro del grupo de contenedores ACI, reenviando las solicitudes entrantes al contenedor dqeone en el puerto 8000. Dado que todos los contenedores de un grupo ACI comparten el mismo espacio de nombres de red, el destino del proxy utiliza localhost.
Cree un archivo llamado default.conf con el siguiente contenido:
server {
listen 80;
location / {
proxy_pass http://localhost:8000;
proxy_read_timeout 300s;
}
}Si el HTTPS se gestiona directamente a nivel del ACI (sin la descarga SSL del Application Gateway), añada un segundo bloque server para el puerto 443 y cargue los archivos de certificado SSL y clave en el recurso compartido de archivos nginxconf, bajo un subdirectorio ssl/.
Cargue default.conf en el recurso compartido de archivos nginxconf:
az storage file upload \
--account-name MY_STORAGE_ACCOUNT \
--share-name nginxconf \
--source ./default.conf \
--path default.conf2.7. YAML del grupo de contenedores
Cree un archivo llamado container-group.yaml. Reemplace todos los marcadores de posición antes de desplegar. La siguiente tabla enumera todos los valores necesarios.
| Marcador de posición | Descripción |
|---|---|
MY_LOCATION |
Región de Azure, por ejemplo westeurope
|
DQE_REGISTRY_LOGIN |
Nombre de usuario del registro proporcionado por DQE |
DQE_REGISTRY_PASSWORD |
Contraseña del registro proporcionada por DQE |
MY_STORAGE_ACCOUNT |
Nombre de la cuenta de almacenamiento creada en la sección 2.4 |
MY_STORAGE_ACCOUNT_KEY |
Clave de la cuenta de almacenamiento recuperada en el Paso 2 de la sección 2.4 |
LOG_ANALYTICS_WORKSPACE_ID |
Workspace ID recuperado en el Paso 2 de la sección 2.5 |
LOG_ANALYTICS_WORKSPACE_KEY |
Primary Key recuperada en el Paso 3 de la sección 2.5 |
SUBNET_RESOURCE_ID |
ID de recurso completo de la subred anotado en la sección 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_IDImportante: utilice las versiones de imagen proporcionadas por DQE. No las reemplace con la etiqueta latest.
Nota clave sobre redes en ACI: todos los contenedores comparten el mismo espacio de nombres de red. La comunicación entre contenedores utiliza localhost — por eso REDIS_URL es redis://localhost:6379 y DB_HOST es localhost, a diferencia de una configuración de Docker Compose donde se utilizan los nombres de servicio.
2.8. Variables de entorno
| Variable | Valor de ejemplo | Descripción |
|---|---|---|
SFAPIVERSION |
v65.0 |
Versión de la API de Salesforce utilizada por la aplicación. |
CREATE_SUPERUSER |
true |
Crea la cuenta de administrador inicial durante el primer inicio. |
RUN_COLLECTSTATIC |
false |
Ejecuta el comando collectstatic de Django durante el inicio. Configúrelo en false a menos que sea explícitamente necesario. |
DQE_ONE_SERVER_ADMIN_USER |
— | Nombre de usuario de la cuenta de administrador inicial. |
DQE_ONE_SERVER_ADMIN_PASSWORD |
— | Contraseña de la cuenta de administrador inicial. Utilice secureValue. |
DQE_CLIENT_LICENCE |
— | Clave de licencia del cliente proporcionada por DQE. |
WEBSITE_HOSTNAME |
https://myapp.example.com |
URL HTTPS pública. Debe coincidir con el nombre DNS que apunta al Application Gateway. |
SECRET_ENCRYPTION_KEY |
— | Clave de cifrado para datos sensibles. Genérela una vez, nunca la cambie después del despliegue. Utilice secureValue. |
WAIT_HOSTS |
localhost:6379 |
Servicio que se debe esperar antes de iniciar. Utiliza localhost en ACI. |
WAIT_HOSTS_TIMEOUT |
300 |
Tiempo máximo de espera, en segundos, para los servicios dependientes. |
WAIT_SLEEP_INTERVAL |
5 |
Retraso, en segundos, entre comprobaciones de disponibilidad. |
WAIT_HOST_CONNECT_TIMEOUT |
30 |
Tiempo de espera, en segundos, para cada intento de conexión. |
REDIS_URL |
redis://localhost:6379 |
URL de conexión de Redis. Utiliza localhost en ACI. |
PORT |
8000 |
Puerto de escucha interno de la aplicación. |
DEBUG |
false |
Modo de depuración. Debe ser false en producción. |
DB_USER |
dqeone |
Nombre de usuario de PostgreSQL. |
DB_PASSWORD |
— | Contraseña de PostgreSQL. Debe coincidir con POSTGRES_PASSWORD en el contenedor postgres. Utilice secureValue. |
DB_NAME |
dqeone |
Nombre de la base de datos PostgreSQL. |
DB_HOST |
localhost |
Nombre de host de PostgreSQL. Utiliza localhost en ACI. Configúrelo con el nombre de host del servidor gestionado si utiliza Azure Database for PostgreSQL. |
DB_VOLUME_PATH |
./db/ |
Ruta para el almacenamiento relacionado con la base de datos. |
DB_MAX_CAPACITY |
8000000000 |
Capacidad máxima de la base de datos, en bytes. |
AUTHORIZED_SFTP_HOSTS |
depot-1.dqe-software.net |
Lista separada por comas de hosts SFTP autorizados. |
Importante: la SECRET_ENCRYPTION_KEY debe generarse una vez y conservarse durante toda la vida del despliegue. Para generar una clave compatible:
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"3. Lanzador
3.1. Iniciar sesión en Azure
az login3.2. Desplegar el grupo de contenedores
az container create -g MY_RESOURCE_GROUP -f container-group.yamlUna vez finalizada la operación, recupere la dirección IP privada asignada al grupo de contenedores:
az container show \
--resource-group MY_RESOURCE_GROUP \
--name dqe-standalone \
--query "ipAddress.ip" -o tsvEsta dirección IP privada solo es accesible desde dentro de la VNET de Azure.
3.3. Configurar el grupo de backend del Application Gateway
Una vez desplegado el ACI, vaya a Azure Portal > Application Gateway > Backend pools > su grupo de backend > Edit.
Añada la dirección IP privada del ACI recuperada en el paso 3.2. Haga clic en Save.
3.4. Configurar la sonda de estado (health probe) del Application Gateway
La sonda de estado permite al Application Gateway verificar que la aplicación esté en ejecución. Vaya a Azure Portal > Application Gateway > Health probes > Add.
Configure la sonda para llamar a la ruta raíz de la aplicación mediante HTTP. Haga clic en Test. Si el estado muestra Healthy, el ACI está correctamente configurado y el Application Gateway puede enrutar el tráfico hacia él.
Haga clic en Add para guardar la sonda de estado.
3.5. Configurar el DNS
Contacte con sus administradores DNS para crear un registro DNS que apunte a la dirección IP pública del Application Gateway:
| Tipo de registro | Nombre | Valor |
|---|---|---|
| A | standalone.yourdomain.com |
IP pública del Application Gateway |
3.6. Verificar la instalación
Compruebe que todos los contenedores estén en ejecución:
az container show \
--resource-group MY_RESOURCE_GROUP \
--name dqe-standalone \
--query "containers[].{Name:name, State:instanceView.currentState.state}" \
-o tableSalida esperada:
Name State
-------- -------
nginx Running
redis Running
postgres Running
dqeone RunningNota: ACI inicia todos los contenedores simultáneamente. El mecanismo WAIT_HOSTS gestiona el orden de arranque reintentando la conexión. Se espera un retraso de 1 a 2 minutos antes de que la aplicación esté completamente operativa en el primer inicio.
Una vez que todos los contenedores estén en ejecución y el DNS se haya propagado, navegue a https://standalone.yourdomain.com.
4. Direcciones IP a autorizar
Una vez que la aplicación esté en ejecución, configure el WAF o el firewall superior para autorizar los siguientes rangos de IP entrantes:
- DQE Software Office Server: póngase en contacto con el soporte de DQE Software para obtener la dirección IP a autorizar.
- DQE Deduplication Service: póngase en contacto con el soporte de DQE Software para obtener la dirección IP a autorizar.
- DQE Quality Service: póngase en contacto con el soporte de DQE Software para obtener la dirección IP a autorizar.
Acción requerida: proporcione a DQE Software la dirección IP pública saliente utilizada por su infraestructura de Azure (NAT Gateway, Azure Firewall o equivalente) para que pueda ser autorizada en los servicios de DQE.
5. Solución de problemas
Ver los registros de los contenedores
Los registros de los contenedores están disponibles en Azure Monitor bajo la tabla ContainerInstanceLog_CL. También puede recuperarlos directamente mediante la CLI:
az container logs \
--resource-group MY_RESOURCE_GROUP \
--name dqe-standalone \
--container-name CONTAINER_NAMENo autorizado al descargar imágenes
Verifique que:
- la sección
imageRegistryCredentialscontenga el usuario y la contraseña correctos proporcionados por DQE; - todas las imágenes hagan referencia al registro de producción de DQE
dqeone.azurecr.io; - las versiones de imagen coincidan con las proporcionadas por DQE.
El contenedor de PostgreSQL no logra iniciarse
Azure File Shares utiliza el protocolo SMB, que puede no admitir las operaciones del sistema de archivos POSIX requeridas por PostgreSQL. Si el contenedor postgres se reinicia repetidamente con errores de permisos, utilice en su lugar Azure Database for PostgreSQL — Flexible Server:
- Elimine el contenedor
postgresy el volumenpostgresdatadel YAML. - Configure
DB_HOSTcon el nombre de host del servidor gestionado (por ejemplo:myserver.postgres.database.azure.com). - Actualice
DB_USER,DB_PASSWORDyDB_NAMEpara que coincidan con las credenciales del servidor gestionado.
La sonda de estado del Application Gateway falla
Verifique que:
- todos los contenedores del ACI muestren el estado
Running; - el grupo de backend contenga la dirección IP privada correcta del ACI;
- la subred esté correctamente delegada a
Microsoft.ContainerInstance/containerGroups; - el NSG asociado a la subred permita el tráfico entrante en el puerto 80 desde la subred del Application Gateway.