經過上兩篇實戰Windows Server Docker系列文章,大家對安裝Windows Docker服務以及如何打包現有IIS應用為docker鏡像已經有了基本認識。接下來我們來簡單講講一些最基本的運維問題。鑒於到目前為止我們只談到單服務器部署。這里暫時不涉及集群模式下的復雜生產環境運維。
本主題將涵蓋下面這些主要內容,由於這個主題包含的內容較多,將分成上下兩篇發布:
上篇
- 遠程操作Windows Docker服務器
- 自動化Docker編譯和部署
- Windows Docker網絡配置和端口映射
下篇
- 負載均衡和反向代理
- 日志解析和監控
遠程操作Windows Docker服務器
和Linux下的Docker服務默認通過TCP 2375/2376端口執行docker命令不同,Windows Docker服務默認只支持本機基於命名管道來執行docker命令。如果安裝完Windows Docker服務后,在命令窗口執行netstat -an,可以看到,服務器並不監聽2375或者2376這樣的端口。當然,我們可以通過修改daemon.json這個配置文件(關於如何修改daemon.json文件,請參考本系列的第一篇),來開啟2375/2376端口。2375端口和linux下的2375端口一樣,用於非TLS的遠程連接;而2376則支持基於證書的安全連接。對於,開發測試環境,一般開啟2375端口就行,而對於生產環境,則應該使用2376端口,基於TLS安全連接來遠程管理Docker服務器。
要開啟2375端口,只需要如下在daemon.json添加hosts配置項,然后重啟Docker服務:
{
"hosts": ["tcp://0.0.0.0:2375"]
}
要開啟2376端口也類似,就是稍微復雜一點,需要生成和配置證書,具體的可以參考微軟的這篇官方文檔這里就不詳述了。
開啟2375端口之后,可以通過在命令窗口執行如下的netstat命令,確保2375端口已經正確監聽:
netstat -an | findstr 2375
如果返回類似下面,就說明已經在監聽了:
TCP 0.0.0.0:2375 0.0.0.0:0 LISTENING
TCP [::]:2375 [::]:0 LISTENING
只是開始監聽還不夠,要允許外部機器能夠遠程訪問本機的2375端口,我們還要添加防火牆的Inbound規則,可以通過下面的powershell命令開啟:
New-NetFirewallRule -DisplayName 'Docker TCP Inbound' -Profile @('Domain', 'Public', 'Private') -Direction Inbound -Action Allow -Protocol TCP -LocalPort 2375
接下來,我們就可以嘗試從安裝了Docker client的遠程機器,訪問這台Windows Docker服務器了。Docker client有各種跨平台版本,所以只要是相兼容的版本,我既可以從Windows的docker client,也可以從linux的docker client通過2375端口遠程訪問docker服務器。
當我們從當前機器,比如你的開發機訪問一台遠程docker服務器時,我們需要為docker client指定目標HOST。一般有兩種方式:一種是可以通過在每個docker命令執行時,添加-H server_name_or_ip參數,另一種是設置DOCKER_HOST環境變量,這樣,就不需要每個docker命令都帶-H參數了。例如,下面的命令會列出遠程服務器1.2.3.4的所有docker images:
docker -H 1.2.3.4 images
docker -H tcp://1.2.3.4 images
docker -H tcp://1.2.3.4:2375 images
上面的幾種指定host的語法都是可以的,如果使用默認的2375端口,最簡單的就可以用第一種,少打不少字符。如果要指定DOCKER_HOST環境變量,那么必須使用完整的格式,比如:
SET DOCKER_HOST=tcp://1.2.3.4:2375
開啟遠程訪問之后,當需要從開發或者編譯環境編譯和發布docker鏡像時,我們就不需要像上一篇中那么蛋疼的先copy發布出來的應用網站文件到docker服務器,然后在服務器上執行docker build了,只需要直接從開發環境執行docker build,就能直接在遠程docker服務器上生成和運行docker鏡像了。
自動化Docker編譯和部署
docker的命令行工具,有許多子命令和參數。如果要經常編譯和運行docker鏡像,我們當然不希望每次都手打所有參數,例如,下面的命令編譯一個docker鏡像,並運行一個docker容器,每次手打一邊實在沒啥樂趣:
docker build -t iis-demo:1.0 .
docker run --ip 172.24.128.2 -p 80 -v "c:/temp:c:/inetpub/logs/LogFiles" -e "env1=LIVE1" -e "env2=LIVE2" -e "HOSTS=1.2.3.4:TEST.COM" iis-demo:1.0
為了簡化這個過程,通常我們會寫一些帶參數的powershell腳本;或者,我們可以使用另一個docker的必備命令行工具:docker-compose。
docker-compose是一個docker官方發布的docker容器編排工具,用於通過yml格式的配置文件來簡化docker命令的執行。例如,上面這兩個編譯並運行docker容器的腳本,如果我們定義如下這個docker-compose.yml配置文件:
version: "2.1"
services:
iis-demo:
build: .
image: "iis-demo:1.0"
ports:
- "80"
networks:
nat:
ipv4_address: 172.24.128.2
volumes:
- "c:/temp:c:/inetpub/logs/LogFiles"
environment:
- "env1=LIVE1"
- "env2=LIVE2"
- "HOSTS=1.2.3.4:TEST.COM"
networks:
nat:
external: true
那么,我們就可以在docker-compose.yml所在的目錄,通過下面這一條命令,就能自動編譯docker鏡像,並且運行一個docker容器了:
docker-compose up
是不是超級簡單?事實上,docker-compose幾乎包裝了所有通過docker命令行可以執行的參數,而且,一個docker-compose.yml文件,可以包含多個相關的docker鏡像的配置,比如,你的這個應用可能依賴於某一個DB,或者另一個應用的,那么,寫在一個yml文件里,就能很方便的一鍵編譯,一鍵發布,一鍵關閉這些相關容器。限於篇幅,本文就不細說docker-compose各種功能了,大家可以參看官方文檔和示例自行摸索。
這里簡單講一下,在windows下,如何安裝docker-compose。
- 首先,docker-compose是一個客戶端工具,也就是,它應該安裝於安裝了docker client的機器,並不需要安裝於docker服務器;
- 對Windows版本的docker-compose來說,它就是一個單個文件的.exe文件,你只需要從官網下載Windows版本的.exe文件,將文件名改成docker-compose.exe,然后隨便放到任何方便訪問的目錄就可以了。我比較懶,一般直接丟到c:\windows\system32目錄,那樣就不需要設置額外的PATH路徑,就能在任何當前目錄下,在命令窗口直接執行了。
有了,docker-compose,我們也可以很簡單的設置我們的docker服務器每次機器啟動之后,自動運行指定的docker容器,只需要配置一個機器的啟動腳本,每次機器啟動后自動運行docker-compose up,就可以了。
有人可能想問,如何為windows設置自動啟動腳本?一個簡單的方法是,使用NSSM這個小工具。例如,下載nssm的exe到本地后,只需要在命令行執行:
nssm install "Docker Startup" command param1 param2 ...
就能將指定的命令變成自動開機執行的windows service了。是不是很方便?網上介紹NSSM也文章也很多的,大家可以搜索一些,這里我就給幾個link,不過多介紹了:
- https://help.aliyun.com/document_detail/49021.html
- https://github.com/verbosemode/public-notes/blob/master/logstash-windows.md
Windows Docker網絡配置和端口映射
微軟官方,主要就這一篇文檔介紹了windows容器的網絡設置。介紹得其實並不是很深入。主要來說,它介紹了Windows Docker支持的幾種網絡模式,例如:nat、transparent、overlay、l2bridge。其中,最常用的,大家最容易理解的,也是Windows Docker服務安裝后的默認模式是nat模式。簡單的說,就是:
- 宿主機上運行的所有的容器,都屬於一個子網段,每個容器運行時,可以靜態指定網段內可用的ip,或者自動分配一個網段內的ip;
- 子網段內的ip,在宿主機外部無法直接訪問,只能從宿主機上直接訪問;
- 可以通過docker命令的-p參數,設置靜態或者動態的宿主機ip到容器ip的端口映射,這樣宿主機的外部網絡,就可以通過宿主機的ip和端口,間接訪問到容器內的網站了;
例如,在上面的示例中的docker run --ip 172.24.128.2 -p 80 ...里,-p 80這個參數就會導致docker命令執行時,動態分配一個宿主機上的端口,映射到容器ip的80端口上。如果我們執行上面的docker run命令,或者docker-compose up命令后,在命令窗口執行docker ps,可以看到下面的正在運行的容器:
0f0e07424d80 iis-demo:latest "C:\\SetHostsAndSta..." 5 minutes ago Up 4 minutes 0.0.0.0:39924->80/tcp windowsdockeriisdemo_iis-demo_1
其中,0.0.0.0:39924就是指的,對宿主機上任意ip的39924端口的訪問,已經被映射到這個容器的子網ip的80端口了。
但是,這里有個坑,很深的坑,讓我一度差點懷疑人生,甚至重裝了機器的坑!!!——如果你在宿主機上的瀏覽器里,訪問比如http://localhost:39924/iis-demo,按這個端口映射,你天真的以為就能訪問到容器內的網站,尤其示玩過linux下容器的小伙伴,更絕對會認為它能訪問。但是,它其實不能!!什么原因呢?我為此一度差點崩潰,最后,在某個windows docker的github issuer中,有開發人員解釋說,這個是因為windows版本的實現問題,在宿主機本機,這個映射的端口無法訪問,但是,在宿主機外部,訪問宿主機上的ip加這個端口是可以訪問的!!只允許從外部訪問!!WTF?這是什么鬼的道理?不過,反正,現狀就是如此,也只能忍了。
除了使用動態分配的端口,如果我們把參數改成例如-p 80:80,那么就能通過宿主機的ip:80端口,訪問到容器內的網站了。再提醒一遍,記住,只能從宿主機外部訪問!!
微軟的官方文檔,除了介紹了幾種常見的網絡模式如何配置,還提到了一些Windows版本的Docker相對於linux版本的docker沒有實現的功能,下面的這些docker命令的參數,對Windows Docker無效:
- --add-host
- --dns-opt
- --dns-search
- --aux-address
- --internal
- --ip-range
其中,最遺憾的就是--add-host參數沒有實現。--add-host參數原本是用於為容器內的系統的hosts文件添加靜態dns解析的,這是一個非常常用的功能,沒有它,部署到容器內的應用可能無法解析某些服務器名稱或者域名。當然,我們可以自己實現類似功能,例如,在上一篇 docker化現有iis應用中,我們就實現了一個通過環境變量,傳入,並設置hosts的簡單功能,從而避免了這個參數沒實現帶來的痛點。
上篇完