我有一个项目,其中包含2个Dockerfile,一个用于后端,一个用于数据库。 dockerfile位于单独的文件夹中。我使用如下所示的docker-compose.yml文件构建了两个图像:
version: "3.7"
services:
dotnet-backend:
container_name: dotnet-backend
build: .
env_file: .env
links:
- mssql-db
ports:
- "8000:80"
mssql-db:
container_name: mssql-db
build: ./Database
env_file: .env
volumes:
- ./Database/:/scripts/
ports:
- "1433:1433"
expose:
- "1433"
command:
- /bin/bash
- -c
- |
/opt/mssql/bin/sqlservr &
sleep infinity
如您所见,我使用.env文件作为环境变量,该文件位于src文件夹中,与后端和其余后端代码的Dockerfile相同。
这是我的后端Dockerfile:
FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Debug -o out MyProject.csproj
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0
WORKDIR /app
COPY --from=build-env /app/out .
EXPOSE 80
ENV ASPNETCORE_ENVIRONMENT=$ASPNETCORE_ENVIRONMENT
ENTRYPOINT ["dotnet", "MyProject.dll"]
这是我的数据库Dockerfile(位于./Database中):
FROM mcr.microsoft.com/mssql/server:2017-latest
ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=$SA_PASSWORD
ENV MSSQL_PID=Developer
ENV MSSQL_TCP_PORT=1433
WORKDIR /src
COPY ./ /scripts/
EXPOSE 1433
RUN (/opt/mssql/bin/sqlservr --accept-eula & ) | grep -q "Service Broker manager has started" && sleep 5s && (for foo in /scripts/*.sql;do /opt/mssql-tools/bin/sqlcmd -S127.0.0.1 -Usa -P$SA_PASSWORD -i$foo;done)
最后是我的.env文件:
SA_PASSWORD=SomePassword
ASPNETCORE_ENVIRONMENT=Development
ConnectionStrings__My_db=Data Source=tcp:mssql-db,1433;Initial Catalog=DevDB;User ID=sa;Password=SomePassword
奇怪的是,设置了ASPNETCORE_ENVIRONMENT变量,正如我通过测试我的API可以知道它正在开发模式下运行一样,而且.env文件中的连接字符串也得到了设置,因为我的API可以在以下情况下连接到我的数据库我手动输入密码。但是未设置SA_PASSWORD环境变量。这是docker-compose up --build命令的输出:
那么为什么要设置其他变量和连接字符串而不设置密码?如果我在数据库Dockerfile中将ENV SA_PASSWORD=$SA_PASSWORD
替换为ENV SA_PASSWORD=SomePassword
,一切都会正常工作。
答案 0 :(得分:1)
您根本不需要在docker映像中设置环境变量,并且可以使用以下更改来解决问题
ASPNETCORE_ENVIRONMENT 之所以有效,是因为该应用仅在运行时而不是在构建时进行检查
数据库docker文件
FROM mcr.microsoft.com/mssql/server:2017-latest
ENV ACCEPT_EULA=Y
ENV MSSQL_PID=Developer
ENV MSSQL_TCP_PORT=1433
WORKDIR /src
COPY ./ /scripts/
EXPOSE 1433
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
docker-entrypoint.sh(chmod a + x)
#!/bin/bash -e
(/opt/mssql/bin/sqlservr --accept-eula & ) | grep -q "Service Broker manager has started" && sleep 5s && (for foo in /scripts/*.sql;do /opt/mssql-tools/bin/sqlcmd -S127.0.0.1 -Usa -P$SA_PASSWORD -i$foo;done)
exec "$@"
exit 0
应用docker文件
FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Debug -o out MyProject.csproj
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0
WORKDIR /app
COPY --from=build-env /app/out .
EXPOSE 80
ENTRYPOINT ["dotnet", "MyProject.dll"]
您也可以将这些文件移到环境文件中,建议为容器分开环境文件
ENV ACCEPT_EULA=Y
ENV MSSQL_PID=Developer
ENV MSSQL_TCP_PORT=1433
答案 1 :(得分:0)
这不是从环境中获取var的有效方法。
Dockerfile中的变量$ SA_PASSWORD实际上是Dockerfile范围和构建映像时间的变量。
var没有值,因为通过ARG命令(https://docs.docker.com/engine/reference/builder/#arg)进行分配的方式。
无论如何,如果您需要声明SA_PASSWORD并在容器运行时读取环境信息,则必须通过ENTRYPOINT来执行此操作。容器启动时执行ENTRYPOINT。