各位大佬,简而言之:无法启动从docker镜像连接到MS SQL数据库的项目,出现错误
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly
'Microsoft.Data.SqlClient, Version=5.0.0.0, Culture=neutral, PublicKeyToken=23ec7fc2d6eaa4a5'.
The system cannot find the file specified.
File name: 'Microsoft.Data.SqlClient, Version=5.0.0.0, Culture=neutral, PublicKeyToken=23ec7fc2d6eaa4a5'
通过错误的措辞搜索网络会导致像这样的相当愚蠢的话题
尝试使用以前版本的 Microsoft.Data.SqlClient,甚至使用 Net Core 5.0 而不是 6.0,也都不起作用。
该怎么办?
现在详细说一下。
我正在做的是在 Net Core 上编写一个简单的控制台程序,该程序需要连接到数据库并执行查询。
对于这个问题,我做了一个单独的回购
https://github.com/junecat/SqlDemoCsharp
从字面上看,这是它的“内容”部分:
using (SqlConnection conn = new SqlConnection(sqlCnStr))
{
conn.Open();
using (StreamWriter w = File.AppendText(fPath))
w.WriteLine("Conection opened!");
const string sqlSel = "select count(*) from Table1";
using (SqlCommand cmd = new SqlCommand(sqlSel, conn))
{
int rez = (int)cmd.ExecuteScalar();
using (StreamWriter w = File.AppendText(fPath))
w.WriteLine($"count = {rez}");
}
}
为了创建这个项目 - 我使用最简单的命令
dotnet new console
和
dotnet add package Microsoft.Data.SqlClient
然后我在项目中添加一些代码,保存、编译、运行——一切正常!
在 Windows 下。
输出到文件
Hello, from SQL test program...
Conection opened!
count = 6
现在我正在尝试在 Linux 虚拟机中构建这个项目:
dotnet publish -c release
cd /home/konst/SqlDemoCsharp/SqlDemoCsharp/bin/Release/net6.0/publish/
dotnet SqlDemoCsharp.dll
一切正常,Logs/Logfile.log同样的三行可见,说明项目已经启动,连接SQL并执行查询。
现在我正在尝试在 docker 映像中做同样的事情。
实际上,整个构建和运行过程包含在两个 Dockerfile 和两个 sh 文件中:
集会:
码头文件:
FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y wget
RUN wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
RUN dpkg -i packages-microsoft-prod.deb
RUN rm packages-microsoft-prod.deb
RUN apt-get update
RUN apt-get install -y apt-transport-https
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
RUN apt-get install -y dotnet-sdk-6.0
# dotnet sdk is installed!
COPY ./SqlDemoCsharp /App/SqlDemoCsharp
WORKDIR /App/SqlDemoCsharp
RUN dotnet publish -c release
CMD mkdir /App/publish-output/
CMD cp -r /App/SqlDemoCsharp/bin/Release/net6.0/publish/* /App/publish-output
.sh 文件:
docker build -t build_sql_demo-image -f Dockerfile .
docker run -it --name build_sql_demo-cont -v ~/SqlDemoCsharp/publish-output:/App/publish-output -d build_sql_demo-image
发射:
码头文件2:
FROM mcr.microsoft.com/dotnet/aspnet:6.0
ENV TZ=Europe/Moscow
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
COPY publish-output/* /App/
WORKDIR /App
ENTRYPOINT ["dotnet", "SqlDemoCsharp.dll"]
.sh 文件:
docker build -t run_sql_demo-image -f Dockerfile2 .
docker run -it --name run_sql_demo-cont -v ~/SqlDemoCsharp/Logs/:/App/Logs/ -d run_sql_demo-image
启动容器后,日志中没有写入任何内容,执行后,docker logs run_sql_demo-cont我看到一个不幸的错误:
Unhandled exception. System.IO.FileNotFoundException:
Could not load file or assembly 'Microsoft.Data.SqlClient, Version=5.0.0.0, Culture=neutral, PublicKeyToken=23ec7fc2d6eaa4a5'.
The system cannot find the file specified.
File name: 'Microsoft.Data.SqlClient, Version=5.0.0.0, Culture=neutral, PublicKeyToken=23ec7fc2d6eaa4a5'
Microsoft.Data.SqlClient而且,当然,我在组装过程中没有得到一个具有确切名称的文件,但是 Microsoft.Data.SqlClient.dll 文件已经出现了 3 次:
konst@pve:~/SqlDemoCsharp$ find . -name Microsoft.Data.SqlClient.dll
./publish-output/runtimes/win/lib/netcoreapp3.1/Microsoft.Data.SqlClient.dll
./publish-output/runtimes/unix/lib/netcoreapp3.1/Microsoft.Data.SqlClient.dll
./publish-output/Microsoft.Data.SqlClient.dll
如果您搜索运行应用程序的 Linux 虚拟机的文件系统,您可以看到相同的 DLL 位于相同的路径中:
konst@ucs117:~$ cd SqlDemoCsharp/
konst@ucs117:~/SqlDemoCsharp$ sudo find . -name Microsoft.Data.SqlClient.dll
./SqlDemoCsharp/bin/Release/net6.0/runtimes/unix/lib/netcoreapp3.1/Microsoft.Data.SqlClient.dll
./SqlDemoCsharp/bin/Release/net6.0/runtimes/win/lib/netcoreapp3.1/Microsoft.Data.SqlClient.dll
./SqlDemoCsharp/bin/Release/net6.0/publish/runtimes/unix/lib/netcoreapp3.1/Microsoft.Data.SqlClient.dll
./SqlDemoCsharp/bin/Release/net6.0/publish/runtimes/win/lib/netcoreapp3.1/Microsoft.Data.SqlClient.dll
./SqlDemoCsharp/bin/Release/net6.0/publish/Microsoft.Data.SqlClient.dll
./SqlDemoCsharp/bin/Release/net6.0/Microsoft.Data.SqlClient.dll
这里在 find 命令的输出中有 6 行而不是 3 行,但这是因为应用程序有一个单独的目录,以及一个单独的目录 Publish
另外,我已经阅读了这个“ MS 故障排除指南”,但那里的建议都没有帮助。
一般来说,大自然的奥秘。很明显,由于某种原因,docker“看不到”位于“附近”的文件(或者更确切地说,与应用程序本身的 DLL 位于同一目录中)Microsoft.Data.SqlClient.dll
是的!是的!有效!
在编写问题的过程中,我决定测试假设“如果您在构建过程中指定一个特定平台,您需要为其构建项目会发生什么?”
这是通过将命令从
dotnet publish -c release到指定目标平台 linux-x64 的更完整的命令:
dotnet publish --runtime linux-x64 --self-contained true -c release也就是说,添加了密钥--runtime linux-x64(之后我不得不添加密钥
--self-contained true- 由于构建期间出现的警告)经过这样的澄清,显示组装项目的目录已经从
在
同时,组装好的代码开始在容器中正常运行!
是的,我必须补充一点,
publish-output使用此类密钥构建时目录中的文件数量显着增加!我已经放置了正确文件的示例,以便在问题的存储库中构建。