具有Azure CLI的自定义Docker镜像用于身份验证

问题描述 投票:0回答:1

我正在构建要通过Azure Devops构建管道进行部署的.NET Core应用程序。该管道将​​使用Docker容器构建,测试和部署。

我已经使用以下Dockerfile为我的应用程序成功构建了第一个docker映像,现在正在尝试在管道中使用它之前先在本地计算机上运行它:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
MAINTAINER yummylumpkins <[email protected]>
WORKDIR /app

COPY . ./
RUN dotnet publish MyAPIApp -c Release -o out

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /app
COPY --from=build-env /app/out .

ENTRYPOINT ["dotnet", "MyAPIApp.dll"]

在docker容器中运行此映像在本地崩溃,因为我的应用程序使用AzureServiceTokenProvider()尝试从Azure服务中获取令牌,然后将该令牌用于从Azure Key Vault中获取机密。运行映像的本地docker容器无权访问Azure服务。docker容器错误输出如下所示:

 ---> Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/XXXX-XXXX-XXXX-XXXX. Exception Message: Tried the following 3 methods to get an access token, but none of them worked.
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/XXXX-XXXX-XXXX-XXXX. Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. Connection refused
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/XXXX-XXXX-XXXX-XXXX. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Environment variable LOCALAPPDATA not set.
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/XXXX-XXXX-XXXX-XXXX. Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. /bin/bash: az: No such file or directory

