虛擬化云和容器機(jī)器的發(fā)展,給我們帶來(lái)了極大的方便,尤其是開(kāi)發(fā)環(huán)境,開(kāi)發(fā)、測(cè)試、驗(yàn)證環(huán)境的維護(hù)和一致化一直困擾著開(kāi)發(fā)和測(cè)試人員,為了配置一個(gè)環(huán)境往往需要花費(fèi)大量的精力,而且還無(wú)法解決環(huán)境一致性問(wèn)題,由于環(huán)境差異導(dǎo)致的Bug問(wèn)題也讓開(kāi)發(fā)人員和測(cè)試耗費(fèi)大量的精力。如何解決這種問(wèn)題?那就是利用神器Docker容器了。本文蟲(chóng)蟲(chóng)將實(shí)例演示如何使用將Docker來(lái)輕松地建立一個(gè)高效的本地開(kāi)發(fā)環(huán)境。
開(kāi)發(fā)環(huán)境架構(gòu)
我們假設(shè)開(kāi)發(fā)組使用了下面一個(gè)典型的多余系統(tǒng)架構(gòu),其中涉及了NodeJS、Python、Golang、數(shù)據(jù)還有Web前端JS等應(yīng)用,架構(gòu)圖如下:
架構(gòu)組成
構(gòu)成部分由:
NJS1:NodeJS服務(wù),監(jiān)聽(tīng)端口7000,連接數(shù)據(jù)庫(kù)Db1(Psql數(shù)據(jù)庫(kù),監(jiān)聽(tīng)端口5433)。
Py1: Python服務(wù),監(jiān)聽(tīng)端口9000,連接數(shù)據(jù)庫(kù)Db1。
Go1: Golang服務(wù),監(jiān)聽(tīng)端口5000,連接數(shù)據(jù)庫(kù)Db1。
NJS2: NodeJS服務(wù),監(jiān)聽(tīng)端口8000,連接數(shù)據(jù)庫(kù)Db2(Psql數(shù)據(jù)庫(kù),監(jiān)聽(tīng)端口5432)。
Web服務(wù): webpack的開(kāi)發(fā)前端服務(wù)器,監(jiān)聽(tīng)端口8080。
以上環(huán)境可以通過(guò)監(jiān)聽(tīng)的端口互相通訊和數(shù)據(jù)交流。
問(wèn)題分析
管理繁瑣
要管理這些服務(wù),需要打開(kāi)大量終端窗口,然后單獨(dú)運(yùn)行,雖然可以使用screen和tmux這樣的神器來(lái)幫助我們使用多窗口,甚至工作界面的共享等,但是隨著要管理不斷增長(zhǎng),管理會(huì)相當(dāng)繁瑣耗時(shí)。
不一致的依賴環(huán)境
假設(shè)服務(wù)依賴于不同開(kāi)發(fā)語(yǔ)言的版本(比如Python 2和Python 3 )。我們就需要在運(yùn)行服務(wù)之前手動(dòng)切換環(huán)境中語(yǔ)言版本,當(dāng)然可以用多語(yǔ)言版本管理器比如pyenv我們服務(wù)業(yè)有可能需要多個(gè)數(shù)據(jù)庫(kù)服務(wù)器,那么在運(yùn)行服務(wù)之前,我們需要確保數(shù)據(jù)庫(kù)服務(wù)器運(yùn)行無(wú)誤,并且數(shù)據(jù)庫(kù)連接配置都無(wú)誤。還有更多的是開(kāi)發(fā)應(yīng)用的基礎(chǔ)類庫(kù)版本的依賴問(wèn)題。
基于Docker的開(kāi)發(fā)環(huán)境
Docker容器是一種完美的工具,可以輕松地一鍵創(chuàng)建,部署和運(yùn)行應(yīng)用程序。通過(guò)容器可以將所有需要的環(huán)境打包到一個(gè)鏡像中,然后通過(guò)鏡像一鍵生成開(kāi)發(fā)容器允。
Docker容器
理想的docker容器是一個(gè)超輕量級(jí)的linux的虛擬機(jī),在它上面運(yùn)行的應(yīng)用程序服務(wù)。容器中有應(yīng)用代碼及其所有依賴環(huán)境(系統(tǒng)庫(kù),工具等)。我們上面提到的架構(gòu),容器化后如下圖所示:
容器管理Docker Compose
Docker Compose是一個(gè)用于管理和編排容器定義和運(yùn)行的多應(yīng)用程序的工具(類似的流行工具還有谷歌的K8s)。通過(guò)Compose,可以使用YAML文件來(lái)配置應(yīng)用程序的服務(wù)。然后可以一鍵創(chuàng)建和運(yùn)行所有的服務(wù)。Docker Compose也提供Web UI管理界面和容器監(jiān)控系統(tǒng)等。。
Docker Compose由一下部分構(gòu)成
服務(wù):服務(wù)是可以用Compose工具運(yùn)行的各個(gè)docker容器列表。通過(guò)服務(wù)我們來(lái)定義各個(gè)容器名稱、端口以及其他配置。
網(wǎng)絡(luò):網(wǎng)絡(luò)組件提供了服務(wù)之間互相連接的通道。各個(gè)容器可以將自身附加到網(wǎng)絡(luò),相同網(wǎng)絡(luò)內(nèi)的所有容器可以彼此通信。
卷:默認(rèn)情況下,Docker容器不包含任何類型的持久性存儲(chǔ)。如果一個(gè)docker容器被關(guān)掉,那么其內(nèi)存中的所有數(shù)據(jù)都會(huì)丟掉。為了持久性保存一些數(shù)據(jù),我們需要數(shù)據(jù)卷來(lái)掛載到數(shù)據(jù)機(jī)硬盤上。
實(shí)戰(zhàn)配置
docker-compose.yml配置
我們上述典型環(huán)境的docker-compose.yml如下:
其中一個(gè)服務(wù)(njs1)的部分代碼如下:
服務(wù)運(yùn)行
配置好docker-compose.yml后,可以通過(guò)下面命令啟動(dòng)
docker-compose up
如果配置無(wú)誤,比如njs1成功啟動(dòng)后,將顯示:
在瀏覽器通過(guò)localhost:7000分文該服務(wù)。
常見(jiàn)docker-compose命令
build dockerfile的路徑。注意:可以指定包含Dockerfile的文件夾,也可以指定Dockerfile本身的完整路徑。
command 啟動(dòng)docker容器時(shí)運(yùn)行的命令。
environment 需要設(shè)置的所有環(huán)境變量。
ports 指定容器內(nèi)端口與主機(jī)端口的映射關(guān)系。
working_dir 這是希望運(yùn)行上面指定的命令的容器內(nèi)部的路徑。
啟動(dòng)所有服務(wù)
docker-compose start
該命令會(huì)啟動(dòng)docker-compose文件中的所有服務(wù)并以demon方式啟動(dòng),在后臺(tái)運(yùn)行。
停止所有服務(wù)
docker-compose start
停止所有服務(wù)
重啟服務(wù)
docker-compose restart njs1
啟動(dòng)特定服務(wù)
docker-compose up njs1
在docker-compose.yml服務(wù)列表中只啟動(dòng)njs1
查看特定服務(wù)的日志
docker-compose logs -f njs1
該命令將會(huì)在終端打印njs1的日志。
ssh連接到特定容器
docker-compose exec njs1 bash
總結(jié)
本文我們利用docker容器的方式來(lái)簡(jiǎn)化開(kāi)發(fā)環(huán)境的架構(gòu),解決典型開(kāi)發(fā)環(huán)境中管理繁瑣,環(huán)境一致性等問(wèn)題,為了簡(jiǎn)潔我們只以Docker Compose為例進(jìn)行了架構(gòu)重建。其實(shí)基于Docker編排管理系統(tǒng)K8S,結(jié)合Gitlab CI/CD功能,可以實(shí)現(xiàn)版本管理、測(cè)試、安全掃描、驗(yàn)證、發(fā)布等一鍵自動(dòng)化DevOps架構(gòu),以后我們會(huì)深入探索。






