來源:Linux學習
ID:LoveLinux1024
一般說來 SPA 的專案我們只要啟一個靜態檔案 Server 就可以了,但是針對傳統專案就不一樣了,一個專案會依賴很多服務端程式。之前我們的開發樣式是在一臺開發機上部署開發環境,所有人都在這臺開發機上使用 Samba 連線開發。老式開發是沒什麼問題的,但是前端因為引入了編譯流程,增加了 Webpack 打包構建的行為,當多人共同開發的時候經常會因為記憶體爆滿行程被殺導致打包失敗。痛定思痛後為瞭解決這個問題,我決定將 Docker 引入我們的開發環境,透過將開發環境本地化來解決這個問題,所以有了本文。
本文內容主要是我之前分享的文字版,若想看重點的話可以看之前的Slide①
也可以檢視分享影片②
Why Docker?
普通的 Web 服務一般都會依賴很多程式,例如 PHP, MySQL, Redis, Node 等等。正常情況下我們會去手動安裝這些程式來配置服務需要的環境,這樣會帶來幾個問題:
-
同一環境不同的服務依賴同一個軟體的不同版本,經典的例如 python2 和 python3, 本地 Mac 上是 PHP7,但是服務只能支援 PHP5.6。
-
同一環境不同的服務可能會修改同一份檔案,例如系統的配置,Nginx 的配置等,都會造成影響。
-
同一服務在多臺機器上部署需要手工操作,導致大量的人力成本浪費。
這樣逐個的安裝軟體實在是太麻煩了,所以大家就想乾脆就直接把整個系統打包好放到機器上得了,於是就出現了虛擬機器技術。這樣做能保證系統環境的穩定以及重覆的手工操作可以避免,但是也同樣會帶來一些問題:
-
打包後的虛擬機器檔案包含系統映象所以特別大。
-
打包後的虛擬機器檔案包含系統映象所以服務需要等待系統啟動成功之後才能啟動。
-
打包過程無法實現自動化。
針對第三點,後來出現了 Vagrant 使用 vagrantfile 的形式將映象構建指令碼化從而實現自動化的功能,不過其它兩點沒有解決。所以後來就出來了系統之上的行程級別虛擬化技術 —— Docker。它為我們帶來了以下幾個優點:
-
不需要打包系統進映象所以體積非常小
-
不需要等待虛擬系統啟動所以啟動快速資源佔用低
-
沙箱機制保證不同服務之間環境隔離
-
Dockerfile 映象構建機制讓映象打包部署自動化
-
Docker hub 提供映象平臺方便共享映象
以下是 VM 和 Docker 技術的具體區別,可以看到 VM 是打包了 Guest OS 進入映象中的,而 Docker 是直接基於宿主系統虛擬化的實體。
Docker 基礎
Docker 支援 Windows/Linux/Mac/AWS/Azure 多種平臺的安裝,其中 Windows 需要 Win10+,Mac 需要 EI Captain+。Docker 是一個 C/S 架構的服務,安裝好 docker 之後需要啟動 docker 軟體後才能使用 docker 命令。
Docker 主要有 Dockerfile, Image, Container, Repository 四個基本概念。透過 Dockerfile 我們可以生成 Docker Image(映象)。自己製作的映象可以上傳到 Docker hub 平臺,也可以從平臺上拉去我們需要的映象。當映象拉到本地之後,我們就可以實體化這個映象形成一個 Container(實體) 了。一個簡單的映象啟動的命令是:
$ docker run [組織名稱]/<映象名稱>:[映象標簽]`
其中除了映象名稱,其它的都是可選引數。組織名稱不填預設為library,映象標簽不填則預設為latest。例如經典的啟動一個 Hello World 映象的過程如下:
可以看到當我實體化hello-world這個映象的時候,docker 發現本地沒有這個映象會先去 Docker hub 遠端拉取映象,如剛才說的,預設是latest標簽。拉取後就會實體化執行入口命令了。我們除了可以使用 Docker hub 查詢我們需要的映象之外,也可以使用docker search命令來查詢。16年的一篇文章③顯示,Docker hub 上的映象包總量已經超過40萬了,並且以每週4-5k的速度增長著。
下麵我們就來看看如何執行一個 Nginx 容器實體:
$ docker run
-d
--rm
-p 8080:80
-v "$PWD/workspace":/var/www/hello.world
-v "$PWD/hello.world.conf":/etc/nginx/conf.d/hello.world.conf
nginx
使用docker run命令就能啟動一個實體了,其中-p表示將本機的 8080 埠對映到映象實體內的 80 埠,而-v表示將本地的$PWD/workspace檔案夾對映到映象實體裡的/var/www/hello.world檔案夾,後面的同理。最後再指定一下映象名稱,就能完成一次 Nginx 實體的啟動了。此時訪問http://hello.world:8080即可看到效果。
註:千萬不要在容器實體中儲存內容,實體銷毀時實體內的所有內容都會被銷毀,下次啟動的時候又是全新的實體,內容不會儲存下來。如果需要儲存服務需要使用掛載捲或者外部儲存服務。
Dockerfile
Dockerfile 是 Docker 比較重要的概念。它是 Docker 建立映象的核心,它的出現給 Docker 提供了兩大好處:
-
文字化的映象生成操作讓其方便版本管理和自動化部署
-
每條命令對應映象的一層,細化操作後保證其可增量更新,復用映象塊,減小映象體積
Dockerfile 的一些編寫規則主要如下:
-
使用#來註釋
-
FROM 指令告訴 Docker 使用哪個映象作為基礎
-
RUN 開頭的指令會在建立中執行,比如安裝一個軟體包
-
COPY 指令將檔案複製進映象中
-
WORKDIR 指定工作目錄
-
CMD/ENTRYPOINT 容器啟動執行命令
RUN 和 CMD/ENTRYPOINT 都是執行命令,區別在於 RUN 是在映象構建過程中執行的,而 CMD/ENTRYPOINT 是在映象生成實體的時候執行的,類似於 C/C++ 語言的頭檔案的正常程式碼的區別。而且後者在一個 Dockerfile 檔案中只能有一個存在。CMD/ENTRYPOINT 的區別除了在寫法上有區別之外,還有在docker run命令後增加 CMD 引數的情況下有區別(CMD會被覆寫)。一般建議使用 ENTRYPOINT 會更方便點。一個簡單的 Node 命令列指令碼的 Dockerfile 檔案如下:
FROM mhart/alpine-node:8.9.3 LABEL maintainer="lizheming "
org.label-schema.name="Drone Wechat Notification"
org.label-schema.vendor="lizheming"
org.label-schema.schema-version="1.1.0"
WORKDIR /wechat
COPY package.json /wechat/package.json
RUN npm install --production --registry=https://registry.npm.taobao.org
COPY index.js /wechat/index.js
ENTRYPOINT [ "node", "/wechat/index.js" ]
這裡我認為依賴是比較固定的,沒有程式碼修改那麼頻繁,所以將其提前了。最終保證了所以越穩定的變化的命令至於上層,保證了每層打包出來的 Layer 能夠盡可能的復用,而不會徒增映象的大小。最後我們使用如下命令就可以完成一個 Docker 映象的構建了:
$ docker build lizheming/drone-wechat:latest
引數和docker run是一樣的。構建完成之後就可以開心的 push 到 Docker hub 上啦~
Docker Compose
以上我們說了下如何啟動一個服務,但是我們都明白一個完整的專案肯定是不止依賴一個服務的,而 Docker 映象的 ENTRYPOINT 只能設定一個,所以難道我們要使用docker run命令手動建立 N 個容器實體嗎?為瞭解決這個問題,Docker Compose 就瞬時出現了。Docker Compose 是一款容器編排程式,使用 YAML 配置的形式將你需要啟動的容器管理起來,免去我們需要多次執行docker run命令的煩惱。
Docker Compose 是使用 Python 開發的,它的安裝非常的簡單,直接pip install docker-compose就好了。安裝完成之後分別使用up和stop命令可以啟動和停止服務。一個簡單的 docker-compose.yaml 配置檔案大概如下:
version: "2"
services:
nginx:
depends_on:
- "php"
image: "nginx:latest"
volumes:
- "$PWD/src/docker/conf:/etc/nginx/conf.d"
- "$PWD:/home/q/system/m_look_360_cn"
ports:
- "8082:80"
container_name: "m.look.360.cn-nginx"
php:
image: "lizheming/php-fpm-yaf"
volumes:
- "$PWD:/home/q/system/m_look_360_cn"
container_name: "m.look.360.cn-php"
Docker Compose 的另外一個好處就是能夠幫我們處理容器的依賴關係,在每個容器中會將容器的 IP 和服務的名稱使用 hosts 的方式系結,這樣我們就能在容器中直接使用服務名稱來接入對應的容器了。例如下麵這個 Nginx 配置中的php:9000就是利用了這個原理。
server {
listen 80;
server_name dev.m.look.360.cn;
charset utf-8;
root /home/q/system/m_look_360_cn/public;
index index.html index.htm index.php;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ .php$ {
fastcgi_pass php:9000;
#fastcgi_pass unix:/tmp/fcgi.sock;
fastcgi_index index.php;
}
}
Docker 相關
基於 Docker 容器虛擬化技術除了以上說的解決部署環境之外,還有一些其它的優點,例如:
-
基於 Docker 的 CI 持續整合和 CD 持續支付
-
基於 Kubernetes, Docker Swarm 的叢集彈性擴容和縮容
CI/CD 對於現在的敏捷開發是非常重要的,自動化任務幫助我們節省很多不必要的開發時間浪費,具體可檢視我之間的文章《基於Docker的CI工具》④。而 k8s 和 Docker Swarm 帶來的彈性擴容和縮容讓業務不在為流量問題而頭疼。透過監控報警設定當出現峰值的時候自動擴容抗壓,當出現低谷的時候自動去除多餘的容器來節省成本,同時也將多餘的資源給其它服務使用。
學習資料
-
什麼是 Docker ?https://cloud.tencent.com/developer/article/1005172
-
Docker 從入門到實踐https://yeasy.gitbooks.io/docker_practice/
-
Docker compose 詳解https://www.jianshu.com/p/2217cfed29d7
-
深入淺出Dockerhttps://www.kancloud.cn/infoq/docker/79768
文章中的連結
①https://ppt.baomitu.com/d/025d62c6
②http://cloud.live.360vcloud.net/theater/play?roomid=2321
③https://medium.com/microscaling-systems/how-many-public-images-are-there-on-docker-hub-bcdd2f7d6100
④https://imnerd.org/drone.html
來自:怡紅院落 ,作者:怡紅公子
連結:https://imnerd.org/docker-in-action.html
《Linux雲端計算及運維架構師高薪實戰班》2018年05月14日即將開課中,120天衝擊Linux運維年薪30萬,改變速約~~~~
*宣告:推送內容及圖片來源於網路,部分內容會有所改動,版權歸原作者所有,如來源資訊有誤或侵犯權益,請聯絡我們刪除或授權事宜。
– END –
更多Linux好文請點選【閱讀原文】哦
↓↓↓