1+1>2:用Docker和Vagrant構(gòu)建簡(jiǎn)潔高效開發(fā)環(huán)境
譯文Docker和Vagrant經(jīng)常被認(rèn)為是兩種相互替代的工具,其實(shí)它們可以結(jié)合使用,構(gòu)建隔離的、可重復(fù)的開發(fā)環(huán)境。我們將證明該環(huán)境可以構(gòu)建一個(gè)Docker容器以便開發(fā)Java應(yīng)用程序,并充分利用Vagrant的強(qiáng)大功能,以解決一些現(xiàn)實(shí)當(dāng)中的實(shí)際問題。
這篇博客的第一部分探討了開發(fā)環(huán)境的常見缺陷、簡(jiǎn)單Docker環(huán)境的構(gòu)建以及Vagrant+Docker配置具有的優(yōu)點(diǎn)。但是如果你想就開始使用Docker和Vagrant,不妨直接跳到本文的這個(gè)章節(jié):使用Vagrant,讓Docker容器易于移植。
開發(fā)環(huán)境有什么問題?
要花很長(zhǎng)的時(shí)間來構(gòu)建
新的開發(fā)人員要花多長(zhǎng)時(shí)間才能構(gòu)建好當(dāng)前項(xiàng)目的開發(fā)環(huán)境?答案取決于諸多因素(項(xiàng)目時(shí)間、從事該項(xiàng)目的開發(fā)人員數(shù)量等),但至少需要半天時(shí)間并不罕見。
嘿!其實(shí)應(yīng)該比這快得多:查看腳本,執(zhí)行腳本。就是這樣。這兩個(gè)步驟應(yīng)該足以構(gòu)建你的環(huán)境,并準(zhǔn)備隨時(shí)開發(fā)。
它可能與測(cè)試環(huán)境和生產(chǎn)環(huán)境大不一樣
你有沒有因構(gòu)建的環(huán)境在機(jī)器上未通過而跳過自動(dòng)化測(cè)試?或者更糟糕的是,即使更改的內(nèi)容在機(jī)器上順利編譯,但是在持續(xù)整合(CI)服務(wù)器上老是失敗,你有沒有查過問題的根源出在哪里?
任何稍有不同,就會(huì)導(dǎo)致意料不到的行為。有的方法可能很簡(jiǎn)單,比如試一試框架的上一個(gè)版本,或者改用不同的項(xiàng)目。
查明什么導(dǎo)致你的系統(tǒng)出現(xiàn)不同行為是每個(gè)開發(fā)人員都應(yīng)該避免的煩人任務(wù)。
虛擬機(jī)和Docker
因而,開發(fā)環(huán)境應(yīng)該具有兩個(gè)特點(diǎn):
隔離:你不希望在測(cè)試某個(gè)新工具或不同項(xiàng)目時(shí)弄得一團(tuán)糟。
可重復(fù):同一個(gè)環(huán)境應(yīng)該在每個(gè)團(tuán)隊(duì)成員的機(jī)器、持續(xù)整合服務(wù)器和生產(chǎn)服務(wù)器上都一再可復(fù)制。
虛擬機(jī)環(huán)境確保了這些特性,可是典型的虛擬機(jī)很耗費(fèi)資源。開發(fā)人員需要每隔幾分鐘編碼/構(gòu)建/測(cè)試,不會(huì)接受虛擬化帶來的開銷。
這時(shí)候,Docker顯得大有幫助。相比典型的虛擬機(jī),其輕型容器極其快速,而且在開發(fā)人員當(dāng)中極受歡迎。下面是來自Docker博客的一段摘要,解釋了這種成功的原因:
| 在問世后的頭12個(gè)月內(nèi),Docker在初創(chuàng)企業(yè)和早期采用者當(dāng)中迅速流行起來,他們重視該平臺(tái)的這一功能,即可以將應(yīng)用程序開發(fā)管理的問題與基礎(chǔ)設(shè)施提 供、配置和運(yùn)營(yíng)的問題分離開來。Docker為這些早期用戶提供了一種新穎的、更迅速的方法,可以構(gòu)建分布式應(yīng)用程序,另外提供了一種“編寫一次到處運(yùn) 行”的部署選擇,部署對(duì)象從筆記本電腦、裸機(jī)、虛擬機(jī)到私有云/公有云,不一而足。 | 
使用Docker來配置的、可重復(fù)的開發(fā)環(huán)境
為了舉例說明,我們將構(gòu)建一個(gè)構(gòu)建并測(cè)試Vert.x HTTP服務(wù)器的Docker容器。
Vert.x是一種輕型應(yīng)用程序框架,鼓勵(lì)小型、獨(dú)立微服務(wù)的架構(gòu)。微服務(wù)“就是一種小巧的獨(dú)立式可執(zhí)行程序,可與其他的獨(dú)立式可執(zhí)行程序進(jìn)行溝通”(Uncle Bob,http://blog.cleancoder.com/uncle-bob/2014/09/19/MicroServicesAndJars.html)。我們認(rèn)為,它在Docker容器中再合適不過了,這就是為什么我們?cè)诖诉x擇它作為例子。
要是你之前還沒有安裝過Docker,先安裝它。你可以參閱官方文檔(https://docs.docker.com/installation/),或者使用get docker script(https://get.docker.io)來安裝它。我們假設(shè)在本章節(jié)中,我們?cè)贚inux上運(yùn)行。即使Docker也可以安裝到Windows和Mac上(借助boot2docker),我們會(huì)在下一章中看到如何使用Vagrant來安裝、為什么Vagrant是一種更好的選擇。
#p#
Docker文件(Dockerfile)
為了描述容器,我們需要一個(gè)Docker文件:
FROM ubuntu:14.04
# 安裝開發(fā)工具:jdk和git等
- RUN apt-get update
 - RUN apt-get install -y openjdk-7-jdk git wget
 
# jdk7是默認(rèn)JDK
- RUN ln -fs /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java /etc/alternatives/java
 
# 安裝vertx
- RUN \
 - mkdir -p /usr/local/vertx && cd /usr/local/vertx && \
 - wget http://dl.bintray.com/vertx/downloads/vert.x-2.1.2.tar.gz -qO - | tar -xz
 
# 將vertx添加到路徑
- ENV PATH /usr/local/vertx/vert.x-2.1.2/bin:$PATH
 - RUN mkdir -p /usr/local/src
 - WORKDIR /usr/local/src
 - CMD ["bash"]
 
Docker文件確實(shí)簡(jiǎn)單直觀,當(dāng)你需要更深入地挖掘時(shí),有一份出色的在線參考手冊(cè)(https://docs.docker.com/reference/builder/)。
FROM ubuntu:14.04定義了我們依賴的基本映像。你可以在docker中心(registry.hub.docker.co)找到Docker基本映像的完整列表。就這個(gè)例子而言,我們使用了docker團(tuán)隊(duì)構(gòu)建Docker所用的基本映像。
后面幾行描述了將應(yīng)用到基本映像上的改動(dòng):
- 使用apt-get安裝開發(fā)工具:openjdk、git、wget
 - 下載和安裝vertx
 - 將vertx二進(jìn)制文件夾添加到路徑
 - 創(chuàng)建文件夾/usr/local/src,并讓它成為默認(rèn)的工作目錄
 
一旦我們拷貝了Docker文件,就可以構(gòu)建Docker映像:
- $ sudo docker build -t=vertxdev .
 
獲得源代碼
我們剛構(gòu)建的映像已安裝了git。我們可以用它從Github獲取源代碼:
- $ sudo docker run -t --rm -v /src/vertx/:/usr/local/src vertxdev git clone https://github.com/vert-x/vertx-examples.git
 
請(qǐng)注意:git在容器里面運(yùn)行,源代碼因而在容器里面?zhèn)魉?確切的位置是在文件夾/usr/local/src)。為了讓代碼具有持續(xù)性,即使在容器停止和刪除之后,我們也可以使用標(biāo)志-v /src/vertx/:/usr/local/src,將容器的文件夾/usr/local/src綁定掛載到主機(jī)文件夾/src/vertx。一旦git clone命令完成了執(zhí)行,--rm”就銷毀容器。
構(gòu)建并運(yùn)行應(yīng)用程序
由于源代碼已獲取,我們將啟動(dòng)新的容器,這個(gè)容器負(fù)責(zé)構(gòu)建并運(yùn)行vertx示例:HelloWorldServer。要注意:vertx run同時(shí)負(fù)責(zé)vertx應(yīng)用程序的構(gòu)建和執(zhí)行。
- $ sudo docker run -d -v /src/vertx/:/usr/local/src -p 8080:8080 vertxdev vertx run vertx-examples/src/raw/java/httphelloworld/HelloWorldServer.java
 
與前一個(gè)容器相反,這個(gè)容器在停止后不會(huì)被銷毀,暴露端口8080(-p 8080:8080),在后臺(tái)運(yùn)行(-d)。若想看一看vertx run的輸出結(jié)果:
- $ sudo docker logs
 - Succeeded in deploying verticle
 
不妨使用curl,從主機(jī)端測(cè)試應(yīng)用程序:
- $ curl localhost:8080
 - Hello World
 
這個(gè)簡(jiǎn)單例子應(yīng)該足以體現(xiàn)出運(yùn)行Docker容器有多快速。在Docker容器里面運(yùn)行g(shù)it clone和vertx run的開銷可忽略不計(jì)。
但構(gòu)建的這個(gè)環(huán)境很基本。在現(xiàn)實(shí)環(huán)境中,純Docker配置存在一些不足,而Vagrant就有助于克服這些不足。
#p#
Docker + Vagrant
Docker(其實(shí)是作為Docker模塊的libcontainer)仍需要Linux內(nèi)核3.8或更高版本和x86_64架構(gòu)。這在大大限定了Docker能夠原生運(yùn)行在其中的環(huán)境。
Vagrant是一種開源軟件,它為跨眾多操作系統(tǒng)構(gòu)建可重復(fù)的開發(fā)環(huán)境提供了一種方法。Vagrant使用提供者(provider)來啟動(dòng)隔離的虛擬環(huán)境。默認(rèn)的提供者是Virtualbox;自v1.6以來,基于docker的開發(fā)環(huán)境也得到支持。相比幫助Docker在非Linux平臺(tái)上運(yùn)行的其他工具(比如boot2docker),Vagrant具有一些重大優(yōu)點(diǎn):
配置一次,即可到處運(yùn)行:Vagrant就是原生支持Docker的系統(tǒng)上的Docker封裝器,同時(shí)它可啟動(dòng)“主機(jī)虛擬機(jī)”,以便在不支持它的系統(tǒng)上運(yùn)行容器。用戶沒必要操心Docker是不是得到原生支持:同一個(gè)配置可適用于每一個(gè)操作系統(tǒng)。
- Docker主機(jī)并不局限于boot2docker(Tiny Core Linux的Virtualbox映像),但Debian、Ubuntu、CoreOS及其他Linux發(fā)行版也得到支持。而且可以在比Virtualbox更穩(wěn)定的虛擬機(jī)管理器(比如VMware)上運(yùn)行。
 - Vagrant可以編排Docker容器:同時(shí)運(yùn)行多個(gè)容器,并且把它們聯(lián)系起來。
 
在Linux及其他操作系統(tǒng)上使用Vagrant運(yùn)行Docker
在下面三個(gè)章節(jié)中,我們將探討這每一個(gè)要點(diǎn)。
使用vagrant,讓Docker容器易于移植
Vagrant可支持Docker,既作為提供者,又作為配置者。但是為了讓它可以在Windows和Mac上自動(dòng)創(chuàng)建Docker主機(jī)虛擬機(jī),應(yīng)該將它用作提供者。
我們將重復(fù)使用我們?cè)谏厦嬉姷降耐粋€(gè)Docker文件。與上面一樣,我們將運(yùn)行兩個(gè)Docker容器,以便執(zhí)行g(shù)it clone和vertx run。不過將改而使用Vagrant命令,而不是Docker命令。
安裝Vagrant(https://www.vagrantup.com/downloads)和Virtualbox(https://www.virtualbox.org/wiki/Downloads),以便能夠運(yùn)行示例。
Vagrantfile
Vagrantfile描述了Vagrant設(shè)備。我們將使用下列內(nèi)容:
- ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
 - Vagrant.configure("2") do |config|
 - config.vm.define "vertxdev" do |a|
 - a.vm.provider "docker" do |d|
 - d.build_dir = "."
 - d.build_args = ["-t=vertxdev"]
 - d.ports = ["8080:8080"]
 - d.name = "vertxdev"
 - d.remains_running = true
 - d.cmd = ["vertx", "run", "vertx-examples/src/raw/java/httphelloworld/HelloWorldServer.java"]
 - d.volumes = ["/src/vertx/:/usr/local/src"]
 - end
 - end
 - end
 
ENV'VAGRANT_DEFAULT_PROVIDER' = 'docker' 讓我們不必在每個(gè)Vagrant命令中指定提供者是Docker(默認(rèn)提供者是Virtualbox)。該文件的其余部分擁有Vagrant構(gòu)建Docker映像和運(yùn)行容器所用的選項(xiàng)。想了解更多信息,請(qǐng)參閱Vagrantfilehttps://docs.vagrantup.com/v2/vagra...(https://docs.vagrantup.com/v2/vagrantfile/index.html)和Docker提供者(https://docs.vagrantup.com/v2/docker/configuration.html)說明文檔。
獲得源代碼
一旦我們將Vagrantfile拷貝到Dockerfile文件夾中,我們可以運(yùn)行g(shù)it clone,以獲取源代碼:
- $ vagrant docker-run vertxdev -- git clone https://github.com/vert-x/vertx-examples.git
 
與之前一樣,git clone完成執(zhí)行后,容器將被銷毀。請(qǐng)注意:我們還沒有構(gòu)建映像,Vagrant自動(dòng)構(gòu)建了映像。減少了手動(dòng)步驟。
構(gòu)建并運(yùn)行應(yīng)用程序
我們能夠構(gòu)建并運(yùn)行HTTP Hello World服務(wù)器:
- $ vagrant up
 
在底層,Vagrant將執(zhí)行docker run,啟動(dòng)容器的命令由d.cmd選項(xiàng)指定。
想獲得vertx run命令的輸出結(jié)果:
- $ vagrant docker-logs
 - ==> vertxdev: Succeeded in deploying verticle
 
測(cè)試
在Linux平臺(tái)上,只要運(yùn)行:
- $ curl localhost:8080
 - Hello World
 
在Windows和Mac上,端口8080并不從Docker主機(jī)虛擬機(jī)被轉(zhuǎn)發(fā)到主vagrant主機(jī)(不過Docker容器端口被轉(zhuǎn)發(fā)到Docker主機(jī))。因而,我們需要通過ssh進(jìn)入到Docker主機(jī)虛擬機(jī),以便連接至HTTP服務(wù)器。不妨檢索Vagrant默認(rèn)Docker主機(jī)的ID:
- $ vagrant global-status
 - id name provider state directory
 - -------------------------------------------------------------------------------------------------------
 - c62a174 default virtualbox running /Users/mariolet/.vagrant.d/data/docker-host
 
一旦檢索到該設(shè)備,我們可以測(cè)試HTTP服務(wù)器了:
- $ vagrant ssh c62a174 -c "curl localhost:8080"
 - Hello World
 
#p#
你有說過一模一樣嗎?如何定制Docker主機(jī)?
在不支持容器的平臺(tái)上,默認(rèn)情況下,Vagrant啟動(dòng)一個(gè)Tiny Core Linux(boot2docker)Docker主機(jī)。如果我們的持續(xù)整合環(huán)境、試運(yùn)行環(huán)境或生產(chǎn)環(huán)境不運(yùn)行boot2docker,我們會(huì)在這些環(huán)境的配置之間有一個(gè)缺口。這實(shí)際上是生產(chǎn)環(huán)境缺陷的根源,不可能在開發(fā)環(huán)境中發(fā)現(xiàn)。不妨試著解決這個(gè)問題。
不同環(huán)境上的不同Docker主機(jī):實(shí)際上違反安全
如上所見,Vagrant的主要便利之一是,它讓我們可以指定自定義的Docker主機(jī)。換句話說,我們并不被boot2docker和Tiny Core Linux所束縛。
Docker主機(jī)虛擬機(jī)Vagrantfile
我們將使用一個(gè)新的Vagrantfile來定義Docker主機(jī)虛擬機(jī)。下面這個(gè)文件基于Ubuntu Server 14.04 LTS:
- Vagrant.configure("2") do |config|
 - config.vm.provision "docker"
 - # 下面這一行終結(jié)所有ssh連接,因此
 - # Vagrant將被迫重新連接。
 - # 那是在PATH中擁有docker命令的替代辦法
 - config.vm.provision "shell", inline:
 - "ps aux | grep 'sshd:' | awk '{print $2}' | xargs kill"
 - config.vm.define "dockerhost"
 - config.vm.box = "ubuntu/trusty64"
 - config.vm.network "forwarded_port",
 - guest: 8080, host: 8080
 - config.vm.provider :virtualbox do |vb|
 - vb.name = "dockerhost"
 - end
 - end
 
將它保存到原始的Vagrantfile文件夾,名稱為DockerHostVagrantfile。
在自定義的Docker主機(jī)中運(yùn)行Docker容器
下一步指定使用這個(gè)新的虛擬機(jī)作為Docker主機(jī),而不是默認(rèn)主機(jī),因而將下面新的兩行添加到a.vm.provider代碼段:
- config.vm.define "vertxdev" do |a|
 - a.vm.provider "docker" do |d|
 - [...]
 - d.vagrant_machine = "dockerhost"
 - d.vagrant_vagrantfile = "./DockerHostVagrantfile"
 - end
 - end
 
請(qǐng)注意:配置自定義的Docker主機(jī)有另一個(gè)好處:我們現(xiàn)在可以指定自定義的轉(zhuǎn)發(fā)端口:
- config.vm.network "forwarded_port",
 - guest: 8080, host: 8080
 
因而,我們能夠從主主機(jī)操作系統(tǒng)里面訪問vertx HTTP服務(wù)器:
不同環(huán)境上同樣的Docker主機(jī)和端口轉(zhuǎn)發(fā)
當(dāng)然,主機(jī)虛擬機(jī)并不局限于Ubuntu??梢栽赩agrant云(https://vagrantcloud.com)上發(fā)現(xiàn)更多的vagrant設(shè)備。值得關(guān)注的支持Docker的設(shè)備有boot2docker(原始版和改良版)和CoresOS。
#p#
使用Vagrant編排Docker容器
就在不久前,我們還每次只能運(yùn)行一個(gè)Docker容器。然而在現(xiàn)實(shí)生活中,我們卻常常需要同時(shí)運(yùn)行多個(gè)容器:數(shù)據(jù)庫、http、Web容器等都在單獨(dú)的容器中運(yùn)行。
我們?cè)诒菊鹿?jié)將探討使用Vagrant“多機(jī)器”環(huán)境(https://docs.vagrantup.com/v2/multi-machine/),同時(shí)執(zhí)行多個(gè)docker容器。然而,我們不會(huì)考慮Docker容器分布在不同的Docker主機(jī)這一場(chǎng)景:所有容器都在同一個(gè)主機(jī)里面運(yùn)行。
運(yùn)行多個(gè)容器
多個(gè)容器
作為第一個(gè)例子,我們將使用Vert.x Event Bus Point to Point這個(gè)例子。我們利用了在文章開頭定義的同一個(gè)Docker文件,并且在新的Vagrantfile文件里面配置了兩個(gè)Docker容器:“vertxreceiver”和“vertxsender”:
- ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
 - DOCKER_HOST_NAME = "dockerhost"
 - DOCKER_HOST_VAGRANTFILE = "./DockerHostVagrantfile"
 - Vagrant.configure("2") do |config|
 - config.vm.define "vertxreceiver" do |a|
 - a.vm.provider "docker" do |d|
 - d.build_dir = "."
 - d.build_args = ["-t=vertxreceiver"]
 - d.name = "vertxreceiver"
 - d.remains_running = true
 - d.cmd = ["vertx", "run", "vertx-examples/src/raw/java/eventbus_pointtopoint/Receiver.java","-cluster"]
 - d.volumes = ["/src/vertx/:/usr/local/src"]
 - d.vagrant_machine = "#{DOCKER_HOST_NAME}"
 - d.vagrant_vagrantfile = "#{DOCKER_HOST_VAGRANTFILE}"
 - end
 - end
 - config.vm.define "vertxsender" do |a|
 - a.vm.provider "docker" do |d|
 - d.build_dir = "."
 - d.build_args = ["-t=vertxsender"]
 - d.name = "vertxsender"
 - d.remains_running = true
 - d.cmd = ["vertx", "run", "vertx-examples/src/raw/java/eventbus_pointtopoint/Sender.java","-cluster"]
 - d.volumes = ["/src/vertx/:/usr/local/src"]
 - d.vagrant_machine = "#{DOCKER_HOST_NAME}"
 - d.vagrant_vagrantfile = "#{DOCKER_HOST_VAGRANTFILE}"
 - end
 - end
 - end
 
對(duì)這兩個(gè)docker容器而言,vagrant_mahchine即Docker主機(jī)虛擬機(jī)的ID是dockerhost。Vagrant要足夠智能化,才能重復(fù)使用dockerhost的同一個(gè)實(shí)例來運(yùn)行兩個(gè)容器。
想啟動(dòng)vertxsender和vertxreceiver,把Vagrantfile換成這一個(gè)文件,并運(yùn)行vagrant up:
- $ vagrant up
 - ...
 - $ vagrant docker-logs
 - ==> vertxsender: Starting clustering...
 - ==> vertxsender: No cluster-host specified so using address 172.17.0.18
 - ==> vertxsender: Succeeded in deploying verticle
 - ==> vertxreceiver: Starting clustering...
 - ==> vertxreceiver: No cluster-host specified so using address 172.17.0.19
 - ==> vertxreceiver: Succeeded in deploying verticle
 - ==> vertxreceiver: Received message: ping!
 - ==> vertxsender: Received reply: pong
 - ==> vertxreceiver: Received message: ping!
 - ==> vertxreceiver: Received message: ping!
 - ==> vertxsender: Received reply: pong
 - ==> vertxsender: Received reply: pong
 - ...
 
即使vertxsender和vertxreceiver根本不知道彼此的主機(jī)名和IP地址,vertx eventbus協(xié)議卻有一項(xiàng)發(fā)現(xiàn)功能,以便連接發(fā)送方和接收方。對(duì)于沒有類似功能的應(yīng)用程序而言,Docker提供了容器連接選項(xiàng)。
#p#
連接容器
在這個(gè)例子中,我們先運(yùn)行Docker容器(vertxdev),它啟動(dòng)我們之前看到的那個(gè)HelloWorld Web服務(wù)器。然后,第二個(gè)容器(vertxdev-client)將使用wget執(zhí)行HTTP請(qǐng)求:
- ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
 - Vagrant.configure("2") do |config|
 - config.vm.define "vertxdev" do |a|
 - a.vm.provider "docker" do |d|
 - d.image = "vertxdev:latest"
 - d.ports = ["8080:8080"]
 - d.name = "vertxdev"
 - d.remains_running = true
 - d.cmd = ["vertx", "run", "vertx-examples/src/raw/java/httphelloworld/HelloWorldServer.java"]
 - d.volumes = ["/src/vertx/:/usr/local/src"]
 - d.vagrant_machine = "dockerhost"
 - d.vagrant_vagrantfile = "./DockerHostVagrantfile"
 - end
 - end
 - config.vm.define "vertxdev-client" do |a|
 - a.vm.provider "docker" do |d|
 - d.image = "vertxdev:latest"
 - d.name = "vertxdev-client"
 - d.link("vertxdev:vertxdev")
 - d.remains_running = false
 - d.cmd = ["wget","-qO", "-","--save-headers","http://vertxdev:8080"]
 - d.vagrant_machine = "dockerhost"
 - d.vagrant_vagrantfile = "./DockerHostVagrantfile"
 - end
 - end
 - end
 
這個(gè)新Vagrantfile文件的重要部分是這一行d.link("vertxdev:vertxdev")。由于這一行,vertxdev-client就能夠解析主機(jī)名vertxdev,因而使用命令wget -qO - --save-headers http://vertxdev:8080,處理HTTP請(qǐng)求。
想運(yùn)行容器,把Vagrantfile換成這個(gè)新文件,并運(yùn)行vagrant up.。--no-parallel選項(xiàng)確保vertxdev容器在vertxdev-client之前啟動(dòng)。
- $ vagrant up --no-parallel
 
不妨看一下日志,以證實(shí)發(fā)生的情況:
- $ vagrant docker-logs
 - ==> vertxdev: Succeeded in deploying verticle
 - ==> vertxdev-client: HTTP/1.1 200 OK
 - ==> vertxdev-client: Content-Type: text/plain
 - ==> vertxdev-client: Content-Length: 11
 - ==> vertxdev-client:
 - ==> vertxdev-client: Hello World
 
#p#
伙計(jì),我的IDE在哪里?
雖然集成開發(fā)環(huán)境(IDE)是開發(fā)環(huán)境的一個(gè)重要部分,但我們還沒有討論它。那是由于圖形化應(yīng)用程序并不通常在Docker容器里面運(yùn)行。Eclipse或IntelliJ等IDE在主主機(jī)中通常很適合,源代碼在主機(jī)和容器之間使用Docker卷來共享。這就是本章節(jié)所介紹的內(nèi)容。
Vagrant隨帶synced_folder選項(xiàng),以便在docker容器和主主機(jī)之間共享文件夾:
- ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
 - Vagrant.configure("2") do |config|
 - config.vm.synced_folder ".", "/usr/local/src"
 - config.vm.define "vertxdev-src" do |a|
 - a.vm.provider "docker" do |d|
 - d.build_dir = "."
 - d.build_args = ["-t=vertxdev"]
 - d.ports = ["8080:8080"]
 - d.name = "vertxdev-src"
 - d.remains_running = true
 - d.cmd = ["vertx", "run", "vertx-examples/src/raw/java/httphelloworld/HelloWorldServer.java"]
 - d.vagrant_machine = "dockerhost"
 - d.vagrant_vagrantfile = "./DockerHostVagrantfile"
 - end
 - end
 - end
 
在這個(gè)例子中,vertxdev-src文件夾/usr/local/src將與主主機(jī)Vagrantfile文件夾(.)同步。請(qǐng)注意:Vagrant負(fù)責(zé)為我們構(gòu)建Docker卷。
一旦我們把Vagrantfile換成這一個(gè)文件,就可以運(yùn)行g(shù)it clone,再次使用vertxdev-src容器:
- $ vagrant docker-run vertxdev-src -- git clone https://github.com/vert-x/vertx-examples.git
 
一旦克隆完畢,源代碼將同時(shí)出現(xiàn)在容器和主主機(jī)。因而,我們可以直接訪問,還可以編輯文件:
- $ cd vertx-examples/src/raw/java/httphelloworld/
 - $ sed -i '' 's/Hello World/I m in a docker container and I feel good/' HelloWorldServer.java
 
想測(cè)試該應(yīng)用程序,運(yùn)行vagrant up:
- $ cd -
 - $ vagrant up
 - $ curl localhost:8080
 - I m in a docker container and I feel good
 
結(jié)束語
如果你在處理一系列不同的平臺(tái):一些平臺(tái)支持Docker,另一些不支持,那么使用Vagrant來控制Docker容器很有用。在這種場(chǎng)景下,使用Vagrant可以讓構(gòu)建環(huán)境的過程在不同平臺(tái)上具有一致性。
作為Vagrant的替代方案,F(xiàn)ig(http://www.fig.sh)無疑值得關(guān)注。Docker雇用Fig的主要開發(fā)人員,大力支持它,將其視作一種構(gòu)建基于Docker的開發(fā)環(huán)境的出色工具。
原文標(biāo)題:Setting up a development environment using Docker and Vagrant




















 
 
 





 
 
 
 