{"id":4201,"date":"2024-11-11T11:26:42","date_gmt":"2024-11-11T03:26:42","guid":{"rendered":"https:\/\/fwq.ai\/blog\/4201\/"},"modified":"2024-11-11T11:26:42","modified_gmt":"2024-11-11T03:26:42","slug":"%e5%9c%a8%e5%ae%b9%e5%99%a8%e4%b8%ad%e8%bf%90%e8%a1%8c-net-%e6%b5%8b%e8%af%95","status":"publish","type":"post","link":"https:\/\/fwq.ai\/blog\/4201\/","title":{"rendered":"\u5728\u5bb9\u5668\u4e2d\u8fd0\u884c .NET \u6d4b\u8bd5"},"content":{"rendered":"<h1>\u5728\u5bb9\u5668\u4e2d\u8fd0\u884c .NET \u6d4b\u8bd5<\/h1>\n<h2><\/h2>\n<p>\u5f00\u59cb\uff0c\u5b8c\u6210\u672c\u6307\u5357\u524d\u9762\u7684\u6240\u6709\u90e8\u5206 \u3002<\/p>\n<h2><\/h2>\n<p>\u6d4b\u8bd5\u662f\u73b0\u4ee3\u8f6f\u4ef6\u5f00\u53d1\u7684\u91cd\u8981\u7ec4\u6210\u90e8\u5206\u3002\u6d4b\u8bd5\u5bf9\u4e8e\u4e0d\u540c\u7684\u5f00\u53d1\u56e2\u961f\u6765\u8bf4\u610f\u5473\u7740\u5f88\u591a\u4e8b\u60c5\u3002\u6709\u5355\u5143\u6d4b\u8bd5\u3001\u96c6\u6210\u6d4b\u8bd5\u548c\u7aef\u5230\u7aef\u6d4b\u8bd5\u3002\u5728\u672c\u6307\u5357\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u5728\u5f00\u53d1\u548c\u6784\u5efa\u65f6\u5728 Docker \u4e2d\u8fd0\u884c\u5355\u5143\u6d4b\u8bd5\u3002<\/p>\n<h2><\/h2>\n<p>\u793a\u4f8b\u5e94\u7528\u7a0b\u5e8f\u7684<code>tests<\/code>\u76ee\u5f55\u4e2d\u5df2\u7ecf\u6709\u4e00\u4e2a xUnit \u6d4b\u8bd5\u3002\u5728\u672c\u5730\u5f00\u53d1\u65f6\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528 Compose \u6765\u8fd0\u884c\u6d4b\u8bd5\u3002<\/p>\n<p>\u5728\u76ee\u5f55\u4e2d\u8fd0\u884c\u4ee5\u4e0b\u547d\u4ee4<code>docker-dotnet-sample<\/code>\u4ee5\u5728\u5bb9\u5668\u5185\u8fd0\u884c\u6d4b\u8bd5\u3002<\/p>\n<p><span> <\/span><br \/>\n<span> <\/span> <\/p>\n<pre><code><span><span><span>$<\/span> docker compose run --build --rm server dotnet <span>test<\/span> \/source\/tests <\/span><\/span><\/code><\/pre>\n<p>\u60a8\u5e94\u8be5\u770b\u5230\u5305\u542b\u4ee5\u4e0b\u5185\u5bb9\u7684\u8f93\u51fa\u3002<\/p>\n<p><span> <\/span><br \/>\n<span> <\/span> <\/p>\n<pre><code><span><span><span>Starting test execution, please wait... <\/span><\/span><\/span><span><span><span>A total of 1 test files matched the specified pattern. <\/span><\/span><\/span><span><span><span><\/span><span> <\/span><\/span><\/span><span><span><span><\/span><span>Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: &lt; 1 ms - \/source\/tests\/bin\/Debug\/net6.0\/tests.dll (net6.0) <\/span><\/span><\/span><\/code><\/pre>\n<p>\u8981\u4e86\u89e3\u6709\u5173\u8be5\u547d\u4ee4\u7684\u66f4\u591a\u4fe1\u606f\uff0c\u8bf7\u53c2\u9605 \u3002<\/p>\n<h2><\/h2>\n<p>\u8981\u5728\u6784\u5efa\u65f6\u8fd0\u884c\u6d4b\u8bd5\uff0c\u60a8\u9700\u8981\u66f4\u65b0 Dockerfile\u3002\u60a8\u53ef\u4ee5\u521b\u5efa\u4e00\u4e2a\u8fd0\u884c\u6d4b\u8bd5\u7684\u65b0\u6d4b\u8bd5\u9636\u6bb5\uff0c\u6216\u5728\u73b0\u6709\u6784\u5efa\u9636\u6bb5\u8fd0\u884c\u6d4b\u8bd5\u3002\u5bf9\u4e8e\u672c\u6307\u5357\uff0c\u66f4\u65b0 Dockerfile \u4ee5\u5728\u6784\u5efa\u9636\u6bb5\u8fd0\u884c\u6d4b\u8bd5\u3002<\/p>\n<p>\u4ee5\u4e0b\u662f\u66f4\u65b0\u540e\u7684 Dockerfile\u3002<\/p>\n<p><span> <\/span><br \/>\n<span> <\/span> <\/p>\n<pre><code><span><span><span># syntax=docker\/dockerfile:1<\/span><span> <\/span><\/span><\/span><span><span><span> <\/span><\/span><\/span><span><span><span><\/span><span>FROM<\/span><span> --platform=$BUILDPLATFORM mcr.microsoft.com\/dotnet\/sdk:6.0-alpine AS build<\/span><span> <\/span><\/span><\/span><span><span><span><\/span><span>ARG<\/span> TARGETARCH<span> <\/span><\/span><\/span><span><span><span><\/span><span>COPY<\/span> . \/source<span> <\/span><\/span><\/span><span><span><span><\/span><span>WORKDIR<\/span><span> \/source\/src<\/span><span> <\/span><\/span><\/span><span><span><span><\/span><span>RUN<\/span> --mount<span>=<\/span><span>type<\/span><span>=<\/span>cache,id<span>=<\/span>nuget,target<span>=<\/span>\/root\/.nuget\/packages <span>\\ <\/span><\/span><\/span><span><span><span><\/span> dotnet publish -a <span>${<\/span><span>TARGETARCH<\/span><span>\/amd64\/x64<\/span><span>}<\/span> --use-current-runtime --self-contained <span>false<\/span> -o \/app<span> <\/span><\/span><\/span><span><span><span><\/span><span>RUN<\/span> dotnet <span>test<\/span> \/source\/tests<span> <\/span><\/span><\/span><span><span><span> <\/span><\/span><\/span><span><span><span><\/span><span>FROM<\/span><span> mcr.microsoft.com\/dotnet\/sdk:6.0-alpine AS development<\/span><span> <\/span><\/span><\/span><span><span><span><\/span><span>COPY<\/span> . \/source<span> <\/span><\/span><\/span><span><span><span><\/span><span>WORKDIR<\/span><span> \/source\/src<\/span><span> <\/span><\/span><\/span><span><span><span><\/span><span>CMD<\/span> dotnet run --no-launch-profile<span> <\/span><\/span><\/span><span><span><span> <\/span><\/span><\/span><span><span><span><\/span><span>FROM<\/span><span> mcr.microsoft.com\/dotnet\/aspnet:6.0-alpine AS final<\/span><span> <\/span><\/span><\/span><span><span><span><\/span><span>WORKDIR<\/span><span> \/app<\/span><span> <\/span><\/span><\/span><span><span><span><\/span><span>COPY<\/span> --from<span>=<\/span>build \/app .<span> <\/span><\/span><\/span><span><span><span><\/span><span>ARG<\/span> <span>UID<\/span><span>=<\/span><span>10001<\/span> <\/span><\/span><span><span><span>RUN<\/span> adduser <span>\\ <\/span><\/span><\/span><span><span><span><\/span> --disabled-password <span>\\ <\/span><\/span><\/span><span><span><span><\/span> --gecos <span>\"\"<\/span> <span>\\ <\/span><\/span><\/span><span><span><span><\/span> --home <span>\"\/nonexistent\"<\/span> <span>\\ <\/span><\/span><\/span><span><span><span><\/span> --shell <span>\"\/sbin\/nologin\"<\/span> <span>\\ <\/span><\/span><\/span><span><span><span><\/span> --no-create-home <span>\\ <\/span><\/span><\/span><span><span><span><\/span> --uid <span>\"<\/span><span>${<\/span><span>UID<\/span><span>}<\/span><span>\"<\/span> <span>\\ <\/span><\/span><\/span><span><span><span><\/span> appuser<span> <\/span><\/span><\/span><span><span><span><\/span><span>USER<\/span><span> appuser<\/span><span> <\/span><\/span><\/span><span><span><span><\/span><span>ENTRYPOINT<\/span> <span>[<\/span><span>\"dotnet\"<\/span><span>,<\/span> <span>\"myWebApp.dll\"<\/span><span>]<\/span><\/span><\/span><\/code><\/pre>\n<p>\u8fd0\u884c\u4ee5\u4e0b\u547d\u4ee4\u4ee5\u6784\u5efa\u9636\u6bb5\u4e3a\u76ee\u6807\u6784\u5efa\u955c\u50cf\u5e76\u67e5\u770b\u6d4b\u8bd5\u7ed3\u679c\u3002\u5305\u62ec<code>--progress=plain<\/code>\u67e5\u770b\u6784\u5efa\u8f93\u51fa\u3001<code>--no-cache<\/code>\u786e\u4fdd\u6d4b\u8bd5\u59cb\u7ec8\u8fd0\u884c\u4ee5\u53ca<code>--target build<\/code>\u9488\u5bf9\u6784\u5efa\u9636\u6bb5\u3002<\/p>\n<p><span> <\/span><br \/>\n<span> <\/span> <\/p>\n<pre><code><span><span><span>$<\/span> docker build -t dotnet-docker-image-test --progress<span>=<\/span>plain --no-cache --target build . <\/span><\/span><\/code><\/pre>\n<p>\u60a8\u5e94\u8be5\u770b\u5230\u5305\u542b\u4ee5\u4e0b\u5185\u5bb9\u7684\u8f93\u51fa\u3002<\/p>\n<p><span> <\/span><br \/>\n<span> <\/span> <\/p>\n<pre><code><span><span><span>#<\/span><span>11<\/span> <span>[<\/span>build 5\/5<span>]<\/span> RUN dotnet <span>test<\/span> \/source\/tests <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 1.564 Determining projects to restore... <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 3.421 Restored \/source\/src\/myWebApp.csproj <span>(<\/span>in 1.02 sec<span>)<\/span>. <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 19.42 Restored \/source\/tests\/tests.csproj <span>(<\/span>in 17.05 sec<span>)<\/span>. <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 27.91 myWebApp -&gt; \/source\/src\/bin\/Debug\/net6.0\/myWebApp.dll <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 28.47 tests -&gt; \/source\/tests\/bin\/Debug\/net6.0\/tests.dll <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 28.49 Test run <span>for<\/span> \/source\/tests\/bin\/Debug\/net6.0\/tests.dll <span>(<\/span>.NETCoreApp,Version<span>=<\/span>v6.0<span>)<\/span> <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 28.67 Microsoft <span>(<\/span>R<span>)<\/span> Test Execution Command Line Tool Version 17.3.3 <span>(<\/span>x64<span>)<\/span> <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 28.67 Copyright <span>(<\/span>c<span>)<\/span> Microsoft Corporation. All rights reserved. <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 28.68 <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 28.97 Starting <span>test<\/span> execution, please wait... <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 29.03 A total of <span>1<\/span> <span>test<\/span> files matched the specified pattern. <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 32.07 <\/span><\/span><span><span><span>#<\/span><span>11<\/span> 32.08 Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: &lt; <span>1<\/span> ms - \/source\/tests\/bin\/Debug\/net6.0\/tests.dll <span>(<\/span>net6.0<span>)<\/span> <\/span><\/span><span><span><span>#<\/span><span>11<\/span> DONE 32.2s <\/span><\/span><\/code><\/pre>\n<p>\u8981\u4e86\u89e3\u6709\u5173\u6784\u5efa\u548c\u8fd0\u884c\u6d4b\u8bd5\u7684\u66f4\u591a\u4fe1\u606f\uff0c\u8bf7\u53c2\u9605 \u3002<\/p>\n<h2><\/h2>\n<p>\u5728\u672c\u90e8\u5206\u4e2d\uff0c\u60a8\u4e86\u89e3\u4e86\u5982\u4f55\u5728\u4f7f\u7528 Compose \u8fdb\u884c\u672c\u5730\u5f00\u53d1\u65f6\u8fd0\u884c\u6d4b\u8bd5\u4ee5\u53ca\u5982\u4f55\u5728\u6784\u5efa\u6620\u50cf\u65f6\u8fd0\u884c\u6d4b\u8bd5\u3002<\/p>\n<p>\u76f8\u5173\u4fe1\u606f\uff1a<\/p>\n<ul>\n<li><\/li>\n<li><\/li>\n<\/ul>\n<h2><\/h2>\n<p>\u63a5\u4e0b\u6765\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u4f7f\u7528 GitHub Actions \u8bbe\u7f6e CI\/CD \u7ba1\u9053\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5728\u5bb9\u5668\u4e2d\u8fd0\u884c .NET \u6d4b\u8bd5 \u5f00\u59cb\uff0c\u5b8c\u6210\u672c\u6307\u5357\u524d\u9762\u7684\u6240\u6709\u90e8\u5206 \u3002 \u6d4b\u8bd5\u662f\u73b0\u4ee3\u8f6f\u4ef6\u5f00\u53d1\u7684\u91cd\u8981\u7ec4\u6210\u90e8\u5206\u3002\u6d4b\u8bd5\u5bf9\u4e8e\u4e0d\u540c\u7684\u5f00\u53d1\u56e2\u961f\u6765\u8bf4\u610f\u5473\u7740\u5f88\u591a\u4e8b\u60c5\u3002\u6709\u5355\u5143\u6d4b\u8bd5\u3001\u96c6\u6210\u6d4b\u8bd5\u548c\u7aef\u5230\u7aef\u6d4b\u8bd5\u3002\u5728\u672c\u6307\u5357\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u5728\u5f00\u53d1\u548c\u6784\u5efa\u65f6\u5728 Docker \u4e2d\u8fd0\u884c\u5355\u5143\u6d4b\u8bd5\u3002 \u793a\u4f8b\u5e94\u7528\u7a0b\u5e8f\u7684tests\u76ee\u5f55\u4e2d\u5df2\u7ecf\u6709\u4e00\u4e2a xUnit \u6d4b\u8bd5\u3002\u5728\u672c\u5730\u5f00\u53d1\u65f6\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528 Compose \u6765\u8fd0\u884c\u6d4b\u8bd5\u3002 \u5728\u76ee\u5f55\u4e2d\u8fd0\u884c\u4ee5\u4e0b\u547d\u4ee4docker-dotnet-sample\u4ee5\u5728\u5bb9\u5668\u5185\u8fd0\u884c\u6d4b\u8bd5\u3002 $ docker compose run &#8211;build &#8211;rm server dotnet test \/source\/tests \u60a8\u5e94\u8be5\u770b\u5230\u5305\u542b\u4ee5\u4e0b\u5185\u5bb9\u7684\u8f93\u51fa\u3002 Starting test execution, please wait&#8230; A total of 1 test files matched the specified pattern. Passed! &#8211; Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: &lt; 1 ms &#8211; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[],"class_list":["post-4201","post","type-post","status-publish","format-standard","hentry","category-docker"],"_links":{"self":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/4201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/comments?post=4201"}],"version-history":[{"count":0,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/4201\/revisions"}],"wp:attachment":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/media?parent=4201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/categories?post=4201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/tags?post=4201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}