diff --git a/README.md b/README.md index 02630f9..2be11e9 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,8 @@ The two templates are equivalent with `golang-http` using a structured request/r You can manage dependencies in one of the following ways: -- To use Go modules without vendoring, the default already is set `GO111MODULE=on` but you also can make that explicit by adding `--build-arg GO111MODULE=on` to `faas-cli up`, you can also use `--build-arg GOPROXY=https://` if you want to use your own mirror for the modules -- You can also Go modules with vendoring, run `go mod vendor` in your function folder and add `--build-arg GO111MODULE=off --build-arg GOFLAGS='-mod=vendor'` to `faas-cli up` +- To use Go modules without vendoring, the default already is set `GO111MODULE=on` but you also can make that explicit by adding `--build-arg GO111MODULE=on` to `faas-cli up`, you can also use `--build-arg GOPROXY=https://` if you want to use your own mirror for the modules. +- You can also Go modules with vendoring, run `go mod vendor`, the build process will automatically detect the vendor folder and configure the Go environment correctly. - If you have a private module dependency, we recommend using the vendoring technique from above. ## Adding static files to your image diff --git a/template/golang-http/Dockerfile b/template/golang-http/Dockerfile index e08b274..94e9d1c 100644 --- a/template/golang-http/Dockerfile +++ b/template/golang-http/Dockerfile @@ -20,8 +20,15 @@ ARG GO111MODULE="on" ARG GOPROXY="" ARG GOFLAGS="" ARG CGO_ENABLED=0 +ARG DEBUG=0 + +ENV DEBUG=${DEBUG} ENV CGO_ENABLED=${CGO_ENABLED} +ENV GOOS=${TARGETOS} +ENV GOARCH=${TARGETARCH} +ENV GO=/go/src/handler/go.sh +RUN chmod +x ${GO} # Run a gofmt and exclude all vendored code. RUN test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./function/vendor/*"))" || { echo "Run \"gofmt -s -w\" on your Golang code"; exit 1; } @@ -29,11 +36,10 @@ RUN test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*" -n WORKDIR /go/src/handler/function RUN mkdir -p /go/src/handler/function/static -RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go test ./... -cover +RUN ${GO} test ./... -cover WORKDIR /go/src/handler -RUN CGO_ENABLED=${CGO_ENABLED} GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ - go build --ldflags "-s -w" -a -installsuffix cgo -o handler . +RUN ${GO} build --ldflags "-s -w" -a -installsuffix cgo -o handler . FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine:3.15 # Add non root user and certs diff --git a/template/golang-http/go.sh b/template/golang-http/go.sh new file mode 100644 index 0000000..026f328 --- /dev/null +++ b/template/golang-http/go.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# go.sh is a wrapper for the Go command that will +# automatically set the required module related flags +# when a vendor folder is detected. +# +# Currently, in Go 1.18, Go Workspaces are incompatible +# with vendored modules. As a result, we must disable +# Go modules and use GOPATH mode. + +# We use this bash script to wrap Go commands because +# there is no clear way to set an env variable from the +# a script in a Dockerfile. +# It is possible to use `go env -w` but, but env varaibles +# have precedence and if it is set as an arg/env variable, +# then it will be ignored by the `go env -w`. + +# if the function/vendor folder exists +# then we set the env variables for +# GO111MODULE=off +if [ -d "/go/src/handler/function/vendor" ]; then + echo "Setting vendor mode env variables" + export GO111MODULE=off +fi + +# if DEBUG env is 1, print the go env +if [ "${DEBUG:-0}" = "1" ]; then + go env +fi + +go "$@" diff --git a/template/golang-middleware/Dockerfile b/template/golang-middleware/Dockerfile index 54f13f8..f7ec771 100644 --- a/template/golang-middleware/Dockerfile +++ b/template/golang-middleware/Dockerfile @@ -20,7 +20,15 @@ ARG GO111MODULE="on" ARG GOPROXY="" ARG GOFLAGS="" ARG CGO_ENABLED=0 +ARG DEBUG=0 + +ENV DEBUG=${DEBUG} ENV CGO_ENABLED=${CGO_ENABLED} +ENV GOOS=${TARGETOS} +ENV GOARCH=${TARGETARCH} +ENV GO=/go/src/handler/go.sh + +RUN chmod +x ${GO} # Run a gofmt and exclude all vendored code. RUN test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./function/vendor/*"))" || { echo "Run \"gofmt -s -w\" on your Golang code"; exit 1; } @@ -28,11 +36,10 @@ RUN test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*" -n WORKDIR /go/src/handler/function RUN mkdir -p /go/src/handler/function/static -RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go test ./... -cover +RUN ${GO} test ./... -cover WORKDIR /go/src/handler -RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ - go build --ldflags "-s -w" -a -installsuffix cgo -o handler . +RUN ${GO} build --ldflags "-s -w" -a -installsuffix cgo -o handler . FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine:3.15 as ship diff --git a/template/golang-middleware/go.sh b/template/golang-middleware/go.sh new file mode 100644 index 0000000..026f328 --- /dev/null +++ b/template/golang-middleware/go.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# go.sh is a wrapper for the Go command that will +# automatically set the required module related flags +# when a vendor folder is detected. +# +# Currently, in Go 1.18, Go Workspaces are incompatible +# with vendored modules. As a result, we must disable +# Go modules and use GOPATH mode. + +# We use this bash script to wrap Go commands because +# there is no clear way to set an env variable from the +# a script in a Dockerfile. +# It is possible to use `go env -w` but, but env varaibles +# have precedence and if it is set as an arg/env variable, +# then it will be ignored by the `go env -w`. + +# if the function/vendor folder exists +# then we set the env variables for +# GO111MODULE=off +if [ -d "/go/src/handler/function/vendor" ]; then + echo "Setting vendor mode env variables" + export GO111MODULE=off +fi + +# if DEBUG env is 1, print the go env +if [ "${DEBUG:-0}" = "1" ]; then + go env +fi + +go "$@"