天天看點

使用Docker部署PHP應用的設計方案1. Docker2. LNMP3. Dockerfile4. 總結

1. Docker

Docker的官方定義是:

Docker allows you to package an application with all of its dependencies into a standardized unit for software development.

-- https://www.docker.com/whatisdocker

毫無疑問的是,Docker解決了應用部署上一個巨大的問題:

客戶: 安裝好了,用不了。

釋出者:我的機器上沒問題。

如何解決每個應用的依賴在Docker出現之前是個頭疼的問題,現在僅僅通過一次配置,Dockerfile或者image作為最終傳遞,就能在任何Linux上完美運作了。說起來很簡單的樣子,但在Docker配置過程中,又存在很多值得思考的問題:應用各個元件如何安排?一個Container解決問題還是細化Container?Container之間何如通信?等等。。下面用一個最普遍的WEB應用配置部署來說明這些問題。

NOTE:本文假定讀者對Docker中的一些概念有基本的認識,如果不甚了解,我推薦這篇文章:

https://linux.cn/article-6074-weibo.html

2. LNMP

典型的PHP應用配置方案是LAMP或者LNMP,本文以LNMP為例。

設計方案如下圖(我已經實作并運作于 https://apporz.com):

使用Docker部署PHP應用的設計方案1. Docker2. LNMP3. Dockerfile4. 總結

應用由4個元件組成,分别是Nginx,PHP-FPM(PHP),MySQL以及WWW,4個元件運作在由各自鏡像建立出來的獨立的容器中。其中WWW Container隻是一個存儲業務代碼和靜态資源的容器,可以認為是"死"的。

事實上LNMP架構采用上面的設計方式應該是最容易想到的,也是最清晰的,每個元件有相對的獨立性。其中除了WWW容器,其他3個容器都可以直接通過官方鏡像建構出來。

然而網上很多同學并不是這樣做的,不會分的這麼細,通常是把Nginx和WWW放到一個容器内,或者幹脆全部放到一個容器中。可以學習一下大家的Dockerfile:

https://github.com/search?utf8=✓&q=docker-lnmp

細化Container這種設計的優缺點:

  1. 容器間的耦合性增大。可以看到PHP-FPM容器和另外三個容器間有耦合關系,MySQL容器最獨立。
  2. 雖然耦合性比較大,但這種端口耦合,檔案系統耦合關系可以通過增加幾個運作選項解決掉,後面有介紹。
  3. 由于容器對整個架構的劃分,使得容器中的内容變得十分獨立和安全。例如,我希望線上上更新WWW中的代碼,隻需要進入WWW容器做修改,不會影響到Nginx,PHP-FPM或者是MySQL。
  4. 各容器可靈活拆卸更換,比如我想把MySQL換成Mongodb,或者幹脆把業務代碼搬個家,不會影響到其他容器(僅僅更改相關配置檔案)
  5. 由于各容器經由官方的鏡像建立,是以可以随時花最少的代價使用最新的官方鏡像嘗鮮。
  6. 占用空間會比較大,一個簡單的應用要這麼做的話,四個鏡像會占用大量的存儲空間。

2.1 容器間通信問題

細化Container面臨着另一個問題,就是如何進行容器間通信。下面簡要描述一下上圖中的資料流程:

  1. 用戶端的http請求達到server的80端口,該端口被映射到Nginx Container的80端口,是以進入Nginx處理。Nginx會分析請求資源,判定是靜态資源還是php腳本,如果是靜态資源,則直接從WWW中取出發回用戶端;如果是腳本程式,則要告訴PHP-FPM到WWW擷取相應腳本,然後通過php-cgi處理。
  2. fast-cgi通過php執行腳本,必要時通路MySQL存取資料。

這樣耦合關系就出來了:

  1. Nginx需要連接配接PHP-FPM開放的9000端口,需要通路WWW中的檔案系統。
  2. PHP-FPM也需要通路WWW中的檔案系統,還要通路MySQL的3306端口。

2.2 解決問題

可以看出有兩類耦合關系:端口和檔案系統。

對于端口耦合,docker是通過--link選項解決的;對于檔案系統耦合,docker是通過--volumes-from選項解決的。

解決第一個耦合關系:

$ sudo docker run -p 80:80 -p 443:443  # 主機端口映射到容器
--volumes-from WWW_CONTAINER_NAME  # 把WWW容器VOLUME過的檔案夾挂載到将啟動的容器上
--link PHP_FPM_CONTAINER_NAME:fpmservice  # 冒号前是正在運作的FPM容器名稱,後面是别名,别名會作為hostname在将啟動的容器内可見
-d  # detach
NGINX_IMAGE  # 鏡像名
           

解決第二個耦合關系:

$ sudo docker run --volumes-from WWW_CONTAINER_NAME
--link MYSQL_CONTAINER_NAME:mysql
-d
PHP_FPM_IMAGE
           

參考文檔:https://docs.docker.com/reference/run/

是以容器啟動的先後順序就出來了:

  1. MySQL Container
  2. WWW Container (由于沒有任何服務運作,容器run後會立即exit,可以使用 tail -f 等block指令使容器保持運作不退出)
  3. PHP-FPM Container
  4. Nginx Container

其中1和2可以對換。

3. Dockerfile

Dockerfiles 請參見:

https://github.com/micooz/dockerfile

http://git.oschina.net/micooz/dockerfile

4. 總結

利用Docker部署Web應用可以帶來很多便利,在宏觀上實作應用元件化,為實作分布式系統奠定了基礎。

可以看到實際上在Docker容器間共享資料是很友善的,搞清楚各容器的依賴關系就不難解決。

P.s. 本文是我學習docker兩天後的心得體會,纰漏在所難免,如有錯誤還請斧正。

版權聲明:本文為CSDN部落客「weixin_34166472」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。

原文連結:https://blog.csdn.net/weixin_34166472/article/details/91871085