前言:
本文主要內容是docker部署netcore應用以及docker運行nginx實作負載均衡,到目前為止感覺微軟在跨平臺的方面雖然有較大的進步,但是和linux比還是有一定的差距,在學習docker,nginx以及Netcore 程序中網上能查找參考的資料還是比較有限的,所以在此記錄下遇到的問題以及踩到的各種坑,希望避免再次走彎路,
一.新建NET Core應用程式;
1.添加Docker支持,由于到目前為止,nginx還不支持windows容器,為了便于本機測驗所以選用Linux容器,如下圖:

2.輸出請求處理,顯示當前請求IP以及埠號:

3.編輯Dockerfile檔案
dockerfile檔案指令說明:
FROM -指定基礎鏡像(FROM是必備的指令,并且必須為第一條指令)
WORKDIR-配置作業目錄
EXPOSE-宣告鏡像內服務監聽的埠
COPY-復制內容到鏡像
ENTRYPOINT-啟動鏡像的默認人口命令
ENV -設定環境變數
編輯后的dockerfile檔案如下:
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base WORKDIR /app EXPOSE 8005 EXPOSE 443 ENV ASPNETCORE_URLS http://+:8005 COPY . . ENTRYPOINT ["dotnet", "DockerDemo.dll"]
右鍵屬性,選擇“如果較新則復制”
4.Docker發布,
Release生成解決方案,定位到reliease檔案夾,執行"docker build”指令,如下圖:

在執行程序中,有可能會碰到“no such host”問題,重試幾次或者設定鏡像代理即可
ps: 鏡像版本后面有個空格+“ .”需留意 注意最后有個點,代表使用當前路徑的 Dockerfile 進行構建
運行 docker images查看當前鏡像:

可以看到已經成功構建,
5.構建dockerdemo容器:
執行"docker run“指令,構建該鏡像的實體docker run -d -t -p 8006:8005 --name dockerdemo8006 dockerdemo:1.0,可以看到,容器已經構建成功:

瀏覽器輸入即可看到下列結果

同理構建該鏡像的其他容器,分別為8007,8008;至此docker構建netcore鏡像已經完成,我們可以在Kitematic查看已經構建的容器;

二.Docker構建nginx容器實作負載均衡
1.執行“docker pull nginx“指令獲取鏡像,docker images 查看當前鏡像;
2.構建nginx鏡像容器
執行docker run -d -p 8003:80 --name dockernginxdemo nginx,其中-d表示后臺運行,-p表示開放的埠,將80埠代理到宿主8003埠,這樣訪問ip:8003就可以訪問nginx 80埠,--name表示容器名字,最后為鏡像名:標簽,
docker ps查看當前容器:

可以看出已經實體化鏡像檔案,在瀏覽器中輸入localhost:8003出現如下界面則表示成功:

