上篇文章我們成功在Windows下安裝了Docker,輸出了一個簡單的Hello World程序。本文中我們將利用Docker已有的雲端鏡像training/webapp來發布一個簡單Python的Web程序,在瀏覽器中輸出hello world。
本文內容的測試環境是Windows7下的Docker,用例基於官方文檔用例。
一:從運行一個簡單的Python Web程序說起
啟動Docker客戶端並登陸。在客戶端中輸入以下內容:
$ sudo docker run -d -P training/webapp python app.py
第一次輸入上面命令時,Docker會先從雲端鏡像庫中下載training/webapp鏡像(筆者機器已經下載過了,圖1略過了此過程),成功運行后如圖1所示。
圖1.運行截圖
下面我們來詳細看看這條命令的具體內容,這一部分我們可以在官方文檔中找到詳細的英文解釋,這里筆者將其翻譯過來並加了些自己的理解。
前面我們已經說過,Docker虛擬機系統實際也是基於Linux內核,所以這條語句實際上就是Linux的命令,我們可以輸入以下內容查看docker命令的詳解:
$ sudo docker
輸出結果如下:
圖2.docker命令的子命令列表
再回到第一條中,我們使用的子命令是run。
在子命令列表中我們看到run子命令解釋是:run Run a command in a new container,也就是在一個新的容器中運行一條命令。
我們的run命令后面跟的可選項有-d和-P。
查閱官方文檔我們可以知道,-d表示Docker會把當前命令的容器放到后台執行並監控起來。-P則表示讓Docker映射任何容器內部需要的端口到虛擬機上。這里需要對Docker一些概念有所了解,我們這里暫且簡單地理解為Docker虛擬機下的每個Docker容器都是一台子虛擬機,每個子虛擬機都有一塊虛擬網卡,當外部要訪問容器時都必須通過Docker虛擬機,而-P就做了相關的端口映射。
命令執行后返回的一長串字符串(也就是fc4028b21d84f5c075821ca2425d74d45dea87cd28c4eb92620ae39ddec22f46)則是Docker的容器ID,這是一個唯一的值,我們可以以它為標識對容器做相應的操作。
當我們需要查看和管理當前后台運行的所有容器時,我們可以輸入以下命令。
$ sudo docker ps
圖3.容器詳細信息
這里我們可以看到容器的詳細信息,包括容器ID(精簡的ID),鏡像,命令,創建時間,狀態,端口,以及容器名字。
接下來的training/webapp就是我們運行的容器的源了,Docker中稱之為鏡像,這個鏡像是Docker官方之前就創建好的,里面包含了一個簡單Python Flask web應用。
最后,我們在容器中執行了python app.py,python app.py啟動了我們的web應用。
二:訪問頁面——從Linux和Windows的區別到對Docker層次的簡單理解
從上面我們查看運行容器的詳細信息時(圖3)我們看到了,在PORTS這一欄中,有這樣的信息:
0.0.0.0:49153->5000/tcp
上文中提到Docker虛擬機對容器做了端口映射,這里我們可以更直觀的看到了,Docker虛擬機中的49153端口映射到了容器的5000端口(這里我們運行的是web程序,所以是tcp協議,其他容器有需要可以指定成udp協議)。
在官方文檔中,這時我們訪問localhost:49153,應該就能出現Hello world了,但是筆者在這個步驟根本訪問不到這個頁面。
圖4.此時訪問,瀏覽器一直處於等待狀態
因此這里我們需要重新看看這個虛擬網絡的結構,要看整個網絡的結構,我們應該先了解Docker的層次結構。在Linux中,Docker的邏輯結構是這樣的:
硬件 < Linux系統(Docker Kernel) < Docker容器
而我們在前文中提過,在Windows中要運行Docker,實際上是在虛擬機下運行的,所以在Windows中Docker的邏輯結構應該是:
硬件 < Windows系統 < Docker虛擬機(Docker Kernel) < Docker容器。
因此官方文檔中用例應該是基於Linux下的,Linux此時訪問localhost:49153是沒有問題的,因為Docker Kernel此時把49153端口映射給了容器的5000端口,而Windows則不行,因為我們只是把Docker虛擬機的49153端口映射給了容器,我們在瀏覽器中輸入localhost:49153明顯是訪問的Windows層級別。
理解到這里問題就已經解決了,我們只需進入VirtualBox中,將Docker虛擬機的網絡做個橋接,或者端口映射就行了。
進入VirtualBox主界面,選中Docker虛擬機(boot2docker-vm),單擊設置按鈕,在設置中選擇網絡,這里我們發現Docker虛擬機默認選擇了“網絡地址轉換(NAT)”。
圖5.Docker虛擬機的網絡連接方式默認是NAT
而且端口轉發中還默認有兩個端口映射。
圖6.Docker虛擬機和宿主機默認的端口映射
不難猜測這里可能是Docker客戶端和Docker虛擬機進行通信的端口,因此我們不能將Docker虛擬機的網絡連接方式改成橋接了,否則Docker客戶端無法和Docker虛擬機進行通信。
因此我們這里選擇添加一個端口映射,將Windows系統的80端口映射到Docker虛擬機的的49153端口上去。端口映射的名稱隨便取,協議一定要是TCP(HTTP基於TCP)
圖7.添加映射端口
此時我們可以在Windows下的瀏覽器直接訪問localhost了(一般來說瀏覽器默認訪問80端口,80端口可以省略),因為我們直接映射了80端口到Docker虛擬機的49153端口上,而Docker虛擬機的49153端口又映射到了我們剛剛創建的Docker容器的5000端口上,我們的web程序正是運行在該容器的5000端口上。
圖8.Hello world!
總結:
本文實際上只運行了一個簡單的web程序,用例也是基於官方文檔,而且如果讀者是在Linux運行的話輸入完第一條命令應該直接在瀏覽器中訪問了。因此本文主要是對Docker的run命令做了簡單的解釋,並且通過Docker在Linux和Windows下的區別來簡單理解Docker邏輯層次結構。
希望對初學者有一些幫助,筆者自己也是Docker的初學者,文章錯處,萬請見諒指正。