DEV Community

Daniel Jonathan
Daniel Jonathan

Posted on Edited on

Dockerizing Azure Service Bus Emulator and Test with Logic Apps

Run Azure Logic Apps Standard with Service Bus Emulator completely in Docker - zero Azure resources needed.

This guide covers:

  • ๐Ÿณ Complete Docker setup with memory optimization
  • ๐Ÿ”ง Logic Apps configuration for Service Bus
  • ๐Ÿ“จ Queue and Topic messaging patterns
  • ๐ŸŽฏ SQL filters for message routing
  • โœ… Real working examples (wf4, wf5, wf6, wf7)

Why This Setup?

  • โšก Fast local development
  • ๐Ÿ’ธ Zero Azure costs
  • ๐Ÿ”Œ Works offline
  • ๐Ÿงช Safe testing environment
  • ๐Ÿ” Same behavior as Azure Service Bus
  • ๐Ÿณ Everything containerized

Prerequisites

Docker Memory Configuration

Critical: Service Bus Emulator requires significant memory.

Minimum Requirements:

  • Docker Desktop: 15-16GB RAM
  • Service Bus container: 8GB
  • SQL Server: 2GB

Configure Docker Desktop:

  1. Open Docker Desktop โ†’ Settings โ†’ Resources
  2. Set Memory to 15.6GB or higher
  3. Click Apply & Restart

Without sufficient memory, the Service Bus emulator will crash with Out of memory errors (exit code 133).


Project Structure

LADevStuff2/                      # Logic App project
โ”œโ”€โ”€ connections.json              # Service Bus connection config
โ”œโ”€โ”€ local.settings.json           # Connection strings
โ”œโ”€โ”€ wf4/
โ”‚   โ””โ”€โ”€ workflow.json             # Queue receiver
โ”œโ”€โ”€ wf5/
โ”‚   โ””โ”€โ”€ workflow.json             # Topic subscriber (TypeA filter)
โ”œโ”€โ”€ wf6/
โ”‚   โ””โ”€โ”€ workflow.json             # Topic subscriber (TypeB filter)
โ””โ”€โ”€ wf7_sb_send/
    โ””โ”€โ”€ workflow.json             # Message sender

DockerFiles/
โ”œโ”€โ”€ docker-compose.yml            # Container orchestration
โ””โ”€โ”€ ServiceBus/
    โ”œโ”€โ”€ Config.json               # Queue, Topic, Filters
    โ””โ”€โ”€ .env                      # SQL Server credentials
Enter fullscreen mode Exit fullscreen mode

Step 1: Service Bus Configuration

DockerFiles/ServiceBus/Config.json

This defines your Service Bus entities with SQL filters:

