ASP.NET Docker容器无法读取外部SSL证书问题求助
问题
在Ubuntu服务器上运行承载ASP.NET网站的Docker容器,此前HTTP运行正常,切换为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)
已确认证书文件存在:
:~# 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"); }); }); });
已尝试将证书文件权限改为644,但问题依旧,请问可能是什么原因?
可能的原因及解决办法
Let's Encrypt证书软链接无法被容器解析
Let's Encryptlive目录下的证书文件是软链接,实际指向/etc/letsencrypt/archive目录中的真实文件。直接挂载软链接到容器内,容器无法识别链接对应的真实路径,导致找不到文件。
解决方法:- 挂载
archive目录下的真实证书文件:
注意:volumes: - /etc/letsencrypt/archive/example.com/fullchain1.pem:/etc/ssl/certs/fullchain.pem:ro - /etc/letsencrypt/archive/example.com/privkey1.pem:/etc/ssl/private/privkey.pem:rofullchain1.pem和privkey1.pem的数字会随证书更新变化,后续更新需同步修改路径。 - 或直接挂载整个
/etc/letsencrypt目录,同时修改Program中的路径:volumes: - /etc/letsencrypt:/etc/letsencrypt:rolistenOptions.UseHttps("/etc/letsencrypt/live/example.com/fullchain.pem", "/etc/letsencrypt/live/example.com/privkey.pem");
- 挂载
容器内用户无证书目录访问权限
即使证书文件权限设为644,容器内运行ASP.NET的非root用户可能无法访问/etc/ssl/private目录(默认权限700,仅root可访问)。
解决方法:- 临时测试可在docker-compose中指定root用户运行(不推荐生产环境):
user: "root" - 修改宿主机证书目录权限,让容器用户可读:
chmod -R 755 /etc/letsencrypt/archive/example.com chmod -R 644 /etc/letsencrypt/archive/example.com/*.pem - 生产环境推荐在Dockerfile中创建专用用户组,赋予证书目录访问权限后用该用户运行应用。
- 临时测试可在docker-compose中指定root用户运行(不推荐生产环境):
路径拼写或挂载一致性问题
检查Program中的路径与docker-compose挂载路径是否完全一致(Linux路径区分大小写),可进入容器验证文件是否存在:docker exec -it <容器名> bash ls -l /etc/ssl/certs/fullchain.pem ls -l /etc/ssl/private/privkey.pem证书与私钥不匹配
确认fullchain.pem和privkey.pem是配对的,可在宿主机验证:openssl x509 -noout -modulus -in /etc/letsencrypt/live/example.com/fullchain.pem | openssl md5 openssl rsa -noout -modulus -in /etc/letsencrypt/live/example.com/privkey.pem | openssl md5两个命令输出的MD5值需一致,否则证书与私钥不匹配。
内容的提问来源于stack exchange,提问作者UnSure
相关产品推荐
相关产品推荐

