我正在构建一个多容器应用程序,使用“docker compose”部署在 Azure 应用程序服务上,分配一个身份(用户分配的托管身份)并向主体 ID 提供 RBAC,以使用以下命令访问 cosmos 容器
az cosmosdb sql role assignment create -a cosmos-nosql-db -g rish90-rg-westus -s "/" -p actual_principal_id -d 00000000-0000-0000-0000-000000000002
多容器应用程序由三个容器 nginx 代理、nginx http web 服务器和基于 .NET 的后端服务器组成。它是使用 DefaultAzureCredential 与 CosmosDB 进行通信的后端服务器。
但是对于多容器应用程序,cosmos db 无法访问。我收到错误
Azure.Identity.CredentialUnavailableException: DefaultAzureCredential failed to retrieve a token from the included credentials.
但是如果我将后端部署为单个容器天蓝色应用程序服务;并启用托管身份和各自的RBAC,后端能够访问cosmos;
我无法理解这里的问题是什么以及如何解决?
这是系统的设计
我认为使用
docker compose
文件的多容器应用程序当前不支持托管身份连接,因为它当前处于预览状态。我建议使用 connection string
进行连接以解决问题。
使用连接字符串对我有用。
我为客户端使用了连接字符串。
docker-compose.yml
:
version: '3.3'
services:
proxy:
image: vivek.azurecr.io/proxy
ports:
- "80:80"
container_name: proxy
frontend:
image: vivek.azurecr.io/frontend
ports:
- "80"
depends_on:
- backend
container_name: frontend
backend:
image: vivek.azurecr.io/backend
ports:
- "3000"
container_name: backend
TodoListDbClient.cs
:
using System.Net.Http.Headers;
using Azure.Identity;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.Linq;
using TodoApi;
public class TodoListDbClient : IDbClient
{
private readonly Container _todoListContainer;
public TodoListDbClient()
{
var cosmosClientOptions = new CosmosClientOptions {
};
var cosmosClient = new CosmosClient("AccountEndpoint=https://multicontainer-web-app-db.documents.azure.com:443/;AccountKey=xxxxxxxxxxxxxxxxxxxxx;");
_todoListContainer = cosmosClient.GetDatabase("ToDoList").GetContainer("Items");
}
public async Task<ItemResponse<Todo>> AddAsync(Todo todoItem)
{
return await _todoListContainer.CreateItemAsync<Todo>(todoItem);
}
public async Task<List<Todo>> GetAllAsync()
{
var queryable = _todoListContainer.GetItemLinqQueryable<Todo>();
var feed = queryable.Where(p => p.id != null).ToFeedIterator();
List<Todo> todos = [];
while (feed.HasMoreResults)
{ //pagination response
var response = await feed.ReadNextAsync();
foreach (var item in response)
{
todos.Add(item);
}
}
return todos;
}
}
OUTPUT