Reputation: 4434
I have a .net core 3 app running locally/development just fine, both on its own and when run in a linux container. I then take the app and have it built into a docker image inside azure pipelines. The image is loaded to azure container registry.
Finally, I have an Azure Web APP for Containers (Linux) that uses the image to run.
Locally I have the docker-compose file set up like this:
environment:
- "ASPNETCORE_ENVIRONMENT=Development"
...
- "ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx"
- "ASPNETCORE_Kestrel__Certificates__Default__Password=Your_password123"
volumes:
- ~/.aspnet/https:/https:ro
For production I have the following:
environment:
- UseInMemoryDatabase=false
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_Kestrel__Certificates__Default__Path=/security/mycert.pfx
- "ASPNETCORE_Kestrel__Certificates__Default__Password=Your_password123"
ports:
- "5000:5000"
- "5001:5001"
volumes:
- fsmount001: /security:/security
- /var/ssl/private:/https
I loaded "mycert" into the azure portal and added its thumbprint to the App's configuration settings under WEBSITE_LOAD_CERTIFICATES
I used Open SSL to create the mycert file and I can use it locally and kestral will use it, but with a warning.
When I run the app with this image I get the following error in the docker logs:
System.InvalidOperationException: Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date ... at Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(ListenOptions listenOptions, Action`1 configureOptions)
I have tried a lot of variations of loading certs and can not get any of them to work. This is an issue that only happens in production.
I also have tried:
- ASPNETCORE_Kestrel__Certificates__Default__Path=/var/ssl/private/<thumbprint>.p12
- ASPNETCORE_Kestrel__Certificates__Default__Password=""
I used no password because when you buy a cert there is no password set
Downloaded the purchased App Cert and used open ssl to create a password linked .pfk file and uploaded that as another private key
Use azure file mount and upload my dev cert files and reference them from the file mount like:
- ASPNETCORE_Kestrel__Certificates__Default__Path=/security/mycert.com.pfx
- ASPNETCORE_Kestrel__Certificates__Default__Password="Your_password123"
volumes:
- fsmount001: /security:/security
There is a security folder with the mycert.pfx file inside it
I set the mount path to be the security folder in my file share
services:
webui:
image: ${DOCKER_REGISTRY-}webui
build:
context: .
dockerfile: src/WebUI/Dockerfile
environment:
- UseInMemoryDatabase=false
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=https://+:443;http://+:80
- "ConnectionStrings__DefaultConnection=****"
- ASPNETCORE_Kestrel__Certificates__Default__Path=/secure/mycert.pfx
- ASPNETCORE_Kestrel__Certificates__Default__Password="Your_password123"
ports:
- "5000:5000"
- "5001:5001"
volumes:
- fsmount001: /secure
- ~/var/ssl/private:/https
restart: always
volumes:
fsmount001:
driver: azure_file
driver_opts:
share_name: st-*****tus
storage_account_name: st********001
for further context you can find my dockerfile below
please note that I am using the open source application template/framework cleanarchiecture. You can see that I am trying to use the docker pull request for the repo as the base code. My goal is to "dockerize" this base framework in azure ci/cd pipeline and deploy it to azure web app for containers (linux)
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
ENV ASPNETCORE_URLS=https://+:5001;http://+:5000
WORKDIR /app
EXPOSE 5000 5001 2222
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt install -y nodejs
WORKDIR /src
COPY ["src/WebUI/WebUI.csproj", "src/WebUI/"]
COPY ["src/Application/Application.csproj", "src/Application/"]
COPY ["src/Domain/Domain.csproj", "src/Domain/"]
COPY ["src/Infrastructure/Infrastructure.csproj", "src/Infrastructure/"]
RUN dotnet restore "src/WebUI/WebUI.csproj"
COPY . .
WORKDIR "/src/src/WebUI"
RUN dotnet build "WebUI.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "WebUI.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "CleanArchitecture.WebUI.dll"]
Can someone help me figure out how to set a certificate for kestral inside a Linux container?
thanks in advance
Upvotes: 3
Views: 7889
Reputation: 53411
Is it possible that your docker-compose
file has an error in the definition of the service volumes
?
You have the following docker-compose
fragment for your service:
environment:
- UseInMemoryDatabase=false
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_Kestrel__Certificates__Default__Path=/security/mycert.pfx
- "ASPNETCORE_Kestrel__Certificates__Default__Password=Your_password123"
ports:
- "5000:5000"
- "5001:5001"
volumes:
- fsmount001: /security:/security
- /var/ssl/private:/https
With this setup you are trying to create two volumes.
On one hand, you are mapping the /var/ssl/private
path in the host system to the /https
container destination. It should work fine.
But, on the other hand, I think you are mixing syntax for named volumes and volumes based on path mapping.
For your update you are trying to use an Azure File storage mount. Then you need to modify your service volumes
definition as follows:
environment:
...
ports:
...
volumes:
- fsmount001:/security
- /var/ssl/private:/https
As indicated in the documentation, it is important to understand that the mount path corresponds to the folder inside the container that you want to mount to Azure Storage:
The mount path setting corresponds to the folder inside the container that you want to mount to Azure Storage. Setting it to '/' mounts the entire container to Azure Storage.
Please, also note that the path provided for fsmount001
in your docker-compose
file is the same as the mount path indicated when you created the mount, /security
in this case.
With this setup, you need to configure the certificate location like this:
- ASPNETCORE_Kestrel__Certificates__Default__Path=/security/security/mycert.pfx
The first /security
for the path in the container, and the second for the directory in which your pfx is included in the file share.
UPDATE
After reviewing your Dockerfile
and docker-compose
files together, I think your problem could be motivated not for the actual file share, but because the environment variables required to setup your HTTPS are not visible inside the docker container because they are used only in its build phase. Please, see this I think related stack overflow question.
You need to provide this environment information directly in your Dockerfile
or indirectly using ARG
s in your docker-compose
file.
For example, modify your docker-compose
file as follows - basically, change your environment
entry for args
:
services:
webui:
image: ${DOCKER_REGISTRY-}webui
build:
context: .
dockerfile: src/WebUI/Dockerfile
args:
- UseInMemoryDatabase=false
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=https://+:443;http://+:80
- ConnectionStrings__DefaultConnection=****
- ASPNETCORE_Kestrel__Certificates__Default__Path=/secure/mycert.pfx
- ASPNETCORE_Kestrel__Certificates__Default__Password="Your_password123"
ports:
- "5000:5000"
- "5001:5001"
volumes:
- fsmount001: /secure
- ~/var/ssl/private:/https
restart: always
volumes:
fsmount001:
driver: azure_file
driver_opts:
share_name: st-*****tus
storage_account_name: st********001
And them modify your Dockerfile
to read the provided build arguments:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
ARG UseInMemoryDatabase
ENV UseInMemoryDatabase=$UseInMemoryDatabase
ARG ASPNETCORE_ENVIRONMENT
ENV ASPNETCORE_ENVIRONMENT=$ASPNETCORE_ENVIRONMENT
ARG ASPNETCORE_URLS=https://+:5001;http://+:5000
ENV ASPNETCORE_URLS=$ASPNETCORE_URLS
ARG ConnectionStrings__DefaultConnection
ENV ConnectionStrings__DefaultConnection=$ConnectionStrings__DefaultConnection
ARG ASPNETCORE_Kestrel__Certificates__Default__Path
ENV ASPNETCORE_Kestrel__Certificates__Default__Path=$ASPNETCORE_Kestrel__Certificates__Default__Path
ARG ASPNETCORE_Kestrel__Certificates__Default__Password
ENV ASPNETCORE_Kestrel__Certificates__Default__Password=$ASPNETCORE_Kestrel__Certificates__Default__Password
WORKDIR /app
EXPOSE 5000 5001 2222
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt install -y nodejs
WORKDIR /src
COPY ["src/WebUI/WebUI.csproj", "src/WebUI/"]
COPY ["src/Application/Application.csproj", "src/Application/"]
COPY ["src/Domain/Domain.csproj", "src/Domain/"]
COPY ["src/Infrastructure/Infrastructure.csproj", "src/Infrastructure/"]
RUN dotnet restore "src/WebUI/WebUI.csproj"
COPY . .
WORKDIR "/src/src/WebUI"
RUN dotnet build "WebUI.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "WebUI.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "CleanArchitecture.WebUI.dll"]
Please, modify it as you consider appropriate. Pay attention especially at the moment in which the different ARG
s and ENV
s should be defined because they are scoped per build-stage, and will not be preserved in the next stage. You can try as is, or you can define the ARG
s in base
and the ENV
s in final
, as one extend from the other the ARG
s variables should be visible in both.
Upvotes: 3