Reputation: 704
I have a solution which contains 2 microservices (Product & Review). Each of the 2 API projects have a Dockerfile defined, here is an example of the review dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
ENV ConnectionString:Review="Data Source=db,1433;Initial Catalog=Review;uid=sa;pwd=TesT111t!;Integrated Security=false;MultipleActiveResultSets=True"
COPY ["Review.Api/Review.Api.csproj", "Review.Api/"]
COPY ["Review.Data/Review.Data.csproj", "Review.Data/"]
COPY ["Review.Service/Review.Service.csproj", "Review.Service/"]
RUN dotnet restore "Review.Api/Review.Api.csproj"
COPY . .
WORKDIR "/src/Review.Api"
RUN dotnet build "Review.Api.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Review.Api.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Review.Api.dll"]
As you can see the dockerfile contains an env variable ConnectionString
.
I have a breakpoint in the startup of the review api project to inspect what is inside the Configuration
, here is what the file looks like:
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ReviewDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Review")), ServiceLifetime.Transient);
services.AddAutoMapper(typeof(FindProductReviews));
services.AddAutoMapper(typeof(FindReview));
services.AddAutoMapper(typeof(ReviewController));
services.AddAutoMapper(typeof(ProductController));
services.AddMediatR(typeof(FindProductReviews.Handler).Assembly);
services.AddMediatR(typeof(FindReview.Handler).Assembly);
services.AddMediatR(typeof(CreateReview.Handler).Assembly);
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapDefaultControllerRoute();
});
}
}
My solution has a docker-compose
file and when running docker-compose up -d
the breakpoint is hit, however when looking inside the Configuration
their is no connection string which is defined like the one in the dockerfile.
I feel like im missing something small, I've looked at the documentations and cannot find what I'm missing
Upvotes: 3
Views: 1473
Reputation: 2269
First of all, please confirm that, when your program starts, you are building your configuration such as below (typical setups), in order to bind it with env.variables.
// Defining a configuration that explicitly uses env. variables
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
...
.AddEnvironmentVariables()
.Build();
or
// The default builder already adds env. variables
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
...
Please, replace ConnectionString:Review
by ConnectionString__Review
(reference here).
If you want to keep on setting the env.variable in your Dockerfile
, you can move it to the last section final
, such as:
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ConnectionString__Review="Data Source=db,1433;Initial Catalog=Review;uid=sa;pwd=TesT111t!;Integrated Security=false;MultipleActiveResultSets=True"
ENTRYPOINT ["dotnet", "Review.Api.dll"]
However, to enhance decoupling, you may prefer to set the variable in your docker-compose
file.
You may also consider using the appsettings
JSON files, since they allow much flexibility across environments.
If your services are able to access shared configurations, but also have their own, then, you can specify proper names to each configuration, to ensure that any mistake happens :)
Upvotes: 1
Reputation: 159790
You only define the ENV
variable in the build
image. If you follow the FROM
chain, the final
image is built FROM base
, and COPY --from=build
, but the COPY
only copies files and not environment variables or other metadata.
Your question title and tags hint at a Compose-based setup. Connection information like the database host name and (especially) credentials need to be configured at deployment time, not part of the image. I'd remove this line from your Dockerfile
entirely, and instead include it in your docker-compose.yml
:
version: '3.8'
services:
db: { ... }
app:
environment:
- ConnectionString:Review=Data Source=db,1433;Initial Catalog=Review;uid=sa;pwd=TesT111t!;Integrated Security=false;MultipleActiveResultSets=True
...
Upvotes: 0