Microsoft ACI - Backend server installation

Support DQE
Support DQE

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

ContainerCPU (vCores)Memory
redis0.50.5 GB
rabbitmq0.51 GB
nginx0.50.5 GB
unify-server0.51 GB
queue-worker1.05 GB
Total3.08 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

SoftwareVersion / Notes
Azure CLILatest stable — az command available in terminal
Azure SubscriptionActive subscription with permissions to create Container Instances and Storage Accounts
Internet accessRequired 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.

  1. Step 1 — Create a Storage Account:

    az storage account create \
      --name dqeunifystorage \
      --resource-group <resource-group> \
      --location <location> \
      --sku Standard_LRS
  2. Step 2 — Retrieve the storage account key:

    az storage account keys list \
      --account-name dqeunifystorage \
      --resource-group <resource-group> \
      --query "[0].value" -o tsv
  3. 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 (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.conf

HTTPS

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.

PlaceholderDescription
<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_URL and CLOUDAMQP_URL use localhost instead of redis and rabbitmq.
  • The image unify-server-web-ms-dynamics:v3.0 contains compiled Python bytecode — the entry point is app.pyc, not app.py.
  • RabbitMQ uses the official image with credentials set via environment variables. The virtual host is / (default).

1.6 Deploy the Application

  1. Step 1 — Deploy the Container Group:

    az container create \
      --resource-group <resource-group> \
      --file container-group.yaml
  2. Step 2 — Check the deployment status:

    az container show \
      --resource-group <resource-group> \
      --name dqe-unify \
      --query "instanceView.state" -o tsv

    Expected output: Running

  3. Step 3 — Retrieve the public IP address:

    az container show \
      --resource-group <resource-group> \
      --name dqe-unify \
      --query "ipAddress.ip" -o tsv
  4. 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 table

    Expected 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.

  1. Go to Azure Portal → Network Security Groups → [Your NSG] → Inbound security rules.
  2. Click Add.
  3. Set Destination port ranges to 80,443.
  4. Set Protocol to TCP, Action to Allow.
  5. 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 TypeNameValue
Aunify.yourdomain.comPublic 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.com

You can also test directly using the public IP:

curl http://<public-ip>
curl http://<public-ip>:8000

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: 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

Was this article helpful?

0 out of 0 found this helpful