[经过大量研究(并在此处获得了一些积极的反馈),看来授权本地运行的Docker容器的最佳方法是在Microsoft的Azure CLI基础映像之上构建映像,然后使用[C0 ]在构建/运行过程中的某个地方授权本地docker容器。

我已成功从Microsoft(az login --service-principal -u <app-url> -p <password-or-cert> --tenant <tenant>)提取Azure CLI映像,并可以通过docker pull mcr.microsoft.com/azure-cli运行它。该容器使用Azure CLI命令行运行,我可以通过bash登录,但就我所知。

下一步是在映像构建过程中将此Azure CLI映像分层到我以前的Dockerfile中,但是我不确定这样做。我尝试了以下方法:

docker run -it mcr.microsoft.com/azure-cli

但是这仍然行不通,该过程仍会导致上述相同错误(我认为是因为添加新的# New base image is now Azure CLI FROM mcr.microsoft.com/azure-cli RUN az login -u yummylumpkins -p yummylumpkinspassword FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env MAINTAINER yummylumpkins <[email protected]> WORKDIR /app COPY . ./ RUN dotnet publish MyAPIApp -c Release -o out FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 WORKDIR /app COPY --from=build-env /app/out . ENTRYPOINT ["dotnet", "MyAPIApp.dll"] 层时登录不会持久。我的问题是,我将如何显式构建Azure CLI映像使用dotnet core命令进入我的dockerfile /映像构建过程以授权docker容器,保留授权,然后设置命令以具有持久授权运行应用程序(MyAPIApp.dll)?

或者,我是否采用完全错误的方法?预先感谢您的任何反馈。

docker docker-compose azure-devops dockerfile containers
1个回答
0
投票

在此处发布带有答案的更新,以防万一其他人遇到类似问题。我还没有找到其他解决方案,所以我不得不自己做。以下是我的Dockerfile。现在,映像的大小为1GB,因此我肯定需要进行优化,但是我将解释自己的工作:

azure login

[第1步-安装.NET Core SDK生成环境:我们首先使用.NET Core SDK作为基础图像来构建我的应用程序。应该注意的是,我有一个具有一个解决方案和多个项目文件的大型应用程序。 API项目依赖于其他项目。

第2步-构建YummyApp:我们将整个项目结构从本地目录复制到docker映像(/ app)中的工作目录。以防万一有人好奇,我的项目是一个基本的API应用程序。看起来像这样:

#1 Install .NET Core SDK Build Environment
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app

#2 Build YummyApp
COPY . ./
RUN dotnet publish YummyAppAPI -c Release -o out

#3 Install Ubuntu Base Image
FROM ubuntu:latest
MAINTAINER yummylumpkins <[email protected]>
WORKDIR /app
ENV ASPNETCORE_URLS=http://+:80
EXPOSE 80

#4 Install package dependencies & .NET Core SDK
RUN apt-get update \
    && apt-get install apt-transport-https \
    && apt-get update \
    && apt-get install -y curl bash dos2unix wget dpkg \
    && wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \
    && dpkg -i packages-microsoft-prod.deb \
    && apt-get install -y software-properties-common \
    && apt-get update \
    && add-apt-repository universe \
    && apt-get update \
    && apt-get install apt-transport-https \
    && apt-get update \
    && apt-get install -y dotnet-sdk-3.1 \
    && apt-get update \
    && rm packages-microsoft-prod.deb

#5 Copy project files from earlier SDK build
COPY --from=build-env /app/out .

#6 Install Azure CLI for AppAuthorization
RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash

#7 Login to Azure Services and run application
COPY entrypoint.sh ./
RUN dos2unix entrypoint.sh && chmod +x entrypoint.sh
CMD ["/app/entrypoint.sh"]

复制完所有内容后,我们将构建/发布应用程序的Release配置。

第3步-安装Ubuntu基本映像:我们使用Ubuntu启动一个新层。最初,我尝试使用Alpine Linux,但发现几乎不必在其中进行Azure命令行操作而无需做一些真正的变通办法,因此我选择了Ubuntu,以简化安装。

[第4步-安装程序包依赖项和.NET Core SDK:在Ubuntu层中,我们设置工作目录并安装/更新一堆库,包括.NET Core SDK。应该注意的是,我需要为以后必须运行的shell脚本文件安装[YummyApp] |-YummyAppDataAccess |YummyAppDataAccess.csproj |-YummyAppInfrastructure |YummyAppInfrastructure.csproj |-YummyAppAPI |-YummyAppAPI.csproj |-YummyAppServices |-YummyAppServices.csproj |-YummyApp.sln 。 。我待会再解释。

注意:我最初只是尝试安装.NET Core Runtime,因为它更轻巧,并且可以将映像降低到大约700MB(从1GB开始),但是由于某种原因,当我尝试在文件末尾运行应用程序时(步骤7)我收到一条错误消息,提示未找到任何运行时。所以我回到了SDK。

第5步-从早期的SDK Build复制项目文件:为了节省空间,我将构建的项目文件从第一个“ build image”复制到了Ubuntu层,以节省一些空间(约1GB)。 >

[步骤6-安装Azure CLI:

为了授权我的应用程序从Azure服务中获取令牌,通常我使用dos2unix。该程序包提供了一种称为Microsoft.Azure.Services.AppAuthentication的方法,该方法(通过我的IDE)授权我的应用程序连接到Azure服务,以获取令牌,然后该令牌用于访问Azure密钥保管库。 这整个问题开始是因为我的应用程序无法从Docker容器中执行此操作,因为Azure无法识别来自容器本身的请求。

因此,要解决此问题,在启动应用程序之前,我们需要通过Azure CLI在容器内的AzureServiceTokenProvider()登录。

[步骤7-登录到Azure服务并运行应用程序:

现在是放映时间。我在这里要解决两个不同的问题。我必须弄清楚当该容器启动时如何执行az loginaz login。但是Dockerfile只允许在运行时执行一个dotnet YummyAppAPI.dllENTRYPOINT,因此我找到了一种解决方法。通过制作一个shell脚本文件(entrypoint.sh),我能够将两个命令都放入该文件中,然后执行该文件。

[设置完成后,CMD出现错误,内容如下:entrypoint.sh。我发现我必须使用entrypoint.sh: executable file not found in $PATH更改此文件的权限,因为否则,我的Docker容器将无法访问它。这使文件可见,但是文件仍然无法执行。我收到另一个错误:chmod

经过一些深入的研究,结果表明,当您尝试在基于Linux的系统上使用Windows中创建的.sh文件时,会发生此问题。因此,我必须安装Standard_init_linux.go:211: exec user process caused “no such file or directory”才能将此文件转换为与Linux兼容的文件。我还必须确保文件格式正确。对于任何好奇的人,这就是我的dos2unix样子:

entrypoint.sh

注意:

登录名和密码是硬编码的。 。 。我知道这是一个不好的做法(实际上,这很糟糕),但是,这对我的本地计算机来说是[[only,并且永远都看不到产品。下一步将使用服务原理登录名引入环境变量。由于此部署最终将在Azure Devops管道中进行,因此我可以将那些ENV变量直接注入devops管道YAML中,以便所有这些事情都无需我输入凭据即可完成。它们将直接从存储它们的密钥库中来。最后,此容器的大小很大(1GB),如果要定期更新/构建,则必须对其进行优化。我将继续致力于这一工作,但是我愿意就如何最好地做到这一点提出建议。

再次感谢大家。

© www.soinside.com 2019 - 2024. All rights reserved.