1. Installation
This section describes the deployment of DQE Unify Server on Azure Container Instances (ACI). The application stack — Redis, RabbitMQ, Nginx, Unify Server, and Queue Worker — runs as a single Azure Container Group. All containers share the same network namespace and communicate via localhost.
1.1 Prerequisites
1.1.1 Resource Requirements
| Container | CPU (vCores) | Memory |
|---|---|---|
| redis | 0.5 | 0.5 GB |
| rabbitmq | 0.5 | 1 GB |
| nginx | 0.5 | 0.5 GB |
| unify-server | 0.5 | 1 GB |
| queue-worker | 1.0 | 5 GB |
| Total | 3.0 | 8 GB |
Note: Estimates are based on 1 million records. Depending on data volume, you may need to increase the memory allocation of the queue-worker container.
1.1.2 Software Requirements
| Software | Version / Notes |
|---|---|
| Azure CLI | Latest stable — az command available in terminal |
| Azure Subscription | Active subscription with permissions to create Container Instances and Storage Accounts |
| Internet access | Required to pull images from DQE Container Registry |
1.2 Authenticate to DQE Container Registry
All images (DQE Unify, Redis, RabbitMQ, Nginx) are hosted on a private Azure Container Registry. Use the credentials provided by DQE Software to log in from your local terminal:
az login
docker login <registry-url> --username <Username provided by DQE> --password <Password provided by DQE>A successful login displays: Login Succeeded.
Note: The registry credentials are also required in the Container Group YAML file (section 1.6) so that ACI can pull the images at deploy time.
1.3 Configure Azure Storage
Azure Container Instances do not support local bind mounts. Persistent data for Redis and RabbitMQ must be stored in Azure File Shares. The Nginx configuration file is also uploaded to a file share so the container can mount it at runtime.
-
Step 1 — Create a Storage Account:
az storage account create \ --name dqeunifystorage \ --resource-group <resource-group> \ --location <location> \ --sku Standard_LRS -
Step 2 — Retrieve the storage account key:
az storage account keys list \ --account-name dqeunifystorage \ --resource-group <resource-group> \ --query "[0].value" -o tsv -
Step 3 — Create the file shares:
az storage share create --name redisvol --account-name dqeunifystorage az storage share create --name rabbitvol --account-name dqeunifystorage az storage share create --name nginxconf --account-name dqeunifystorage
1.4 Configure Nginx
Nginx acts as a reverse proxy, forwarding incoming HTTP/HTTPS requests to the Unify Server. In ACI, all containers share the same network namespace, so the proxy target is http://localhost:8000 and not a service name.
Create the file default.conf locally, then upload it to the Azure File Share.
The file default.conf must contain:
server {
listen 80;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 300s;
}
}Upload to the Azure File Share:
az storage file upload \
--account-name dqeunifystorage \
--share-name nginxconf \
--source ./default.conf \
--path default.confHTTPS
Add a second server block and upload your SSL certificate and private key to the nginxconf file share. Update the Container Group YAML to expose port 443.
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/cert.crt;
ssl_certificate_key /etc/nginx/ssl/cert.key;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 300s;
}
}Note: Upload certificate files to the nginxconf file share under an ssl/ subdirectory, and mount the share at /etc/nginx/ssl in the Nginx container configuration.
1.5 Configure Log Analytics Workspace
A Log Analytics workspace centralizes container logs and enables monitoring through Azure Monitor. The workspace ID and key are referenced in the Container Group YAML (section 1.6).
-
Step 1 — Create a Log Analytics workspace:
az monitor log-analytics workspace create \ --resource-group <resource-group> \ --workspace-name dqe-unify-logs \ --location <location> -
Step 2 — Retrieve the Workspace ID:
az monitor log-analytics workspace show \ --resource-group <resource-group> \ --workspace-name dqe-unify-logs \ --query customerId -o tsv -
Step 3 — Retrieve the Workspace Primary Key:
az monitor log-analytics workspace get-shared-keys \ --resource-group <resource-group> \ --workspace-name dqe-unify-logs \ --query primarySharedKey -o tsv
Note: Keep the Workspace ID and Primary Key at hand — they are used as placeholders <workspace-id> and <workspace-key> in the Container Group YAML (section 1.6).
1.6 Container Group Configuration File
Create the file container-group.yaml with the content below. Replace all placeholders in angle brackets before deploying.
| Placeholder | Description |
|---|---|
<resource-group> |
Azure Resource Group name |
<location> |
Azure region, for example westeurope
|
<registry-url> |
DQE Container Registry URL |
<Username provided by DQE> |
Registry username given by DQE Software |
<Password provided by DQE> |
Registry password given by DQE Software |
<storage-account-key> |
Key retrieved in section 1.3 Step 2 |
<workspace-id> |
Log Analytics Workspace ID (retrieved in section 1.5 Step 2) |
<workspace-key> |
Log Analytics Workspace Primary Key (retrieved in section 1.5 Step 3) |
name: dqe-unify-aci
apiVersion: '2021-10-01'
location: <azure-region>
tags:
docker-compose-application: docker-compose-application
properties:
containers:
- name: redis
properties:
image: <registry-url>/dqe-unify-redis:latest
resources:
requests:
memoryInGB: 1
cpu: 0.5
volumeMounts:
- name: redisvol
mountPath: /data
- name: rabbitmq
properties:
image: <registry-url>/dqe-unify-rabbitmq:latest
ports:
- protocol: TCP
port: 5672
resources:
requests:
memoryInGB: 1
cpu: 1
volumeMounts:
- name: rabbitvol
mountPath: /bitnami
readOnly: false
- name: nginx
properties:
image: <registry-url>/dqe-unify-nginx:latest
ports:
- protocol: TCP
port: 80
resources:
requests:
memoryInGB: 1
cpu: 0.25
volumeMounts:
- name: nginxconf
mountPath: /etc/nginx/conf.d
- name: unify-server
properties:
image: <registry-url>/unify-server-web-ms-dynamics:<version>
command: ["python", "-u", "app.pyc"]
ports:
- protocol: TCP
port: 8000
environmentVariables:
- name: REDIS_URL
value: redis://127.0.0.1:6379
- name: CLOUDAMQP_URL
value: amqp://guest:guest@127.0.0.1:5672/
- name: PORT
value: 8000
resources:
requests:
memoryInGB: 1
cpu: 0.25
- name: queue-worker
properties:
image: <registry-url>/unify-server-web-ms-dynamics:<version>
command: ["python", "-u", "queue_worker.pyc"]
environmentVariables:
- name: REDIS_URL
value: redis://127.0.0.1:6379
- name: CLOUDAMQP_URL
value: amqp://guest:guest@127.0.0.1:5672/
resources:
requests:
memoryInGB: 5
cpu: 1
imageRegistryCredentials:
- server: <registry-url>
username: <registry-username>
password: <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: rabbitvol
azureFile:
shareName: rabbitvol
readOnly: false
storageAccountName: <storage-account-name>
storageAccountKey: <storage-account-key>
- name: nginxconf
azureFile:
shareName: nginxconf
readOnly: false
storageAccountName: <storage-account-name>
storageAccountKey: <storage-account-key>
- name: redisvol
azureFile:
shareName: redisvol
readOnly: false
storageAccountName: <storage-account-name>
storageAccountKey: <storage-account-key>
subnetIds:
- id: /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Network/virtualNetworks/<vnet-name>/subnets/<subnet-name>Key configuration notes:
- All containers in an ACI Container Group share the same network namespace — services communicate via
localhost, not via service names. - The
REDIS_URLandCLOUDAMQP_URLuselocalhostinstead ofredisandrabbitmq. - The image
unify-server-web-ms-dynamics:v3.0contains compiled Python bytecode — the entry point isapp.pyc, notapp.py. - RabbitMQ uses the official image with credentials set via environment variables. The virtual host is
/by default. - The
diagnostics.logAnalyticsblock routes all container stdout/stderr to the Log Analytics workspace. Logs appear in Azure Monitor under theContainerInstanceLog_CLtable within a few minutes of deployment.
1.7 Deploy the Application
-
Step 1 — Deploy the Container Group:
az container create \ --resource-group <resource-group> \ --file container-group.yaml -
Step 2 — Check the deployment status:
az container show \ --resource-group <resource-group> \ --name dqe-unify \ --query "instanceView.state" -o tsvExpected output:
Running. -
Step 3 — Retrieve the private IP address assigned to the Container Group:
az container show \ --resource-group <resource-group> \ --name dqe-unify \ --query "ipAddress.ip" -o tsvThe returned IP address is reachable only from the Azure Virtual Network or from connected networks.
-
Step 4 — Verify all containers are running:
az container show \ --resource-group <resource-group> \ --name dqe-unify \ --query "containers[].{Name:name, State:instanceView.currentState.state}" \ -o tableExpected output: all containers should show state
Running:Name State ----------- ------- redis Running rabbitmq Running nginx Running unify-server Running queue-worker Running
Important: If any container shows state Terminated or Waiting, check its logs immediately: az container logs --resource-group <rg> --name dqe-unify --container-name <service-name>.
Note: ACI starts all containers simultaneously. RabbitMQ and Redis may take a few seconds to be ready. The Unify Server will automatically retry the connection on startup.
1.8 Configure Network Security Group (NSG)
If the Container Instance is deployed in an Azure Virtual Network, configure the associated NSG to allow inbound traffic on the required ports.
- Go to Azure Portal → Network Security Groups → [Your NSG] → Inbound security rules.
- Click Add.
- Set Destination port ranges : 80. If HTTPS is enabled through an external reverse proxy or Application Gateway, additional rules may be required.
- Set Protocol to
TCPand Action toAllow. - Click Add.
Note: Port 8000 (Unify Server) and port 5672 (RabbitMQ) are internal to the Container Group and do not need to be exposed externally.
Dynamics 365 — Authorize Inbound IP Ranges
The DQE Unify Server receives requests from Microsoft Dynamics 365, which runs on Azure infrastructure. You must authorize the corresponding Azure IP ranges in the NSG.
The full and up-to-date list of Microsoft Azure IP ranges is available for download at:
Microsoft Azure IP Ranges and Service Tags
Download the JSON file, identify the Dynamics365 and AzureCloud service tags relevant to your region, and add the corresponding IP ranges as inbound allow rules on the port exposed by the reverse proxy or Application Gateway (typically port 80 or 443 depending on the infrastructure configuration). Alternatively, set Source to Service Tag and select Dynamics365 directly in the NSG rule.
1.9 Set Up DNS
Contact your network or DNS administrators to create an internal DNS record pointing to the private IP address of the Container Group or to the hostname exposed by the reverse proxy/Application Gateway.
| Record Type | Name | Value |
|---|---|---|
| A | unify.yourdomain.com |
Private IP of the ACI Container Group |
Alternatively, you can assign a DNS name label directly to the Container Instance in Azure Portal: Azure Portal → Container Instances → [dqe-unify] → Overview → DNS name label. This gives a hostname of the form dqe-unify.<location>.azurecontainer.io.
1.10 Verify the Deployment
Once DNS propagates, open a browser and navigate to:
http://unify.yourdomain.comYou can also test directly using the public IP:
curl http://<private-ip>Expected response from the Unify Server:
{"status": "available"}If the application responds, the deployment is complete and the server is properly configured.
2. Application Set Up
Once the application is running, the NSG and any upstream firewall or proxy must be configured to allow the IP ranges listed below.
2.1 IP Addresses to Authorize
DQE Software Office Server
Contact DQE Software support to obtain the IP address to authorize.
DQE – Deduplication Service
Contact DQE Software support to obtain the IP address to authorize.
DQE – Quality Service
Contact DQE Software support to obtain the IP address to authorize.
Action required: Provide DQE Software with the outbound public IP address used by your Azure infrastructure (NAT Gateway, Azure Firewall or equivalent) so that it can be authorized on DQE services.
Azure IP Ranges — Dynamics 365 and Azure Services
The full and up-to-date list of Microsoft Azure IP ranges (IPv4 and IPv6) is available for download at:
Microsoft Azure IP Ranges and Service Tags
Download the JSON file and identify the service tags relevant to your region (Dynamics365, AzureCloud). Add the corresponding IP ranges to your NSG inbound rules.
Related to