之前我寫過一篇使用 docker 部署 AspNetCore 應用的文章,這種方式搭配 CICD 非常方便, build 之後 push 到私有的 dockerhub ,在生產伺服器上 pull 下來映象就可以直接執行了。
然而,有時需要一種更傳統的部署方式,比如在本地打包可執行檔案之後直接放到伺服器上執行。
.NetCore 打包可執行檔案有兩種方式
前者雖然方便,但打包出來比較大,據說在 .net8 版本會有優化,但後面的事後面再說,本文記錄第二種方式,框架依賴,搭配 docker 部署,這樣就無需在伺服器上安裝 runtime 了。
(PS:有點Java部署內味了)
這種方式設定完成之後,每次更新只需要重新本地重新 publish 後把可執行檔案上傳覆蓋伺服器上的版本即可,非常方便~
每次打包會生成一堆 pdb 偵錯檔案,但部署的時候我們不需要這些檔案,可以通過設定 .csproj 檔案關閉。
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
更好的方式是在解決方案的目錄下建立 common.props
檔案,把以上設定放在這個檔案中,然後每個 .csproj 都參照這個檔案,具體路徑根據實際情況而定。
<Import Project="../../common.props" />
使用以下命令打包
dotnet publish -f net7.0 -c Release -p:PublishSingleFile=true
打包之後生成一個需要依賴 runtime 執行的可執行檔案,接下來準備一下 docker 的設定。
官方的 dockerfile 包含從原始碼構建到部署的整個流程,我們這裡只需要 base
和 final
,也就是把可執行檔案放進去微軟的基礎映象裡執行。
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM base AS final
WORKDIR /app
COPY . .
ENTRYPOINT ["./AIHub.Blazor"]
不想每次都打一堆 docker 的命令,或者不想寫 bash 指令碼的話,docker-compose 是最好的選擇,還可以很方便的和其他容器編排使用。
version: '3.6'
services:
web:
image: ${DOCKER_REGISTRY-}web
container_name: aihub
restart: always
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://+:80
build:
context: .
volumes:
- .:/app
ports:
- "12001:80"
networks:
- default
- swag
networks:
swag:
name: swag
external: true
default:
name: aihub
補充:
ports
節點對映了容器內的 80 埠ports
對映埠使用命令列啟動!
docker compose up
如果沒有對映埠的話,還需要接著設定一下反向代理。
直接上設定
/path/to/swag/config/nginx/proxy-confs/aihub.subdomain.conf
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name aihub.*;
include /config/nginx/ssl.conf;
client_max_body_size 0;
# enable for ldap auth, fill in ldap details in ldap.conf
#include /config/nginx/ldap.conf;
# enable for Authelia
#include /config/nginx/authelia-server.conf;
location / {
# enable the next two lines for http auth
#auth_basic "Restricted";
#auth_basic_user_file /config/nginx/.htpasswd;
# enable the next two lines for ldap auth
#auth_request /auth;
#error_page 401 =200 /ldaplogin;
# enable for Authelia
#include /config/nginx/authelia-location.conf;
include /config/nginx/proxy.conf;
include /config/nginx/resolver.conf;
set $upstream_app aihub;
set $upstream_port 80;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
proxy_hide_header X-Frame-Options; # Possibly not needed after Portainer 1.20.0
}
}