到目前為止大家應該對映象和容器有了一個大概認知,而且也用了docker進行了一個簡單化的部署,但仔細一看問題還有很多,所以這篇我們繼續完善。
一:如何讓外網訪問到容器內應用
我們知道容器內擁有自己的子網,和你的主機ip不在一個網段內,所以宿主之外的機器是無法訪問的,要實現的話你只能通過nat轉發,在docker上實現起
來很簡單,通過 -p 將容器埠對映到宿主機埠即可。
1. 在Dockerfile中,容器會自動監聽8080埠,而且我的程式也是開啟了這個埠號。
FROM microsoft/dotnet:2.2-aspnetcore-runtime LABEL author hxc@qq.com RUN mkdir /data COPY ./ /data WORKDIR /data VOLUME /data/log EXPOSE 8080 CMD [ "dotnet","WebNotebook.dll" ]
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseUrls("http://*:8080") .UseStartup<Startup>(); }
2. 接下來通過 -p 埠對映,將宿主機的8080埠和容器的8080埠進行一個對映,前面是宿主機埠,後面是容器的,你也可以寫成 hostip:8080:8080
[root@localhost ~]# docker run -d --name webnotebook -p 8080:8080 huangxincheng520/webnotebook:v4 82cf45e8fb7281fda7d1b22bf6ef1a5156a75f04b4ef29873d44f161b0238cfb [root@localhost ~]# [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 82cf45e8fb72 huangxincheng520/webnotebook:v4 "dotnet WebNotebook.…" 3 seconds ago Up 2 seconds 0.0.0.0:8080->8080/tcp webnotebook
3. 然後我就可以在windows上輸入網址訪問了,可以看到一點問題都沒有。
4. 有些人可能會很好奇的去問,這個是怎麼做到的呢? 剛才也說到了是通過nat進行協議頭ip地址替換進行轉發的,你要是不信的話,可以用centos的
iptables nat去檢視一下。
[root@localhost ~]# iptables -t nat -L -n Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0 RETURN all -- 192.168.122.0/24 224.0.0.0/24 RETURN all -- 192.168.122.0/24 255.255.255.255 MASQUERADE tcp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 MASQUERADE udp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 MASQUERADE all -- 192.168.122.0/24 !192.168.122.0/24 MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:8080 Chain DOCKER (2 references) target prot opt source destination RETURN all -- 0.0.0.0/0 0.0.0.0/0 DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:8080
可以看到,docker在iptables中實現了一個自己的Docker chain,從 hostIP:8080 -> 172.17.0.2:8080中可以看到,當一個請求到了 192.168.23.149:8080
會自動轉發到 172.17.0.2.8080,有些人可能會問,這個明顯不是一個網段怎麼轉發呢? 那是因為你的宿主機上有一個預設的網橋Docker0,你可以理解成
他就是一個資料鏈路層上的路由器,通過這個路由器,可以將不同的網段進行互聯,你可以用ipconfig檢視docker0的ip地址,這個ip地址就相當於路由器ip,
也即是子網地址。
[root@localhost ~]# ifconfig docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:25ff:fe14:8a13 prefixlen 64 scopeid 0x20<link> ether 02:42:25:14:8a:13 txqueuelen 0 (Ethernet) RX packets 105061 bytes 8399597 (8.0 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 148379 bytes 425576796 (405.8 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.23.149 netmask 255.255.255.0 broadcast 192.168.23.255 inet6 fe80::20c:29ff:fe5c:2e32 prefixlen 64 scopeid 0x20<link> ether 00:0c:29:5c:2e:32 txqueuelen 1000 (Ethernet) RX packets 1570930 bytes 2222888854 (2.0 GiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 532628 bytes 56478232 (53.8 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 0 (Local Loopback) RX packets 104 bytes 8816 (8.6 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 104 bytes 8816 (8.6 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 veth871156e: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::3c7f:5fff:fe53:4542 prefixlen 64 scopeid 0x20<link> ether 3e:7f:5f:53:45:42 txqueuelen 0 (Ethernet) RX packets 99 bytes 726984 (709.9 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 306 bytes 19235 (18.7 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255 ether 52:54:00:83:96:c2 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
二:如何處理容器中的日誌資料
我們的webnotebook執行的時候總會產生一些日誌,這時候可以把日誌資料夾掛載到宿主機上,方便檢視和採集啥的,當然更多的情況是採用集中式
的日誌收集,這個就不是本篇所討論的了,接下來我要做兩件事情,配置nlog日誌框架,然後進行docker目錄掛載。
1. 配置nlog框架,在nuget上下載
2. nlog.config 配置如下,{basedir} 就是當前程式的根目錄。
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="file_info" xsi:type="File" fileName="${basedir}/log/${shortdate}.txt" maxArchiveFiles="30" layout="${longdate} | ${level:uppercase=false} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}" /> </targets> <rules> <logger name="*" writeTo="file_info" /> </rules> </nlog>
3. 然後我們的Controller類修改一下,記錄下客戶端的ip地址。
public class HomeController : Controller { public static Logger logger = LogManager.GetLogger("SimpleDemo"); /// <summary> /// 讀取mongodb資料資料 /// </summary> /// <returns></returns> public IActionResult Index() { var log = $"客戶端:{HttpContext.Connection.RemoteIpAddress} 訪問了 Index 頁面!"; logger.Info(log); return View(); } }
4. 接下來你就可以docker build 成映象啦,在 docker run 中使用-v引數,將宿主機的 /data/log 掛載到容器的 /data/log目錄,如下命令。
[root@localhost publish]# docker build -t huangxincheng520/webnotebook:v5 -f ./Dockerfile . [root@localhost publish]# docker run --name webnotebook5 -d -p 8080:8080 -v /data/log:/data/log huangxincheng520/webnotebook:v5 0e03f54d69ccdf3f88511385fd6fd5fdcafb64c0f971cbadb0b93014cb79e375
5. 一切都部署好了,接下來你可以訪問8080埠,然後到你的宿主機的/data/log目錄下檢視一下,你的日誌就出來啦。
[root@localhost log]# pwd /data/log [root@localhost log]# ls 2019-02-20.txt [root@localhost log]# tail 2019-02-20.txt 2019-02-20 04:13:36.2904 | Info | 客戶端:::ffff:192.168.23.1 訪問了 Index 頁面! [root@localhost log]#
細心的你應該會發現到,日誌所列印出的時間出了問題,比北京時間少了8個小時,所以你要做的是,把預設的0區時間改成東8區即可,那怎麼修改呢?
《1》 在docker run 中加入 -e 引數,也就是加入環境變數 -e TZ=Asia/Shanghai 即可,不要怕引數多,以後這些都是通過CI工具整合的,不要怕哈。
[root@localhost publish]# docker run --name webnotebook5 -d -p 8080:8080 -v /data/log:/data/log -e TZ=Asia/Shanghai huangxincheng520/webnotebook:v5 18cbd284dbd6f6ff498d849eda7652ec63df3c0113c0cdd53ae4a0030abb52f2
訪問網站之後再看看你的log檔案,時區已經調整過來了。
[root@localhost log]# tail 2019-02-20.txt
2019-02-20 04:13:36.2904 | Info | 客戶端:::ffff:192.168.23.1 訪問了 Index 頁面!
2019-02-20 12:20:38.3752 | Info | 客戶端:::ffff:192.168.23.1 訪問了 Index 頁面!
《2》 在dockerfile中增加環境變數佔位符。
FROM microsoft/dotnet:2.2-aspnetcore-runtime ENV TZ Asia/Shanghai
好了,本篇就說到這裡,希望對你有幫助。