「GoCN酷Go推薦」使用GO語言啟動docker Container
推薦背景
在日常開發(fā)中,測試是不可避免的,在針對DAO層的代碼寫測試用例的時候,直接將依賴的存儲服務(wù)(比如mongodb)的client給mock掉,可能達不到檢驗代碼中語法或數(shù)據(jù)操作正確性的目的。如果在本地起一個相關(guān)的存儲服務(wù)又會由于不同的項目帶來環(huán)境的污染,并且測試代碼由于依賴本地環(huán)境可能導(dǎo)致多人協(xié)作困難。在云原生時代,你可能第一想到的就是利用docker container 來解決環(huán)境問題,而本文所推薦的就是用 go 語言來操作docker的開源項目。
項目鏈接:https://github.com/moby/moby
快速使用
準(zhǔn)備環(huán)境
安裝docker:https://www.docker.com/
安裝
//?安裝?docker?client
go?get?github.com/docker/docker/client
啟動mongo
package?main
import?(
?"context"
?"fmt"
?"github.com/docker/docker/api/types"
?"github.com/docker/docker/api/types/container"
?"github.com/docker/docker/client"
?"github.com/docker/go-connections/nat"
)
const?(
?mongoExposedPort?=?"27017/tcp"
)
func?main(){
?cli,?err?:=?client.NewEnvClient()?//?初始化?docker?client
?if?err?!=?nil{
??panic(err)
?}
?ctx?:=?context.Background()
?//?創(chuàng)建一個container
?resp,?err?:=?cli.ContainerCreate(ctx,
??&container.Config{
???Image:?"mongo:latest",?//?鏡像名:推薦提前下好
???ExposedPorts:?nat.PortSet{
????mongoExposedPort:?{},???//?暴露的端口號:可以使用想用命令啟動一個,然后通過docker ps 看
???},
??},
??&container.HostConfig{
???PortBindings:?nat.PortMap{
????mongoExposedPort:?[]nat.PortBinding{?//?端口映射:將容器里的 27017 映射到本機的 27017 端口
?????{
??????HostIP:?"127.0.0.1",
??????HostPort:?"0",?//?這個值如果是0,就會選一個未被占用的端口
?????},
????},
???},
??},
??nil,?//?網(wǎng)絡(luò)配置:默認將可以
??nil,?????//?平臺描述:不用傳
??"",?//?容器名:傳空會隨機分配
?)
?if?err?!=?nil{
??panic(err)
?}
?err?=?cli.ContainerStart(ctx,?resp.ID,?types.ContainerStartOptions{})?//?start?container
?if?err?!=?nil?{
??panic(err)
?}
?fmt.Println("container?start?...")
?result,?err?:=?cli.ContainerInspect(ctx,?resp.ID)
?if?err?!=?nil?{
??panic(err)
?}
?addr?:=?result.NetworkSettings.Ports[mongoExposedPort][0]?//?查看綁定到的地址
?fmt.Printf("binding?port:?%v\n",?addr)
?err?=?cli.ContainerRemove(ctx,resp.ID,types.ContainerRemoveOptions{?//?remove?container
??Force:?true,?//?強制刪除
?})
?if?err?!=?nil{
??panic(err)
?}
?fmt.Println("container?kill?...")
}
封裝容器運行的庫函數(shù)
//?封裝在容器運行mongodb的函數(shù)
package?mongotest
import?(
?"context"
?"fmt"
?"github.com/docker/docker/api/types"
?"github.com/docker/docker/api/types/container"
?"github.com/docker/docker/client"
?"github.com/docker/go-connections/nat"
?"testing"
)
const?(
?mongoExposedPort?=?"27017/tcp"
)
func?RunWithMongo(m?*testing.M,?mongoURI?*string)?int{
?cli,?err?:=?client.NewEnvClient()?//?初始化?docker?client
?if?err?!=?nil{
??panic(err)
?}
?ctx?:=?context.Background()
?//?創(chuàng)建一個container
?resp,?err?:=?cli.ContainerCreate(ctx,
??&container.Config{
???Image:?"mongo:latest",?//?鏡像名:推薦提前下好
???ExposedPorts:?nat.PortSet{
????mongoExposedPort:?{},???//?暴露的端口號:可以使用想用命令啟動一個,然后通過docker ps 看
???},
??},
??&container.HostConfig{
???PortBindings:?nat.PortMap{
????mongoExposedPort:?[]nat.PortBinding{?//?端口映射:將容器里的 27017 映射到本機的 27017 端口
?????{
??????HostIP:?"127.0.0.1",
??????HostPort:?"0",?//?這個值如果是0,就會選一個未被占用的端口
?????},
????},
???},
??},
??nil,?//?網(wǎng)絡(luò)配置:默認將可以
??nil,?????//?平臺描述:不用傳
??"",?//?容器名:傳空會隨機分配
?)
?if?err?!=?nil{
??panic(err)
?}
?containerID?:=?resp.ID
?defer?func()?{
??err?=?cli.ContainerRemove(ctx,containerID,types.ContainerRemoveOptions{?//?remove?container
???Force:?true,?//?強制刪除
??})
??if?err?!=?nil{
???panic(err)
??}
?}()
?err?=?cli.ContainerStart(ctx,?containerID,?types.ContainerStartOptions{})?//?start?container
?if?err?!=?nil?{
??panic(err)
?}
?result,?err?:=?cli.ContainerInspect(ctx,?resp.ID)
?if?err?!=?nil?{
??panic(err)
?}
?addr?:=?result.NetworkSettings.Ports[mongoExposedPort][0]?//?查看綁定到的地址
?*mongoURI?=?fmt.Sprintf("mongodb://%s:%s",?addr.HostIP,?addr.HostPort)
?return?m.Run()
}
//?真實的測試代碼
package?docker_demo
import?(
?mongotest?"github.com/zrruirui/docker-demo/mongo"
?"os"
?"testing"
)
var?mongoURI?=?""
func?TestMain(m?*testing.M){
?os.Exit(mongotest.RunWithMongo(m,?&mongoURI))
}
func?TestA(t?*testing.T){
?//?寫自己的單測代碼
?t.Log(mongoURI)
}
總結(jié)
https://github.com/moby/moby 這個項目中有很多對容器的操作,在我的demo項目中只用了其中的很小一部分,用來解決單測 mock db問題,其他更復(fù)雜的功能有需要可自行查閱。
感謝
特別感謝 ccmouse 老師的講解,我是從他那里了解了這個庫并在日常開發(fā)中使用。
《酷Go推薦》招募:
各位Gopher同學(xué),最近我們社區(qū)打算推出一個類似GoCN每日新聞的新欄目《酷Go推薦》,主要是每周推薦一個庫或者好的項目,然后寫一點這個庫使用方法或者優(yōu)點之類的,這樣可以真正的幫助到大家能夠?qū)W習(xí)到
新的庫,并且知道怎么用。
大概規(guī)則和每日新聞類似,如果報名人多的話每個人一個月輪到一次,歡迎大家報名!戳「閱讀原文」,即可報名
掃碼也可以加入 GoCN 的大家族喲~
評論
圖片
表情