3.修改nginx組態檔:
該頁面是鏡像檔案中自帶的一個html檔案,我們需要將我們自己nginx的組態檔復制替換容器自帶的組態檔,進入容器中
docker exec -it dockernginxdemo /bin/bash
cat /etc/nginx/nginx.conf
可以看到Nginx鏡像自帶的nginx組態檔資訊
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
可以看到這和nginx教程中的組態檔有一定的區別的,我自己在這兒踩了幾個坑,nginx中的組態檔是作為一個整體的,而鏡像中是默認包括兩個檔案:default.conf和nginx.conf檔案,下圖是nginx教程中的組態檔
#定義Nginx運行的用戶和用戶組 #user nobody; #nginx行程數,建議設定為等于CPU總核心數, worker_processes 1; #全域錯誤日志定義型別,[ debug | info | notice | warn | error | crit ] #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #行程檔案 #pid logs/nginx.pid; #作業模式與連接數上限 events { #單個行程最大連接數(最大連接數=連接數*行程數) worker_connections 1024; } #設定http服務器 http { #檔案擴展名與檔案型別映射表 include mime.types; #默認檔案型別 default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; #開啟高效檔案傳輸模式,sendfile指令指定nginx是否呼叫sendfile函式來輸出檔案,對于普通應用設為 on,如果用來進行下載等應用磁盤IO重負載應用,可設定為off,以平衡磁盤與網路I/O處理速度,降低系統的負載,注意:如果圖片顯示不正常把這個改 成off, sendfile on; #防止網路阻塞 #tcp_nopush on; #長連接超時時間,單位是秒 #keepalive_timeout 0; keepalive_timeout 65; #開啟gzip壓縮輸出 #gzip on; #虛擬主機的配置 server { #監聽埠 listen 80; #域名可以有多個,用空格隔開 server_name localhost; #默認編碼 #charset utf-8; #定義本虛擬主機的訪問日志 #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} }View Code
如果直接將conf檔案替換鏡像中的nginx檔案的話,會出現“directive is not allowed here in /etc/nginx/conf.d/nginx.conf”這樣的問題,原因是在default.conf組態檔中,已經存在"server”節點,我們可以執行如下指令
docker cp f3d9ee01637a:/etc/nginx/conf.d/default.conf E:/ngingconf/default.conf
將conf.d/default.conf檔案復制到 E:/ngingconf/default.conf檔案中,default.conf檔案如下:
server { listen 80; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }View Code
可以看到,在default檔案中已經存在server節點,所以不能直接復制自定義的nginx.conf檔案到容器的nginx.conf檔案中,有兩種解決方案,第一分別修改nginx.conf和default.conf檔案;第二,將容器中的default.conf檔案內容洗掉,然后再復制自定義的conf檔案覆寫掉鏡像中nginx.conf的組態檔,這里,我們采用第一種方法,修改鏡像中Nginx.conf以及default.conf的區域節點;
首先,執行
docker cp f3d9ee01637a:/etc/nginx/nginx.conf E:/ngingconf/nginx.conf
指令,將鏡像檔案中的nginx.conf檔案復制到本地,打開E:/ngingconf/nginx.conf,編輯組態檔如下:
1 user nginx; 2 worker_processes 1; 3 4 error_log /var/log/nginx/error.log warn; 5 pid /var/run/nginx.pid; 6 7 8 events { 9 worker_connections 1024; 10 } 11 12 13 http { 14 15 #集群站點配置 16 upstream nginxtest.com{ 17 #server 127.0.0.1:8887 weight=1;#服務器配置 WEIGHT是權重的意思,權重越大,分配的概率越大, 18 server 127.0.0.1:8006 weight=1; 19 server 127.0.0.1:8007 weight=1; 20 server 127.0.0.1:8008 weight=1; 21 } 22 23 24 25 include /etc/nginx/mime.types; 26 default_type application/octet-stream; 27 28 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 29 '$status $body_bytes_sent "$http_referer" ' 30 '"$http_user_agent" "$http_x_forwarded_for"'; 31 32 access_log /var/log/nginx/access.log main; 33 34 sendfile on; 35 #tcp_nopush on; 36 37 keepalive_timeout 65; 38 39 #gzip on; 40 41 include /etc/nginx/conf.d/*.conf; 42 }View Code
nginx.conf檔案中,我們添加了

節點指令,配置服務集群,對應之前的三個netcore應用的埠8006,8007,8008,然后執行
docker cp E:/ngingconf/nginx.conf f3d9ee01637a:/etc/nginx/nginx.conf
執行,將本地修改后的nginx.conf檔案拷貝到鏡像檔案中;同理,執行
docker cp f3d9ee01637a:/etc/nginx/conf.d/default.conf E:/ngingconf/default.conf
將鏡像檔案中的default.conf檔案復制到本地,打開E:/ngingconf/default.conf,編輯組態檔如下:
1 server { 2 listen 80; 3 server_name localhost; 4 5 #charset koi8-r; 6 #access_log /var/log/nginx/host.access.log main; 7 8 #快取檔案路由 9 location ~ .*(\.(js|css|jpg|svg)).* { 10 11 proxy_pass http://nginxtest.com; 12 proxy_cache_valid 200; 13 expires 3d; 14 } 15 #集群站點路由 16 location / { 17 18 proxy_pass http://nginxtest.com; #http://nginxtest.com對應upstream后面的名稱加上http 19 proxy_http_version 1.1; 20 proxy_redirect default; 21 22 proxy_set_header Upgrade $http_upgrade; 23 proxy_set_header Connection keep-alive; 24 proxy_set_header Host $host; 25 proxy_cache_bypass $http_upgrade; 26 27 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 28 } 29 }View Code
注意 集群站點中“proxy_pass”后面引數名稱需要和nginf.conf檔案中集群名稱一致,隨后執行cp指令覆寫鏡像檔案即可;
4.測驗
至此docker 部署nginx反向代理已經完成,預期效果是在網站中輸入localhost:8003就會訪問不同的埠號實作負載均衡實際效果運行卻是,,,

不甘心,有試了幾遍,還是這個結果 后來查看了下Kitematic,日志果然有其他問題:

大概就是無法連接到集群里的服務器,推測了下應該是容器間的通信問題,于是驗證了下,用IIS而不是容器發布了應用然后用docker部署nginx負載均衡,其他步驟一樣,果然可以直接訪問而不會出現該問題,于是開始著手解決這個問題
三 .關于upstream server temporarily disabled while connecting to upstream nginx問題
默認情況下,容器都是使用Docker橋接網路來與其他容器或者主機網路通信,所有的本地Bridged容器都是在同一個橋接網路上,并且默認可以相互通信的的,如下圖:
既然如此,容器之間應該可以通訊的,那為何會出現上述問題,
我們先執行 “docker network ls”指令查看docker中存在的網路:

“ bridge”為docker創建的默認網路,默認的都在改網路下,然后通過命令
docker network inspect bridge
查看bridge網路的詳細配置:

可以看出,我們創建的四個docker容器檔案都在該網路下,但是IP地址卻不是我們之前分配的host:8006,host:8007,host:8008,如上圖綠色標記,我們將nginx.conf檔案中的集群節點做如下修改:
#server 127.0.0.1:8887 weight=1;#服務器配置 WEIGHT是權重的意思,權重越大,分配的概率越大, #server 127.0.0.1:8006 weight=1; #server 127.0.0.1:8007 weight=1; server 172.18.0.2:8005 weight=1; server 172.18.0.3:8005 weight=1; server 172.18.0.4:8005 weight=1; #server 127.0.0.1:8008 weight=1;
需要注意兩點:
1.集群下server節點需要加埠號,否則默認80埠;
2.本機測驗下需要確保集群節點的server子節點 和nginx在同一網路下;
測驗,瀏覽器輸入Localhost:8003,運行結果如下圖:

可以看出,重繪頁面會訪問不同的埠,而且我們我也可以看出,服務端讀取到的ip地址其實就是docker網路中容器的IP地址;
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/33232.html
標籤:.NET Core
