This probably fits in very well with the "nuts" part of the golang-nuts 
group, so here we go: in some of my projects I typically build and deploy 
locally in a container to see that the service work correctly at least 
locally. Now, these projects tend to depend on several of my own separate 
Go modules. Unit testing locally is easy, but in several cases my services 
depend on more stuff that is unwieldy to build so I prefer having this all 
done in a staged container image build.

Can I get my workspace "somehow" into my multi-stage build...?

Well, looks like it is doable, albeit with some limitations due to the 
Dockerfile syntax. So, here we are and I would like to ask kindly for kind 
feedback ... also available as a gist 
<https://gist.github.com/thediveo/0d8b6ae7f88918c2571890e508468b23>.

The illustrative example assumes a filesystem setup as follows:

   - foobar-ws/
      - bar/
         - bar.go
         - go.mod
      - foo/
         - foo.go
         - go.mod
      - foobar/
         - deployments/foobar/
            - *Dockerfile*
         - go.mod
         - go.sum
         - main.go
         - *Makefile*
      
The Makefile:
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})" \ .

The Dockerfile:
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

A "make" inside foobar-ws/foobar will take over the current local workspace 
"use" configuration and then build the "main" application.


-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/e6c8064b-2373-44e8-b439-1f4c71f150f3n%40googlegroups.com.

Reply via email to