golang,docker,gradle

时间:2017-07-31 21:41:39

标签: docker go gradle

我刚开始使用Go(golang),并希望为将使用Gradle构建并部署到Docker镜像的项目设置新的项目文件夹结构。我很难确定这个项目结构的样子,主要是因为GOPATH结构以及Go语言工具似乎与使用Gradle或配置可克隆的项目(Git)相对立的事实。

该项目最终将包含用Go编写的各种服务器端代码,用HTML和JavaScript编写的客户端代码,因此我需要一个适合Gradle构建和打包所有这些类型的项目结构。

是否有人为此提供了良好的工作结构和工具建议?

2 个答案:

答案 0 :(得分:3)

当我开始使用Go时,我摆弄了各种各样的构建工具,从mavengulp

事实证明,至少对我来说,他们弊大于利,所以我开始使用Go看起来不那么惹人注目,但是经过深思熟虑的功能。其中一个是go generate。添加简单的shell脚本或偶尔使用Makefile进行自动化。

示例项目

我已经整理了一个示例项目,以使其更加清晰

/Users/you/go/src/bitbucket.org/you/hello/
├── Dockerfile
├── Makefile
├── _templates
│   └── main.html
└── main.go

main.go

这是一个简单的网络服务器,服务于“Hello,World!”使用优秀的go.rice工具嵌入到二进制文件中的模板:

//go:generate rice embed-go

package main

import (
    "html/template"
    "log"
    "net/http"

    rice "github.com/GeertJohan/go.rice"
)

func main() {

    templateBox, err := rice.FindBox("_templates")
    if err != nil {
        log.Fatal(err)
    }
    // get file contents as string
    templateString, err := templateBox.String("main.html")
    if err != nil {
        log.Fatal(err)
    }
    // parse and execute the template
    tmplMessage, err := template.New("message").Parse(templateString)
    if err != nil {
        log.Fatal(err)
    }

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if err := tmplMessage.Execute(w, map[string]string{"Greeting": "Hello, world!"}); err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
        }
    })

    log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}

注意这一行

//go:generate rice embed-go

当您致电go generate时,将扫描您的源文件以查找此类行,并执行相应的命令。在这种情况下,将生成一个名为rice-embed.go的文件,您的目录将如下所示:

/Users/you/go/src/bitbucket.org/you/hello/
├── Dockerfile
├── Makefile
├── _templates
│   └── main.html
├── main.go
└── rice-box.go

例如,您可以在//go generate中调用webpack,将您的内容放在一起,然后生成其他内容以从结果中创建rice-box.go。通过这种方式,您的所有内容都将嵌入到二进制文件中,并且可以轻松部署。

Dockerfile

我在这个例子中使用了一个相当简单的Dockerfile:

FROM alpine:latest
MAINTAINER You <you@example.com>
COPY hello /usr/bin
EXPOSE 8080
CMD ["/usr/bin/hello"]

然而,这给我们带来了一个问题:我们无法使用go:generate来生成docker镜像,因为当我们需要调用go:generate时,新的二进制文件尚未构建。这会让我们做一些丑陋的事情,比如

go generate && go build && go generate

导致docker图像构建两次以及诸如此类的东西。所以,我们需要一个不同的解决方案

解决方案A:shell脚本

我们当然可以想出类似的东西:

#!/bin/bash
# Checks for existence omitted for brevity
GO=$(which go)
DOCKER=$(which docker)
$GO generate
$GO test
$GO build
$DOCKER -t you/hello .

但是,这会带来一个问题:您将始终使用shell脚本执行整个序列。即使您只想运行测试,也最终会构建docker镜像。随着时间的推移,这加起来。在这种情况下,我倾向于使用

解决方案B:Makefile

Makefile是GNU make

的配置文件
    CC = $(shell which go 2>/dev/null)
    DOCKER = $(shell which docker 2>/dev/null)

    ifeq ($(CC),)
    $(error "go is not in your system PATH")
    else
    $(info "go found")
    endif

    ifeq ($(DOCKER),)
    $(error "docker not in your system path")
    else
    $(info "docker found")
    endif

    .PHONY: clean generate tests docker all

    all: clean generate tests hello docker

    clean:
        $(RM) hello rice-box.go cover.out
    generate:
        $(CC) generate
    tests: generate
        $(CC) test -coverprofile=cover.out
    hello: tests
        $(CC) build
    docker: hello
        $(DOCKER) build -t sosample/hello .

完整的解释超出了本答案的范围,但您基本上可以做的是,您可以调用make并构建all目标:删除旧版本中的文件(clean),生成新的rice-box.gogenerate),依此类推。但是,如果您只想运行测试,则调用make test只会执行目标cleangeneratetests

答案 1 :(得分:0)

您可以查看我构建项目的方法https://github.com/alehano/gobootstrap 这是一个网络框架。