實踐在windows下用docker進行web開發
關於如何在windows下安裝docker,詳見http://blog.csdn.net/ownfire/article/details/45847939
本文著重闡述如何將docker實用起來
大家在協同開發過程中,通常會遇到各人開發環境不同,導致本地部署開發環境浪費時間、擴充套件庫有差異、甚至系統不同等問題,docker就是為了解決這些問題、快速開發環境、讓開發人員迅速進入開發狀態而生的
Docker是一個基於Go語言的開源應用容器引擎,可以自動化地部署應用到可移植的的容器中,這些容器獨立於硬體、語言、框架、打包系統。
一個標準的Docker容器包含一個軟體元件及其所有的依賴——二進位制檔案,庫,配置檔案,指令碼等等。
Docker擴充套件了LXC(Linux Container),使用高層的API,提供輕量虛擬化解決方案來實現程序間隔離。可以執行在任何支援cgroups(control groups)跟AUFS的64位Linux核心上。
LXC是docker的核心技術,藉助於namespace的隔離機制和cgroup限額功能,提供了一套統一的API和工具來建立和管理container。(類Hypervisor)
Linux Namespace (ns)
Control Groups (cgroups)
LXC 旨在提供一個共享kernel的OS級虛擬化方法,在執行時不用重複載入kernel, 且container的kernel與host共享,因此可以大大加快container的啟動過程,並顯著減少記憶體消耗。
在LXC的基礎上, Docker額外提供的Feature包括
1、標準統一的打包部署執行方案
2、歷史版本控制
3、Image的重用
4、Image共享釋出等。
下面是本文重點,安裝好docker後如何快速進入開發狀態,僅針對web開發:
開始講述之前,要再次認識到docker只是一個在虛擬機器中執行的系統底層,是連線上層宿主windows和下層開發環境容器,container(即開發環境容器)類似於子系統,是在docker虛擬機器中像應用程式一樣執行的隔離環境,和宿主系統的一切互動都要通過處於中間層的docker,並且預設都是關閉的,可以理解為好多個沙盒
web開發涉及到web伺服器和專案程式碼和資料庫,我們一項一項來解決
本文假定docker虛擬機器啟動後的繫結ip為192.168.59.103
1、web伺服器
一、安裝nginx並設定埠對映
一開始docker安裝好並且啟動container後,container內的服務埠(例如nginx啟動後監聽的80埠)是不對外暴露的,在宿主windows下用瀏覽器訪問docker虛擬機器ip是訪問不到container內的80埠的
必須做埠對映操作,只要在container啟動時,docker run命令帶上埠對映引數就可以了:
docker run -it -p 22222:33333 fe65a2781dae /bin/bash
解釋:
-it引數在啟動container為tty形式時必帶,否則無法做命令列互動
-p 22222:33333 關鍵引數,指定docker虛擬機器的22222埠,對映為container的33333埠,即對192.168.59.103:22222的訪問,統統訪問到container的33333埠。如果要對映80埠,設定-p 80:80就好
fe65a2781dae 指定docker要執行的imageid,也可以是REPOSITORY:TAG形式
/bin/bash docker啟動container後要執行的命令,一般啟動命令列互動就用這個就好了
所以要把nginx調通,要做以下步驟:
1、docker run -it -p 80:80 fe65a2781dae /bin/bash
2、container內執行nginx
3、宿主windows瀏覽器訪問192.168.59.103
4、Welcome to nginx!
二、配置nginx在容器啟動時自動啟動
最簡單的方法:
vi /etc/bashrc
新增一行類似
/usr/sbin/nginx -c /etc/nginx/nginx.conf
儲存並推出
docker commit 儲存容器修改,下次再啟動容器時,自動就把nginx啟動起來了,要新增其他自啟動程式同樣操作
docker commit 如何使用,不在本文範圍,請自行百度
其他還有通過Dockerfile的方法,還有一種通過linux程序管理工具supervisor的方法,詳見:
http://segmentfault.com/a/1190000000755980
上文關於supervisor的部分,轉載了另一篇文章,在此也直接把連結列出來方便檢視:
http://air.googol.im/2014/03/28/supervisor-with-docker-to-manage-processes.html
2、專案程式碼
docker只是一個開發環境的容器,一般不用來做程式碼持久化的容器,如果這樣做,很容易丟程式碼,因為docker並不主動儲存在container內的修改除非你手動操作
最好的解決辦法就是,有一個共享資料夾,從宿主windows共享至container內,作為專案程式碼根目錄
過程大致如下:
一、建立virtualbox和docker虛擬機器的共享
可以參考http://jingyan.baidu.com/article/2fb0ba40541a5900f2ec5f07.html
開啟virtualbox並且選擇到boot2docker-vm虛擬機器,右鍵點設定
-
點選共享資料夾設定框,右上角的新增按鈕
-
選擇之前本機設定的共享資料夾,此時一定不可以勾選自動掛載
-
設定好共享名後,進入docker虛擬機器系統,開啟終端,先執行命令,在掛載點目錄新增“bdshare”目錄,接著執行"mount -t vboxsf BaiduShare /mnt/bdshare/",就能完成共享資料夾的設定。請記住mount命令一定要帶上引數-t vboxsf,BaiduShare就是共享資料夾名稱,/mnt/bdshare/就是要在docker虛擬機器中掛載的絕對路徑
-
docker虛擬機器系統預設使用docker使用者,可能會遇到Permission denied錯誤,即許可權不足,需要切換到root賬戶操作,只要輸入“sudo su”命令即可,無需密碼
二、docker容器掛載docker虛擬機器的目錄
可以參考http://my.oschina.net/piorcn/blog/324202
docker可以支援把一個宿主機上的目錄掛載到映象裡。
docker run -it -v /home/dock/Downloads:/usr/Downloads ubuntu64 /bin/bash
通過-v引數,冒號前為宿主機目錄,必須為絕對路徑,冒號後為映象內掛載的路徑。
現在映象內就可以共享宿主機裡的檔案了。
此處要掛載上一步virtualbox和docker虛擬機器共享的資料夾,就在docker啟動container時加上引數:
-v /mnt/bdshare/:/data
命令類似:
docker run -it -p 80:80 -v /mnt/bdshare/:/bdshare fe65a2781dae /bin/bash
這樣就把宿主windows的K:\BaiduShare目錄,掛載到了container的/bdshare目錄
3、資料庫
同樣因為docker只是一個容器,不具備主動持久化的原因,所有會記錄狀態的資料(例如資料庫)都無法被儲存下來
解決的方法還是通過使用掛載的共享目錄,將所有需要持久化的資料儲存目錄都放在共享目錄中即可,下次container啟動的時候掛載上共享目錄,資料保持原樣
4、docker虛擬機器和container的持久化
我們可能想對docker虛擬機器本身做些配置,以便在虛擬機器啟動時自動啟動一些程式,比如自動掛載共享目錄,正常的linux系統只要往/etc/fstab檔案或者/etc/rc.local檔案裡寫執行語句,系統啟動時就會自動執行
但是往docker虛擬機器的自啟動檔案裡寫語句的話,下次啟動就不見了,這是為什麼呢,是因為:
docker虛擬機器裡面跑的是TinyCoreLinux,這個OS的rootfs是臨時性的(放在記憶體的,實際上就是boot2docker.iso檔案裡面的一個rootfs),因此其根目錄/下的東西(包括/home)根本不會持久化,只有/mnt/sda1這個目錄下的才能持久化。如果你放在/home目錄下,只要VM一重啟,就會丟失的,/mnt/sda1則不會,實際上就是那個~/.boot2docker-vm.vmdk檔案掛載到了/mnt/sda1目錄下
docker裡跑的container只是docker系統底層的上層隔離沙盒,container裡持久化的一切內容,最終都持久化到docker虛擬機器裡
這樣方法就清楚了,沒辦法針對docker虛擬機器做自啟動配置,但是可以寫好自啟動的sh指令碼,放在/mnt/sda1這個目錄下,下次啟動虛擬機器時,手動切換到這個目錄下執行sh指令碼。目前沒有找到更好的方法, 如果有更好的方法,歡迎告訴我謝謝
而container的持久化,除了掛載宿主windows的共享目錄外,還有就是對映的目錄設定到虛擬機器的/mnt/sda1目錄下,這兩種方法一個是持久化到宿主系統中,一個是持久化到虛擬機器的虛擬磁碟中。兩種方法都可以,就看自己選擇了
舉例,我的/mnt/sda1/的sh指令碼內容是:
sudo mount -t vboxsf sync /mnt/sync/ #掛載宿主windows的共享目錄
docker run -it -p 80:80 -v /mnt/sync:/sync -v /mnt/sda1/data:/data centos:centos6 /bin/bash #對映共享目錄,和虛擬機器磁碟