Dockertools: Support ASP.NET Core user secrets

Created on 6 Jun 2017  Â·  13Comments  Â·  Source: microsoft/DockerTools

_Original post by @chrisoverzero: https://github.com/aspnet/Configuration/issues/659_


Summary: User secrets cannot (easily, portably) be used with Visual Studio's "Docker Support" feature for ASP.NET Core projects.

Hi! I've been using User Secrets for a while in several ASP.NET Core projects. My company is evaluating a move to Docker for deployments, and – as part of that evaluation – I activated the Docker Support feature in Visual Studio. After this, the application completely failed to reference my secrets.

I've worked around this for my own support by bind-mounting (in docker-compose.override.yml) the secrets.json file on my development box to the correct location in the Linux container, but this seems to violate Microsoft's advice:

You should not write code that depends on the location or format of the data saved
with the Secret Manager tool, as these implementation details might change.

...in addition to not being portable between our Windows and Linux developers.

Versions of things

  • Microsoft.Extensions.Configuration.UserSecrets: 1.1.1
  • Microsoft.Extensions.SecretManager.Tools: 1.0.0
  • Visual Studio: 15.1 (26403.7)

_Comment by @natemcmaster: https://github.com/aspnet/Configuration/issues/659#issuecomment-301912883_

The advice was written with authors of third-party class libraries and tools in mind. The location of the files is not "under contract" so your docker-compose file might break in future versions. However, until that happens, volume mounting the user secrets location for development environments is fine, and seems like something Docker Tooling could consider doing by default.

That said, mounting UserSecrets for production is not recommended. For production secrets, checkout https://github.com/aspnet/Configuration/tree/dev/src/Microsoft.Extensions.Configuration.DockerSecrets

Most helpful comment

@RunnX very good! helped a lot!

I'd even extend it to be more machine independent and use %APPDATA% variable or $HOME:

environment:
  - ASPNETCORE_ENVIRONMENT=Development
  - USER_SECRETS_ID=<your user secret id>
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

More details at http://blog.matjanowski.pl/2017/11/18/managing-options-and-secrets-in-net-core-and-docker

Best, Kuba.

All 13 comments

I think the simplest solution would be for docker tools to volume mount %APPDATA%\microsoft\UserSecrets\ to ~/.microsoft/usersecrets/ when creating a new container.

cc @sgreenmsft @yanchenw

I can't seem to figure out how to even do this in docker compose. I don't think you can you can use %APPDATA% directly so I use the full folder path. No errors but my secrets don't appear. I'm not sure if the aspnetcore:2.0 docker image has
https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?tabs=visual-studio

csproj:
<UserSecretsId>918f68d1-483b-46d1-8556-717af3673207</UserSecretsId>

docker-compose:

version: '2'
services:
  postgres:
    container_name: 'postgres'
    image: postgres
    restart: always
    ports:
       - 5432:5432
  main.web:
    image: main.web
    ports:
       - 8080:80
    volumes:
      - C:\Users\FakeUser\AppData\Roaming\Microsoft\UserSecrets\:/.microsoft/usersecrets/
    build:
      context: ./Main.Web
      dockerfile: Dockerfile
    depends_on:
     - "postgres"

startup.cs:

public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                //this works:    .AddJsonFile("/.microsoft/usersecrets/918f68d1-483b-46d1-8556-717af3673207/secrets.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); 

            if (env.IsDevelopment())
            { --this is hit, does not throw an error but no config values are pulled in
                builder.AddUserSecrets<Startup>(optional:false);
            }

            Configuration = builder.Build();
        }

@TotzkePaul - I was having similar issues as you with the volume.
volumes:
- C:\Users\FakeUser\AppData\Roaming\Microsoft\UserSecrets\:/.microsoft/usersecrets/

Needs to change to the following:
volumes:
- C:\Users\FakeUser\AppData\Roaming\Microsoft\UserSecrets\:/root/.microsoft/usersecrets/

I found the details at http://www.natemcmaster.com/blog/2017/11/13/dotnet-watch-and-docker/

Regards,
Michael R. Blevins

@RunnX very good! helped a lot!

I'd even extend it to be more machine independent and use %APPDATA% variable or $HOME:

environment:
  - ASPNETCORE_ENVIRONMENT=Development
  - USER_SECRETS_ID=<your user secret id>
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

More details at http://blog.matjanowski.pl/2017/11/18/managing-options-and-secrets-in-net-core-and-docker

Best, Kuba.

This issue is being closed as an inactive issue. If you wish to keep it active, please re-open with any additional context for our consideration, we are happy to take a look!

Is it possible that this is still not working for windows containers? I attached to my containers powershell and saw the file with the content exists but the configuration provider were searching in some other place like C:// app
My volume is mapped in

  - ${APPDATA}/ASP.NET/Https:C:\Users\ContainerUser\AppData\Roaming\ASP.NET\Https:ro

but the config data wasn´t loaded even if I used builder.AddUserSecret. It worked outside from docker

@RichyP7 Yes, most likely this is still occurring. We closed many issues that hadn't been updated in a while, but we're happy to reopen those that are still relevant.

https://developercommunity.visualstudio.com/content/problem/508586/user-secrets-arent-loaded-in-docker-compose-for-wi.html
for windows server sac 2016 nanoserver image this solution is working. But it seems to depend on the image

@RichyP7 That's correct. We're putting in changes for a future release that will map the UserSecrets folder for all ASP.NET Core web apps, however, since SAC2016 is different (ContainerAdministrator instead of ContainerUser), it will still require the manual mapping in the Developer Community post you linked. Versions newer than SAC2016 should not have this issue.

Hi @RichyP7
I believe this issue to be resolved. Please feel free to reopen or create a new issue if the problem persists.

Does solution in the link mentioned by RichyP7 still apply?

@pratiksanglikar What is the solution?

Hi @jgauffin, the newer version of the tooling now maps the UserSecrets volume for all ASP.NET Core apps.
You can access the user secrets directly using this.Configuration["SecretKey"].

Was this page helpful?
0 / 5 - 0 ratings