我正在运行带有 Docker 容器的 Ubuntu 服务器,其中包含我的 ASP .NET 网站。在切换到使用 HTTPS 之前我能够正常运行它,但现在当我运行我的容器时,我收到以下错误。
app_1 | warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
app_1 | Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
app_1 | Unhandled exception. Interop+Crypto+OpenSslCryptographicException: error:2006D080:BIO routines:BIO_new_file:no such file
at Interop.Crypto.CheckValidOpenSslHandle(SafeHandle handle)
at Internal.Cryptography.Pal.OpenSslX509CertificateReader.FromFile(String fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(String fileName, String password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password)
at Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(ListenOptions listenOptions, String fileName, String password)
现在我认为问题是我的容器正在努力读取 SSL 证书,因为它位于容器外部。我假设我在
docker-compose
内设置了错误的音量或其他什么东西,但我已经尝试修复它有一段时间了,而且我不确定问题到底是什么,因为密钥存在。我还制作了许多不同的 SSL 证书,除了我转而使用 ASP .NET 而不是 nginx 来尝试之外,之前从未遇到过任何问题。
:~# ls /etc/letsencrypt/live/example.com/privkey.pem
/etc/letsencrypt/live/example.com/privkey.pem
现在这是我在
docker-compose
内的音量部分。
volumes:
- /etc/letsencrypt/live/example.com/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro
- /etc/letsencrypt/live/example.com/privkey.pem:/etc/ssl/private/privkey.pem:ro
现在这是我的 Program 类中的
CreateHostBuilder
方法。
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>()
.UseKestrel(options =>
{
options.ListenAnyIP(80); // HTTP
options.ListenAnyIP(443, listenOptions =>
{
listenOptions.UseHttps("/etc/ssl/certs/fullchain.pem", "/etc/ssl/private/privkey.pem");
});
});
});
我还尝试将这些文件的 chmod 更改为 644,但这没有做任何事情,有人知道问题可能是什么吗?
用于识别容器内关键相关问题的初始故障排除步骤:
cat
找到钥匙和秘密吗?cat
密钥/秘密?ls
存储密钥的每个父目录?如果您可以
cat
钥匙和 ls
家长,则您的问题出在应用程序内部。
处理 LetsEncrypt 证书时,最常见的两个问题是权限和符号链接。对于权限,访问用户必须具有密钥的读取权限以及所有父目录的执行权限。由于 LetsEncrypt 经常使用
root:root
权限写入密钥,因此您的容器可能无法访问它们。用于将权限从主机转换为容器的 setuid
和 setgid
映射在容器实现之间存在显着差异。
还请记住,您链接到的证书从技术上讲是符号链接,而不是文件。在许多情况下,符号链接无法跨抽象层正确处理。这就是为什么尝试
cat
文件本身的内容,以验证它们不仅仅是“空占位符”很重要。