{
  "UserConfig": {
    "Namespaces": [
      {
        "Name": "sbemulatorns",
        "Queues": [
          {
            "Name": "local-orders-queue",
            "Properties": {
              "DeadLetteringOnMessageExpiration": false,
              "DefaultMessageTimeToLive": "PT1H",
              "LockDuration": "PT1M",
              "MaxDeliveryCount": 10,
              "RequiresDuplicateDetection": false,
              "RequiresSession": false
            }
          }
        ],
        "Topics": [
          {
            "Name": "local-orders-topic",
            "Properties": {
              "DefaultMessageTimeToLive": "PT1H",
              "RequiresDuplicateDetection": false
            },
            "Subscriptions": [
              {
                "Name": "local-orders-sub",
                "Properties": {
                  "DeadLetteringOnMessageExpiration": false,
                  "DefaultMessageTimeToLive": "PT1H",
                  "LockDuration": "PT1M",
                  "MaxDeliveryCount": 10,
                  "RequiresSession": false
                }
              },
              {
                "Name": "wf5-sub",
                "Properties": {
                  "DeadLetteringOnMessageExpiration": false,
                  "DefaultMessageTimeToLive": "PT1H",
                  "LockDuration": "PT1M",
                  "MaxDeliveryCount": 10,
                  "RequiresSession": false
                },
                "Rules": [
                  {
                    "Name": "TypeAFilter",
                    "Properties": {
                      "FilterType": "Sql",
                      "SqlFilter": {
                        "SqlExpression": "user.orderType = 'TypeA'"
                      }
                    }
                  }
                ]
              },
              {
                "Name": "wf6-sub",
                "Properties": {
                  "DeadLetteringOnMessageExpiration": false,
                  "DefaultMessageTimeToLive": "PT1H",
                  "LockDuration": "PT1M",
                  "MaxDeliveryCount": 10,
                  "RequiresSession": false
                },
                "Rules": [
                  {
                    "Name": "TypeBFilter",
                    "Properties": {
                      "FilterType": "Sql",
                      "SqlFilter": {
                        "SqlExpression": "user.orderType = 'TypeB'"
                      }
                    }
                  }
                ]
              }
            ]
          }
        ]
      }
    ],
    "Logging": {
      "Type": "File"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ’ก SQL Filter Syntax: Use user.propertyName for custom properties in filters.

DockerFiles/ServiceBus/.env

ACCEPT_EULA=Y
MSSQL_SA_PASSWORD=StrongPassword123!
Enter fullscreen mode Exit fullscreen mode

Step 2: Docker Compose Setup

DockerFiles/docker-compose.yml

services:
  # Azure Storage Emulator
  azurite:
    image: mcr.microsoft.com/azure-storage/azurite
    container_name: azurite-shared
    ports:
      - "10000:10000" # Blob
      - "10001:10001" # Queue
      - "10002:10002" # Table
    networks:
      - shared-network

  # SQL Server 2022 (Service Bus backend)
  mssql:
    container_name: mssql-shared
    image: mcr.microsoft.com/mssql/server:2022-latest
    platform: linux/amd64
    env_file:
      - ./ServiceBus/.env
    mem_limit: 2g
    memswap_limit: 2g
    networks:
      - shared-network

  # Service Bus Emulator
  servicebus-emulator:
    container_name: servicebus-emulator-shared
    platform: linux/amd64
    image: mcr.microsoft.com/azure-messaging/servicebus-emulator:latest
    pull_policy: always
    depends_on:
      - mssql
    volumes:
      - ./ServiceBus/Config.json:/ServiceBus_Emulator/ConfigFiles/Config.json
    ports:
      - "5672:5672" # AMQP
      - "5300:5300" # Management
    env_file:
      - ./ServiceBus/.env
    environment:
      SQL_SERVER: mssql
      ACCEPT_EULA: Y
    mem_limit: 8g
    memswap_limit: 8g
    shm_size: 2g
    networks:
      - shared-network

  # Logic App Container
  logicapp2:
    platform: linux/amd64
    build:
      context: ../LADevStuff2
    container_name: logicapp2
    ports:
      - "7072:7072"
    environment:
      AzureWebJobsStorage: "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite:10000/devstoreaccount1;QueueEndpoint=http://azurite:10001/devstoreaccount1;TableEndpoint=http://azurite:10002/devstoreaccount1"
      WORKFLOWS_STORAGE_PROVIDER: "AzureStorage"
      WORKFLOWS_STORAGE_CONNECTION_STRING: "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite:10000/devstoreaccount1;QueueEndpoint=http://azurite:10001/devstoreaccount1;TableEndpoint=http://azurite:10002/devstoreaccount1"
      FUNCTIONS_WORKER_RUNTIME: "node"
      AzureWebJobsFeatureFlags: "EnableMultiLanguageWorker"
      AzureWebJobsSecretStorageType: "Files"
      APP_KIND: "workflowapp"
      WEBSITE_SITE_NAME: "logicapp-local2"
    extra_hosts:
      - "localhost:host-gateway"
    depends_on:
      - azurite
      - servicebus-emulator
    networks:
      - shared-network

networks:
  shared-network:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

Key Configuration Notes:

  • mem_limit: 8g - Critical for Service Bus stability
  • platform: linux/amd64 - Required for Apple Silicon (ARM) Macs
  • extra_hosts: localhost:host-gateway - Enables Logic Apps to reach Service Bus emulator
  • MSSQL Server 2022 - Use this, not SQL Edge (SQL Edge causes crashes)

Step 3: Logic App Configuration

3.1 Connection String Setup

LADevStuff2/local.settings.json

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "servicebusconnection": "Endpoint=sb://localhost:5672;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"
  }
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”‘ Important: Use localhost:5672, not the container name, due to extra_hosts configuration.

3.2 Service Bus Connection

LADevStuff2/connections.json

โš ๏ธ Critical: You cannot create Service Bus connections in the Logic App Designer for queues and topics.

Workaround: Manually edit this file:

{
  "managedApiConnections": {},
  "serviceProviderConnections": {
    "serviceBus": {
      "parameterValues": {
        "connectionString": "@appsetting('servicebusconnection')"
      },
      "parameterSetName": "connectionString",
      "serviceProvider": {
        "id": "/serviceProviders/serviceBus"
      },
      "displayName": "sbConnection"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Then specify queue/topic/subscription names as custom values in your workflow triggers.


Step 4: Workflow Examples

4.1 Message Sender (wf7_sb_send)

LADevStuff2/wf7_sb_send/workflow.json

๐Ÿ’ก Key Point: userProperties.orderType is used by SQL filters to route messages.

4.2 SB Receivers (wf4,wf5,wf6)

LADevStuff2/wf4/workflow.json

๐Ÿ“ Note: queueName, topicName, and subscriptionName are specified as custom values in the trigger, not selected from a dropdown.

๐ŸŽฏ wf5 : Receives only messages where user.orderType = 'TypeA' (defined in Config.json)

๐ŸŽฏ wf6 : Receives only messages where user.orderType = 'TypeB' (defined in Config.json)


Step 5: Start Everything

cd DockerFiles
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Verify Service Bus is running:

docker logs servicebus-emulator-shared --tail 20
Enter fullscreen mode Exit fullscreen mode

Look for:

info: Emulator Service is Successfully Up!
info: Creating queue: local-orders-queue
info: Creating topic: local-orders-topic
info: Entity Sync complete; Operation Result:True
Enter fullscreen mode Exit fullscreen mode

Check all containers:

docker compose ps
Enter fullscreen mode Exit fullscreen mode

All should show status "Up".


Step 6: Test the Workflows

Send TypeA Order

Making the HTTP Request

Use Postman (or curl) to send a POST request to the wf7_sb_send workflow:

What happens:

  1. HTTP POST triggers wf7_sb_send with payload {"OrderType": "TypeA"}
  2. The workflow sends the message to:
    • Queue: local-orders-queue (no filtering)
    • Topic: local-orders-topic with userProperties.orderType = "TypeA"
  3. The userProperties field is what SQL filters use for message routing

Workflow Execution

RunHistory Viewer shows the send workflow successfully completed:

Expected behavior:

  • โœ… wf4 processes message from queue (all messages go here)
  • โœ… wf5 processes message from topic (TypeA filter matches)
  • โŒ wf6 does NOT process (TypeB filter doesn't match)

Send TypeB Order

Follow the same process as TypeA, but change the payload to:

{ "OrderType": "TypeB" }
Enter fullscreen mode Exit fullscreen mode

Note: You can also extension to send simply payloads, refer below gif

Expected behavior:

  • โœ… wf4 processes message from queue (receives all messages)
  • โŒ wf5 does NOT process (TypeA filter doesn't match)
  • โœ… wf6 processes message from topic (TypeB filter matches)

The SQL filters ensure each workflow only receives messages matching its subscription criteria.


Step 7: Verify Execution

Use the RunHistory Viewer in VS Code to verify workflow executions:

Topic Subscriber (wf5) - TypeA Filter

The screenshot shows the workflow successfully received and processed messages filtered by user.orderType = 'TypeA'.

Queue Receiver (wf4) - All Messages

The screenshot shows the workflow processing all messages from the queue, regardless of message properties.


Key Takeaways

โœ… Memory is critical - 15.6GB Docker, 8GB Service Bus, 2GB MSSQL
โœ… Use MSSQL Server 2022 - Not SQL Edge
โœ… extra_hosts configuration - Required for Docker networking
โœ… SQL filters use user. prefix - For custom properties
โœ… Manually edit connections.json - Designer doesn't support queue/topic setup
โœ… localhost:5672 connection string - Due to extra_hosts configuration
โœ… Rebuild containers - After workflow changes


Summary

You now have a complete local development environment with:

โœ… Service Bus Emulator running in Docker
โœ… Queue for point-to-point messaging
โœ… Topic with SQL-filtered subscriptions for pub/sub
โœ… Multiple Logic Apps in containers
โœ… Proper memory configuration for stability
โœ… Working examples (wf4, wf5, wf6, wf7)

This setup is perfect for:

  • Local development and testing
  • Learning Logic Apps and Service Bus patterns
  • Integration demos
  • Offline development

You can later swap the emulator connection string for Azure Service Bus without changing your workflows!

Happy integrating! ๐Ÿš€๐Ÿณ

Top comments (0)