skip to Main Content

I span up two docker containers: one which houses a CosmosDb emulator image container and another which houses my function app. Both of these containers run in linux using Docker Desktop.

I needed to be able to access the cosmosDb container from my function app container. This turned out to be problematic and took me a few days to work out so I’ve put the solution here.

The Microsoft guide does not explain how to do this. What it actually does is tell you how to access the CosmosDb container from your LOCAL machine.
https://learn.microsoft.com/en-us/azure/cosmos-db/docker-emulator-linux?tabs=sql-api%2Cssl-netstd21

The certificate that the cosmosdb emulator uses always has the domain of localhost and this can’t be configured to the container host name:
https://localhost:8081/_explorer/emulator.pem

Therefore how do I access the Cosmos container from my function app container?

2

Answers


  1. Chosen as BEST ANSWER

    I found the solution to be to configure the CosmosDb container with a fixed ip and then I could access the CosmosDb instance using http://<ip_address>:8081.

    The key here is to give the cosmos container a fixed ip (in my case 172.16.238.246) which you can use to get the cert as per the microsoft guide above. You can then call it from your application. Remember to set your HOST_IP variable so you can access it from your local pc.

    Docker compose:

    networks:
      default:
        external: false
        ipam:
          driver: default
          config:
            - subnet: "172.16.238.0/24"
    
    services:
      cosmosDb:
        container_name: CosmosDb
        image: "mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator"
        tty: true
        restart: always
        mem_limit: 3G
        cpu_count: 4
        environment:
          - AZURE_COSMOS_EMULATOR_PARTITION_COUNT=5
          - AZURE_COSMOS_EMULATOR_ENABLE_DATA_PERSISTENCE=true
          # Set this as an environment variable in host shell to allow access from your local pc using http://locahost:8081 e.g. $Env:HOST_IP="192.168.0.16"
          - AZURE_COSMOS_EMULATOR_IP_ADDRESS_OVERRIDE=${HOST_IP}
        ports:
          - '8081:8081'
          - '10250-10255:10250-10255'
        networks:
          default:
            ipv4_address: 172.16.238.246
        healthcheck:
          test: ["CMD", "curl", "-fk", "https://localhost:8081/_explorer/emulator.pem"]
          interval: 5s
          timeout: 10s
          retries: 5
          start_period: 20s
        entrypoint: ["/bin/bash","-c"]
        command: 
           - |
              apt-get update -y && apt-get install -y curl
              /usr/local/bin/cosmos/start.sh
    
      myFuncApp:
        build:
          dockerfile: Dockerfile
          context: .
        container_name: MyFuncApp
        image: myfuncapp
        ports:
          - '80:80'    
        entrypoint: ["/bin/bash","-c"]
        command: 
           - |
            curl -fk -o ~/cosmosemulatorcert.crt https://172.16.238.246:8081/_explorer/emulator.pem
            cp ~/cosmosemulatorcert.crt /usr/local/share/ca-certificates/
            update-ca-certificates
            /azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost
        depends_on:
          cosmosDb: 
            condition: service_healthy
    

    Dockerfile:

    FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4.0-dotnet-isolated6.0 AS base
    
    FROM base AS final
    
    COPY bin/Debug/net6.0 /home/site/wwwroot
    
    RUN apt-get update -y && apt-get install -y curl
    
    ENV CosmosDb__EndpointUrl="https://172.16.238.246:8081"
    

  2. If it helps, I have found that I can reference the Azure Cosmos DB emulator using its service name in the Docker Compose file.

    Here’s an example:

    version: '3'
    services:
      devenv:
        image: mcr.microsoft.com/dotnet/sdk:6.0
        command: sleep infinity
        volumes:
          - ..:/workspace
        depends_on:
          - azurecosmosdb
      azurecosmosdb:
        image: mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator
        ports:
          - 8081:8081
    

    You can then reference the emulator using the name of the service and the port number. Here’s an example of creating an CosmosClient.

    The key used here is the default key for the emulator.

    CosmosClient client = new ("AccountEndpoint=https://azurecosmosdb:8081;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;");
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search