1. 程式人生 > >老司機實戰Windows Server Docker:3 單節點Windows Docker伺服器簡單運維(上)

老司機實戰Windows Server Docker:3 單節點Windows Docker伺服器簡單運維(上)

經過上兩篇實戰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的簡單功能,從而避免了這個引數沒實現帶來的痛點。

上篇完