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 and Docker Hub |
1.2 Authenticate to DQE Container Registry
The DQE Unify images 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.5) 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_LRSStep 2 — Retrieve the storage account key:
az storage account keys list \ --account-name dqeunifystorage \ --resource-group <resource-group> \ --query "[0].value" -o tsvStep 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 (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 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 (e.g. 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 |
apiVersion: 2021-10-01
name: dqe-unify
location: <location>
type: Microsoft.ContainerInstance/containerGroups
properties:
imageRegistryCredentials:
- server: <registry-url>
username: <Username provided by DQE>
password: <Password provided by DQE>
osType: Linux
restartPolicy: Always
ipAddress:
type: Public
ports:
- protocol: tcp
port: 80
- protocol: tcp
port: 443
volumes:
- name: redisvol
azureFile:
shareName: redisvol
storageAccountName: dqeunifystorage
storageAccountKey: <storage-account-key>
- name: rabbitvol
azureFile:
shareName: rabbitvol
storageAccountName: dqeunifystorage
storageAccountKey: <storage-account-key>
- name: nginxconf
azureFile:
shareName: nginxconf
storageAccountName: dqeunifystorage
storageAccountKey: <storage-account-key>
containers:
# ── Redis ──────────────────────────────────────────────
- name: redis
properties:
image: redis:alpine
resources:
requests:
cpu: 0.5
memoryInGb: 0.5
volumeMounts:
- name: redisvol
mountPath: /data
# ── RabbitMQ ───────────────────────────────────────────
- name: rabbitmq
properties:
image: rabbitmq:3.13-management
resources:
requests:
cpu: 0.5
memoryInGb: 1
ports:
- port: 5672
environmentVariables:
- name: RABBITMQ_DEFAULT_USER
value: user
- name: RABBITMQ_DEFAULT_PASS
value: bitnami
volumeMounts:
- name: rabbitvol
mountPath: /var/lib/rabbitmq
# ── Nginx reverse proxy ────────────────────────────────
- name: nginx
properties:
image: nginx:latest
resources:
requests:
cpu: 0.5
memoryInGb: 0.5
ports:
- port: 80
- port: 443
volumeMounts:
- name: nginxconf
mountPath: /etc/nginx/conf.d
# ── Unify Server (web) ─────────────────────────────────
- name: unify-server
properties:
image: <registry-url>/unify-server-web-ms-dynamics:v3.0
command:
- python
- app.pyc
resources:
requests:
cpu: 0.5
memoryInGb: 1
ports:
- port: 8000
environmentVariables:
- name: REDIS_URL
value: redis://localhost:6379
- name: CLOUDAMQP_URL
value: amqp://user:bitnami@localhost:5672/
- name: PORT
value: "8000"
# ── Queue Worker ───────────────────────────────────────
- name: queue-worker
properties:
image: <registry-url>/unify-server-web-ms-dynamics:v3.0
command:
- python
- queue_worker.pyc
resources:
requests:
cpu: 1.0
memoryInGb: 5
environmentVariables:
- name: REDIS_URL
value: redis://localhost:6379
- name: CLOUDAMQP_URL
value: amqp://user:bitnami@localhost:5672/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
/(default).
1.6 Deploy the Application
Step 1 — Deploy the Container Group:
az container create \ --resource-group <resource-group> \ --file container-group.yamlStep 2 — Check the deployment status:
az container show \ --resource-group <resource-group> \ --name dqe-unify \ --query "instanceView.state" -o tsvExpected output:
RunningStep 3 — Retrieve the public IP address:
az container show \ --resource-group <resource-group> \ --name dqe-unify \ --query "ipAddress.ip" -o tsvStep 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.7 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 to
80,443. - Set Protocol to
TCP, 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:
https://www.microsoft.com/en-us/download/details.aspx?id=56519
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 port 443. Alternatively, set Source to Service Tag and select Dynamics365 directly in the NSG rule.
1.8 Setup DNS
Contact your DNS administrators and ask them to create an A record pointing to the public IP address of the Container Instance (retrieved in section 1.6 Step 3).
| Record Type | Name | Value |
|---|---|---|
| A | unify.yourdomain.com | Public IP address 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.9 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://<public-ip>
curl http://<public-ip>:8000Expected 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: Have your SI/network team authorize the Container Instance's public IP on DQE Software's side as well. Provide DQE with the outbound public IP of the ACI group.
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:
https://www.microsoft.com/en-us/download/details.aspx?id=56519
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