Testing cloud-native apps locally is great, but things get tricky when you need to access your local database from a mobile device, a webhook, or a remote colleague's machine.
In this guide, we’ll containerize the Azure Cosmos DB Emulator and use ngrok to create a secure tunnel to the public internet.
The Architecture
- Docker: Runs the Cosmos DB Linux Emulator.
- ngrok: Creates a secure HTTPS tunnel to your local port.
- Node.js App: Connects to the ngrok URL using specific configurations to bypass local certificate and discovery hurdles.
1. Start the Cosmos DB Emulator
Run the following command in your terminal.
Important: Replace
192.168.1.17with your machine's actual Local IP address (find this viaipconfigon Windows orifconfigon Mac/Linux).
docker run
--publish 8081:8081
--publish 1234:1234
--name cosmos-emulator
--env AZURE_COSMOS_EMULATOR_GATEWAY_ADVERTISE_HOST=192.168.1.17
--env AZURE_COSMOS_EMULATOR_IP_ADDRESS_OVERRIDE=192.168.1.17
mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview
- Fire up the ngrok Tunnel Once the container is healthy, expose port 8081. We must use the --host-header rewrite flag because the Cosmos Emulator is picky about the hostnames it accepts.

ngrok http 8081 --host-header=rewrite
Copy the generated https://...ngrok-free.app URL. You'll need it for your connection string.
- The Node.js Client Setup Connecting to a tunneled emulator requires two specific "hacks" in your client configuration:
Disable Endpoint Discovery: This prevents the SDK from trying to find the "real" local IP and sticking to the ngrok URL instead.
Ignore Self-Signed Certs: Since the emulator uses a local dev cert, we need to tell the HTTPS agent to allow it.
The Code (index.js)
const { CosmosClient } = require("@azure/cosmos");
const https = require("https");
const client = new CosmosClient({
endpoint: "https://YOUR_NEW_NGROK_URL.ngrok-free.app",
key: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
connectionPolicy: {
enableEndpointDiscovery: false // Keeps the traffic flowing through ngrok
},
agent: new https.Agent({
rejectUnauthorized: false // Bypasses self-signed certificate errors
})
});
async function testConnection() {
try {
await client.databases.readAll().fetchAll();
console.log("Success! You are connected via ngrok.");
} catch (err) {
console.error("Error:", err.message);
}
}
testConnection();
Key Takeaways
Port 8081: This is the Gateway port. Ensure it's open and mapped correctly.
Discovery Off: If enableEndpointDiscovery is true, your app will try to connect to 127.0.0.1 after the first request, breaking the remote tunnel connection.
Security: Never use rejectUnauthorized: false in a production environment. This is strictly for local emulator testing!
Troubleshooting
If you get a connection timeout:
Ensure your Docker container has finished starting up (it can take 60+ seconds).
Verify that your local firewall isn't blocking port 8081.
Check that the AZURE_COSMOS_EMULATOR_GATEWAY_ADVERTISE_HOST matches your current local IP.



Top comments (0)