如何在从 docker-compose 调用的 .sh 文件中使用 .NET Core 机密

Posted

技术标签:

【中文标题】如何在从 docker-compose 调用的 .sh 文件中使用 .NET Core 机密【英文标题】:How to use .NET Core secrets in .sh file that is called from docker-compose 【发布时间】:2021-10-21 06:57:03 【问题描述】:

背景

我正在编写一个.NET 5 应用程序并使用 .net 用户密码作为我的密钥(数据库连接和密码)。

最近我决定学习Dockers 并更新我的应用程序以使用它,以便使用Visual Studio 为我的API 项目生成一个docker 文件,然后创建一个包含@ 的docker-compose 文件987654327@ 项目和数据库(以及与此问题无关的一些内容)。

几乎一切都运行良好。从技术上讲,我可以对这些秘密进行硬编码,然后应用程序就会运行良好。

我有一些秘密,其中大部分都可以正常工作,例如:数据库连接秘密运行良好,在 C# 代码中我执行以下代码并从 .net user-secrets 获取值:

config.GetConnectionString("Default");

代码详情

我有一个密钥,其中包含 sa 用户的 SQL 密码。

dotnet user-secrets set "SA_PASSWORD" "<MySecretPassword>"

然后我有一个 Linux 系统的 docker-compose 文件,这是代码的一部分:

sql_in_dc:
  build:
    context: .
    dockerfile: items/sql/sql.Dockerfile
  restart: always
  ports:
    - "1440:1433"
  environment:
    - ACCEPT_EULA=Y
    - SA_PASSWORD=$SA_PASSWORD
    - ASPNETCORE_ENVIRONMENT=Development
    - USER_SECRETS_ID=80a155b1-fb7a-44de-8788-4f5759c60ff6
  volumes:
    - $APPDATA/Microsoft/UserSecrets/$USER_SECRETS_ID:/root/.microsoft/usersecrets/$USER_SECRETS_ID
    - $HOME/.microsoft/usersecrets/$USER_SECRETS_ID:/root/.microsoft/usersecrets/$USER_SECRETS_ID

如您所见,它调用sql.Dockerfile,即:

FROM mcr.microsoft.com/mssql/server 

ARG PROJECT_DIR=/tmp/devdatabase
RUN mkdir -p $PROJECT_DIR
WORKDIR $PROJECT_DIR
COPY items/sql/InitializeDatabase.sql ./
COPY items/sql/wait-for-it.sh ./
COPY items/sql/entrypoint.sh ./
COPY items/sql/setup.sh ./

CMD ["/bin/bash", "entrypoint.sh"]

那么setup.sh就是:

# Wait for SQL Server to be started and then run the sql script
./wait-for-it.sh sql_in_dc:1433 --timeout=0 --strict -- sleep 5s && \
/opt/mssql-tools/bin/sqlcmd -S localhost -i InitializeDatabase.sql -U sa -P "$SA_PASSWORD"

问题

文件setup.sh 无法识别来自秘密文件的$SA_PASSWORD 环境变量。

如果我将docker-compose.yml 文件更改为:

- SA_PASSWORD=SomePassword

备注

我在 Google 中搜索了答案并尝试了很多方法,但找不到完全符合我的情况。 我知道可以使用Docker Swarm 作为秘密,但现在我想不使用它。我仍在学习,希望代码能正常工作,下一步将使用Docker Swarm / Kubernetes / 等... 我很高兴知道是否有快速的解决方案,即使它不是理想的解决方案。稍后我会改进它并使用更好的技术。 我写的代码我认为对于案例和相关代码应该足够了,但是如果您需要更多数据,请告诉我,我会添加它。 我在 GitHub 的一个推送分支的公共存储库中拥有它。如果你愿意,我可以与你分享代码。

提前非常感谢!

【问题讨论】:

正如您所提到的,这取决于您的环境(Docker swarm、Kubernetes)。我在生产中使用用户密码进行本地开发我在 openshift(kubernetes)中创建密码并将它们映射到集群中的环境变量 @kraego 是的。对于地方发展的问题。它无法识别SA_PASSWORD 的用户机密。也许我做得不对。 【参考方案1】:

docker-compose.yml 在您的主机操作系统上执行(因此它可以使用操作系统环境变量或来自 .env 文件或来自撰写文件的变量,...)。 正在运行的映像 - 容器有自己的一组环境变量,在您的情况下,这意味着正在运行的容器没有 SA_PASSWORD 变量。 如果您在主机操作系统上设置了 SA_PASSWORD 变量,您的用例就可以工作。

您可以检查容器中设置了哪些变量(如果您的图像带有 bash):

docker exec -it [container id] bash
printenv 

dotnet-secrets 环境变量是在 Visual Studio 执行/运行时隐式创建的(请参阅项目文件中的条目)。

正如您提到的“撰写文件无法识别 dotnet-secrets”

你可以使用:

    *.env File 将它传递给撰写命令:-e compose yml 中的纯文本:- SA_PASSWORD=thepassword 作为主机操作系统变量

请记住,Visual Studio 在运行或调试 docker 容器时会增加一些魔力。 See Visual Studio container volume mapping:For ASP.NET core web apps, there might be two additional folders for the SSL certificate and the user secrets, which is explained in more detail in the next section.

【讨论】:

是的,这就是我所做的,直到我在这里得到答案并且它有效。但是,我仍然不明白连接字符串是如何从用户机密传递到在我的本地环境中在 docker-compose 中运行的代码并且它工作正常,但 SA_PASSWORD 不是? 您的意思是所有其他环境变量都存在吗?只是缺少 SA_PASSWORD? 我的意思是,在我的用户密码中,我有连接字符串和SA_PASSWORD 的密码。当使用 docker 运行应用程序并且代码在Startup.cs => 中运行时,我正在注入从user-secrets 获取它的连接字符串,它设法正确读取这些数据。但是当我尝试在setup.sh 脚本中获取 SA_PASSWORD 数据时,它无法识别它。因此,它确实识别出来自user-secrets 的一些秘密。问题是它在从代码中识别 SA_PASSWORD 时(下一条消息将继续......) 问题是尝试在我的 docker-compose 文件中读取它时。因此,使用环境变量,它运行良好。但是为什么SA_PASSWORDStartup.cs 中是已知的,它在docker-compose up 命令下运行,但是如果我把它放到docker-compose.yml 文件中它就无法识别它?所以也许,答案只是 yml 文件无法识别 dotnet-secrets,如果是这种情况,那很好。 现在我正在阅读这些文章。也许它会帮助我理解。我 +1,也许很快会接受这个答案:) 谢谢,如果你能回答上面的问题,我也会很高兴。

以上是关于如何在从 docker-compose 调用的 .sh 文件中使用 .NET Core 机密的主要内容,如果未能解决你的问题,请参考以下文章