maven和docker_与Maven和Docker的集成测试
maven和docker
Docker是其中的新熱點之一。 與傳統虛擬機相比,它具有一組不同的技術和思想,并通過容器的思想實現了相似但同時又有所不同的東西:幾乎所有VM都具有強大的功能,但速度更快,并且還具有許多有趣的附加功能。
在本文中,我假設您已經對Docker有所了解,并且知道如何與之交互。 如果不是這種情況,我可以建議您從以下鏈接開始:
- http://www.docker.io/gettingstarted
- http://coreos.com/docs/launching-containers/building/getting-started-with-docker/
- http://robknight.org.uk/blog/2013/05/drupal-on-docker/
我對該主題的個人貢獻是向您展示可能的工作流程 ,使您可以從Maven作業中啟動和停止Docker容器。
我研究此功能的原因是為了幫助使用Maven構建的Java項目中的測試和集成測試 。 這個問題是眾所周知的:您的代碼與外部系統和服務交互。 根據您實際編寫的內容,這可能意味著數據庫,消息代理,Web服務等。
測試這些交互的常用策略是:
- 在內存服務器中; 用Java實現,通常很快,但是很多時候它們的局限性在于它們不是真實的東西
- 您實現的存根服務層,以提供所需的接口。
- 真實的外部流程 (有時是遠程的),用于測試真實的交互。
這些策略有效,但通常需要付出很多努力才能落實到位。 最完整的一種,即使用適當的外部服務的那種,會給與隔離有關的問題帶來問題:想象一下您正在與數據庫進行交互,并且在其他人訪問相同資源的同時執行讀/寫操作。 同樣,您可能會找到正確的工作流程,這些工作流程涉及創建單獨的模式等等,但是,這又是額外的工作,而且通常不是很簡單的活動。
如果我們能擁有與這些外部系統相同的機會,但完全隔離,那不是很好嗎? 如果我也增加報價,您會怎么看?
Docker是為我們提供這一機會的工具。
在測試套件的開頭,您可以使用所需的所有服務啟動一組Docker容器,并在結束時將其拆解。 您的Maven工作可以成為這些服務的唯一使用者,并且需要所有隔離功能。 您可以在Dockerfile的幫助下輕松編寫所有腳本,最后,它們只不過是一系列順序的命令行調用。
讓我們看看如何啟用所有這些功能。
顯然,第一個前提條件是在您的系統上安裝Docker。 您可能已經知道Docker技術取決于Linux內核的功能,所以您必須使用Linux或需要傳統VM的幫助來托管D??ocker服務器進程。
這是官方文檔指南,向您展示如何在不同的Linux發行版中進行安裝: http : //docs.docker.io/en/latest/installation/
相反,這是一個非常快速的指南,顯示了如何在MacOSX上進行安裝: http : //blog.javabien.net/2014/03/03/setup-docker-on-osx-the-no-brainer-way /
準備就緒并安裝Docker后,需要應用特定的配置 。
在最新版本的Docker中,默認情況下僅通過Unix套接字公開其遠程API。 盡管我們可以使用正確的代碼與它們進行交互,但我發現通過HTTP與API進行交互要容易得多。 為此,您必須將特定標志傳遞給Docker守護進程,以使其也監聽HTTP。
我正在使用Fedora,要修改的配置文件是/usr/lib/systemd/system/docker.service 。
[Unit] Description=Docker Application Container Engine Documentation=http://docs.docker.io After=network.target[Service] ExecStart=/usr/bin/docker -d -H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock Restart=on-failure[Install] WantedBy=multi-user.target與默認值相比,唯一的修改是添加了-H tcp://127.0.0.1:4243 。
現在,在重新加載systemd腳本并重新啟動服務之后,我有了一個Docker守護程序,該守護程序向我展示了一個不錯的REST API ,可以用curl戳一下。
sudo systemctl daemon-reload sudo systemctl restart docker curl http://127.0.0.1:4243/images/json # returns a json in output您可能還希望此配置能夠在將來的Docker rpm更新中保留下來。 為了實現這一點,您必須將剛剛修改的文件復制到可以保留rpm更新的位置。 在systemd實現此目標的正確方法是:
sudo cp /usr/lib/systemd/system/docker.service /etc/systemd/system如果您使用的是Ubuntu ,則必須配置其他文件。 查看此頁面: http : //blog.trifork.com/2013/12/24/docker-from-a-distance-the-remote-api/
現在,我們擁有與Docker輕松交互所需的一切。
您可能會期望我在此向您介紹如何使用Maven Docker插件 。 不幸的是,事實并非如此。 還沒有這樣的插件 ,或者至少我不知道它。 我正在考慮編寫一個,但是目前我已經借助GMaven插件,一些Groovy代碼和Java庫Rest-assuredSwift解決了我的問題。
這是啟動Docker容器的代碼
import com.jayway.restassured.RestAssured import static com.jayway.restassured.RestAssured.* import static com.jayway.restassured.matcher.RestAssuredMatchers.* import com.jayway.restassured.path.json.JsonPath import com.jayway.restassured.response.ResponseRestAssured.baseURI = "http://127.0.0.1" RestAssured.port = 4243// here you can specify advance docker params, but the mandatory one is the name of the Image you want to use def dockerImageConf = '{"Image":"${docker.image}"}' def dockerImageName = JsonPath.from(dockerImageConf).get("Image")log.info "Creating new Docker container from image $dockerImageName" def response = with().body(dockerImageConf).post("/containers/create")if( 404 == response.statusCode ) {log.info "Docker image not found in local repo. Trying to dowload image '$dockerImageName' from remote repos"response = with().parameter("fromImage", dockerImageName).post("/images/create")def message = response.asString()//odd: rest api always returns 200 and doesn't return proper json. I have to grepif( message.contains("404") ) fail("Image $dockerImageName NOT FOUND remotely. Abort. $message}")log.info "Image downloaded"// retry to create the containerresponse = with().body(dockerImageConf).post("/containers/create")if( 404 == response.statusCode ) fail("Unable to create container with conf $dockerImageConf: ${response.asString()}") }def containerId = response.jsonPath().get("Id")log.info "Container created with id $containerId"// set the containerId to be retrieved later during the stop phase project.properties.setProperty("containerId", "$containerId")log.info "Starting container $containerId" with().post("/containers/$containerId/start").asString()def ip = with().get("/containers/$containerId/json").path("NetworkSettings.IPAddress")log.info "Container started with ip: $ip" System.setProperty("MONGODB_HOSTNAME", "$ip") System.setProperty("MONGODB_PORT", "27017")這是阻止他們的人
import com.jayway.restassured.RestAssured import static com.jayway.restassured.RestAssured.* import static com.jayway.restassured.matcher.RestAssuredMatchers.*RestAssured.baseURI = "http://127.0.0.1" RestAssured.port = 4243def containerId = project.properties.getProperty('containerId') log.info "Stopping Docker container $containerId" with().post("/containers/$containerId/stop") log.info "Docker container stopped" if( true == ${docker.remove.container} ){with().delete("/containers/$containerId")log.info "Docker container deleted" }放心的流利API應該可以提示正在發生的事情,內聯注釋應該可以澄清它,但是讓我添加一些注釋。 啟動容器的代碼是我對docker run功能的實現,如此處的官方API文檔所述: http : //docs.docker.io/en/latest/reference/api/docker_remote_api_v1.9/#inside-docker -跑
我要解決的特定問題是如何將Docker容器的ID從Maven階段傳播到另一個階段 。 通過以下代碼,我已經實現了功能:
// set the containerId to be retrieved later during the stop phase project.properties.setProperty("containerId", "$containerId")我還公開了一些Maven屬性,可用于與API交互:
- docker.image –您要旋轉的圖像的名稱
- docker.remove.container –如果設置為false,則告訴Maven不要從文件系統中刪除已停止的容器(在作業完成后用于檢查Docker容器)
例如
mvn verify -Ddocker.image=pantinor/fuse -Ddocker.remove.container=false您可以在此處找到完整的工作示例。 有人告訴我,有時我的語法著色器腳本會吃一些關鍵字或更改單詞的大小寫,因此,如果要復制和粘貼,可能是從Github裁剪的一個更好的主意。
這是使用命令mvn verify運行Maven構建時輸出的一部分:
... [INFO] --- gmaven-plugin:1.4:execute (start-docker-images) @ gmaven-docker --- [INFO] Creating new Docker container from image {"Image":"pantinor/centos-mongodb"} log4j:WARN No appenders could be found for logger (org.apache.http.impl.conn.BasicClientConnectionManager). log4j:WARN Please initialize the log4j system properly. [INFO] Container created with id 5283d970dc16bd7d64ec08744b5ecec09b57d9a81162826e847666b8fb421dbc [INFO] Starting container 5283d970dc16bd7d64ec08744b5ecec09b57d9a81162826e847666b8fb421dbc [INFO] Container started with ip: 172.17.0.2...[INFO] --- gmaven-plugin:1.4:execute (stop-docker-images) @ gmaven-docker --- [INFO] Stopping Docker container 5283d970dc16bd7d64ec08744b5ecec09b57d9a81162826e847666b8fb421dbc [INFO] Docker container stopped [INFO] Docker container deleted...如果您有任何疑問或建議,請隨時告訴我!
完整的Maven`pom.xml`也可以在這里找到: https ://raw.githubusercontent.com/paoloantinori/gmaven_docker/master/pom.xml
<!--?xml version="1.0"?--> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelversion>4.0.0</modelversion><artifactid>gmaven-docker</artifactid><groupid>paolo.test</groupid><version>1.0.0-SNAPSHOT</version><name>Sample Maven Docker integration</name><description>See companion blogpost here: </description><build><plugins><plugin><groupid>org.codehaus.gmaven</groupid><artifactid>gmaven-plugin</artifactid><version>1.4</version><configuration><providerselection>2.0</providerselection></configuration><executions><execution><id>start-docker-images</id><phase>test</phase><goals><goal>execute</goal></goals><configuration><source><!--[CDATA[ import com.jayway.restassured.RestAssured import static com.jayway.restassured.RestAssured.* import static com.jayway.restassured.matcher.RestAssuredMatchers.*RestAssured.baseURI = "http://127.0.0.1" RestAssured.port = 4243// here you can specify advance docker params, but the mandatory one is the name of the Image you want to use def dockerImage = '{"Image":"pantinor/centos-mongodb"}'log.info "Creating new Docker container from image $dockerImage" def response = with().body(dockerImage).post("/containers/create")if( 404 == response.statusCode ) {log.info "[INFO] Docker Image not found. Downloading from Docker Registry"log.info with().parameter("fromImage", "pantinor/centos-mongodb").post("/images/create").asString()log.info "Image downloaded" }// retry to create the container def containerId = with().body(dockerImage).post("/containers/create").path("Id")log.info "Container created with id $containerId"// set the containerId to be retrieved later during the stop phase project.properties.setProperty("containerId", "$containerId")log.info "Starting container $containerId" with().post("/containers/$containerId/start").asString()def ip = with().get("/containers/$containerId/json").path("NetworkSettings.IPAddress")log.info "Container started with ip: $ip"System.setProperty("MONGODB_HOSTNAME", "$ip") System.setProperty("MONGODB_PORT", "27017") ]]--></configuration></execution><execution><id>stop-docker-images</id><phase>post-integration-test</phase><goals><goal>execute</goal></goals><configuration><source><!--[CDATA[ import com.jayway.restassured.RestAssured import static com.jayway.restassured.RestAssured.* import static com.jayway.restassured.matcher.RestAssuredMatchers.*RestAssured.baseURI = "http://127.0.0.1" RestAssured.port = 4243def containerId = project.properties.getProperty('containerId') log.info "Stopping Docker container $containerId" with().post("/containers/$containerId/stop") log.info "Docker container stopped" with().delete("/containers/$containerId") log.info "Docker container deleted" ]]--></configuration></execution></executions></plugin></plugins></build><dependencies><dependency><groupid>com.jayway.restassured</groupid><artifactid>rest-assured</artifactid><version>1.8.1</version><scope>test</scope></dependency></dependencies> </project> 參考:在Someday Never Comes博客上,我們的JCG合作伙伴 Paolo Antinori 與Maven和Docker進行了集成測試 。翻譯自: https://www.javacodegeeks.com/2014/03/integration-testing-with-maven-and-docker.html
maven和docker
總結
以上是生活随笔為你收集整理的maven和docker_与Maven和Docker的集成测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 春天重新审视战略模式
- 下一篇: 电脑怎么做幻灯片视频教程(电脑怎么做幻灯