Если ваше приложение работает в контейнере и использует российский сервис, например, для отправки сообщений через мессенджер Макс, то для корректной работы недостаточно установить сертификаты Минцифры на уровне операционной системы. Дело в том, что сертификаты, установленные на вашем компьютере или сервере, не видны внутри Docker-контейнера автоматически. У контейнера своя изолированная файловая система, поэтому нужные корневые сертификаты нужно устанавливать заново прямо в образе, чтобы решить эту проблему, корневой сертификат должен быть добавлен прямо в Dockerfile вашего микросервиса.
Для .NET-приложений, работающих в Docker, есть два надёжных способа настроить доверие к сертификатам Минцифры:
- Через системное хранилище сертификатов (ca-certificates).
- Через переменную окружения
SSL_CERT_FILE, которая принудительно указывает путь к PEM-файлу.
Ниже приведены оба варианта реализации в Dockerfile.
Вариант 1: Установка в системное хранилище (рекомендуется для curl/wget и нативного HttpClient) Этот метод обновляет глобальный список доверенных центров сертификации внутри образа.
FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble AS base
# Устанавливаем пакет для работы с системными сертификатами
RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates wget && \
rm -rf /var/lib/apt/lists/*
# Создаём директорию для российских сертификатов
WORKDIR /usr/local/share/ca-certificates/russian-trusted/
# Скачиваем актуальные корневой и выпускающий сертификаты напрямую
# (Эти ссылки ведут на инфраструктуру Госуслуг/НУЦ)
RUN wget https://gu-st.ru/content/lending/russian_trusted_root_ca_pem.crt -O russian_trusted_root_ca.crt && \
wget https://gu-st.ru/content/lending/russian_trusted_sub_ca_pem.crt -O russian_trusted_sub_ca.crt
# Возвращаемся в корень и обновляем системный bundle
WORKDIR /
RUN cat /usr/local/share/ca-certificates/russian-trusted/*.crt > /usr/local/share/ca-certificates/russian_trusted_ca_bundle.crt && \
update-ca-certificates
WORKDIR /app
COPY ./bin/Release/net10.0/publish/ .
ENTRYPOINT ["dotnet", "YourAppName.dll"]
В этом случае большинство инструментов (.NET HttpClient при использовании стандартных настроек, curl) начнут видеть цепочку доверия автоматически.
Вариант 2: Использование переменной SSL_CERT_FILE (универсальный вариант для SslStream) Если ваше приложение использует кастомные настройки HttpClientHandler или работает с низкоуровневым SslStream, надёжнее всего явно указать файл со всеми корнями.
FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble AS base
# Копируем заранее скачанные сертификаты из контекста сборки в образ
# Положите файлы russian_trusted_root_ca.crt и russian_trusted_sub_ca.crt рядом с Dockerfile
COPY ./certs/ /usr/local/share/ca-certificates/russian-trusted/
# Объединяем их в один бандл (это удобнее для передачи в ENV)
RUN cat /usr/local/share/ca-certificates/russian-trusted/*.crt > /usr/local/share/ca-certificates/russian_trusted_ca_bundle.crt
# Указываем среде выполнения .NET использовать этот файл
ENV SSL_CERT_FILE=/usr/local/share/ca-certificates/russian_trusted_ca_bundle.crt
WORKDIR /app
COPY ./bin/Release/net10.0/publish/ .
ENTRYPOINT ["dotnet", "YourAppName.dll"]
Среда выполнения .NET по умолчанию пытается использовать либо системное хранилище OpenSSL, либо собственное внутреннее хранилище корней. Переменная SSL_CERT_FILE переопределяет это поведение, заставляя библиотеку System.Net.Security загружать доверенные центры именно из указанного файла.
Важное замечание по безопасности: никогда не копируйте приватные ключи (*.key, .pfx без пароля) в публичные Docker-образы. В примерах выше используются только открытые корневые сертификаты (файлы .crt или .pem), которые содержат лишь открытый ключ центра сертификации и предназначены для публичного распространения.