8

I want to use variables across multi-stage docker builds. Similar to this question (unanswered at the time of writing.)

My specific use case is to build my Go project in a builder stage and save the directory. This is done in a variable and use the same variable in the next stage(s): The BUILD_DIR variable.

My Dockerfile is (The example in the commented lines doesn't work.):

FROM golang:1.11.5 as builder

WORKDIR /project-name
# What I want to do:
#ENV BUILD_DIR /project-name
#WORKDIR ${BUILD_DIR}


# Vendored dependencies of my project:
COPY ./vendor ./vendor
COPY ./*.go ./
# Source code:
COPY ./go.* ./

RUN GOFLAGS=-mod=vendor GOOS=linux go build .

FROM something-else:some-version

WORKDIR some-folder

# Executable from previous stage:
COPY --from=builder /project-name/executable-name .
# Config files:
COPY ./conf ./conf

# What I want to do to copy the executable:
#COPY --from=builder /${BUILD_DIR}/executable-name .

ENTRYPOINT ["./executable-name"]

1 Answer 1

11

To send variable we can use "ARG" solution, the "base" solution, and "file" solution.

ARG version_default=v1

FROM alpine:latest as base1
ARG version_default
ENV version=$version_default
RUN echo ${version}
RUN echo ${version_default}

FROM alpine:latest as base2
ARG version_default
RUN echo ${version_default}

another way is to use base container for multiple stages:

FROM alpine:latest as base
ARG version_default
ENV version=$version_default

FROM base
RUN echo ${version}

FROM base
RUN echo ${version}

You can find more details here: https://github.com/moby/moby/issues/37345

Also you could save the hash into a file in the first stage, and copy the file in the second stage and then read it and use it there.

From what I understand you want to copy the built program into the new docker for multistage build that the output size is smaller. Basically you do not need to send a variable you need to know were you built it in the first image and copy it from there

FROM golang:alpine as gobuilder
RUN apk update && apk add git

COPY sources/src/ $GOPATH/src/folder/
WORKDIR $GOPATH/src/folder/
#get dependencies
RUN go get -d -v
#build the binary
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -ldflags="-w -s" -o /go/bin/myGoProgram myGoSource.go

FROM alpine:latest
COPY --from=gobuilder /go/bin/myGoProgram /usr/local/bin/myGoProgram
ENTRYPOINT ["myGoProgram"] # or ENTRYPOINT ["/usr/local/bin/myGoProgram"]
Sign up to request clarification or add additional context in comments.

4 Comments

I know i can do that and that is what I've currently done. The thing is I want to use variables for this purpose. (The point is using variables somehow.)
I actually answered the question you said it was unanswered with the response to that stackoverflow.com/questions/52904847/…
Your answer over there seems doable/legit :) and I'll try it on Sunday. Thanks.
I will update this answer here too to mark it here as correct answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.