(gist title)
This gist assumes the following directory structure:
- foobar-ws/
- bar/
- bar.go
- go.mod
- foo/
- foo.go
- go.mod
- foobar/
- deployments/foobar/
- Dockerfile
- go.mod
- go.sum
- main.go
- Makefile
- deployments/foobar/
- bar/
(gist title)
This gist assumes the following directory structure:
| FROM scratch as empty | |
| FROM golang:1.20-alpine AS builder | |
| ARG WSDISKPATHS | |
| ARG MOD1=./ | |
| ARG MOD2=./ | |
| ARG MOD3=./ | |
| ARG MOD4=./ | |
| ARG MOD5=./ | |
| ARG MOD6=./ | |
| ARG MOD7=./ | |
| ARG MOD8=./ | |
| ARG MOD9=./ | |
| WORKDIR /ws | |
| # Copy the additionally used modules into the soon-to-be workspace. | |
| COPY --from=bctx1 . ${MOD1} | |
| COPY --from=bctx2 . ${MOD2} | |
| COPY --from=bctx3 . ${MOD3} | |
| COPY --from=bctx4 . ${MOD4} | |
| COPY --from=bctx5 . ${MOD5} | |
| COPY --from=bctx6 . ${MOD6} | |
| COPY --from=bctx7 . ${MOD7} | |
| COPY --from=bctx8 . ${MOD8} | |
| COPY --from=bctx9 . ${MOD9} | |
| # Finally copy in the main module containing a main package to be build. | |
| WORKDIR /ws/foobar | |
| COPY go.mod go.sum ./ | |
| RUN go mod download | |
| COPY *.go ./ | |
| # Establish the Go workspace | |
| WORKDIR /ws | |
| RUN go work init ${WSDISKPATHS} | |
| RUN go build -v -o /foobar ./foobar |
| MAINUSE:=./foobar | |
| EMPTYCONTEXT:=.emptyctx | |
| NUMCONTEXTS:=9 | |
| SHELL:=/bin/bash | |
| build: | |
| @# find out if we are in workspace mode -- and it we are, then the list of | |
| @# modules actually used. | |
| @mkdir -p $(EMPTYCONTEXT); \ | |
| trap 'rm -rf -- "$(EMPTYCONTEXT)"' EXIT; \ | |
| contexts=(); \ | |
| workspace_details=$$(go work edit --json); \ | |
| if [[ $${workspace_details} ]]; then \ | |
| goworkdir=$$(dirname $$(go env GOWORK)); \ | |
| echo "found workspace" $${goworkdir}; \ | |
| diskpaths=$$(echo $${workspace_details} | jq --raw-output '.Use | .[]? | .DiskPath'); \ | |
| echo "modules used in workspace:" $${diskpaths}; \ | |
| while IFS= read -r module; do \ | |
| if [[ "$${module}" == "$(MAINUSE)" ]]; then \ | |
| echo " 🏠" $${module}; \ | |
| else \ | |
| relcontext=$$(realpath --relative-to="." $${goworkdir}/$${module}); \ | |
| contexts+=( $${relcontext} ); \ | |
| echo " 🧩" $${module} "» 📁" $${relcontext}; \ | |
| fi \ | |
| done <<< $${diskpaths}; \ | |
| else \ | |
| diskpaths="$(MAINUSE)"; \ | |
| fi; \ | |
| buildctxargs=(); \ | |
| buildargs=(); \ | |
| ctxno=1; \ | |
| for ctx in "$${contexts[@]}"; do \ | |
| buildctxargs+=( "--build-context=bctx$${ctxno}=$${ctx}" ); \ | |
| buildargs+=( "--build-arg=MOD$${ctxno}=./$$(basename ./$${ctx})/" ); \ | |
| ((ctxno=ctxno+1)); \ | |
| done; \ | |
| for ((;ctxno<=$(NUMCONTEXTS);ctxno++)); do \ | |
| buildctxargs+=( "--build-context=bctx$${ctxno}=$(EMPTYCONTEXT)" ); \ | |
| done; \ | |
| echo "args:" $${buildctxargs[*]} $${buildargs[*]}; \ | |
| echo "build inside:" $${CWD}; \ | |
| docker build \ | |
| -f ./deployments/foobar/Dockerfile \ | |
| $${buildargs[@]} \ | |
| $${buildctxargs[@]} \ | |
| --build-arg=WSDISKPATHS="$$(echo $${diskpaths})" \ | |
| . |