Reputation: 10613
I'm following two guides which appear to conflict
Go's Standard Go Project Layout recommends a /build
directory, the use of which is described as
Packaging and Continuous Integration.
Put your cloud (AMI), container (Docker), OS (deb, rpm, pkg) package configurations and scripts in the /build/package directory.
Following Google Cloud Endpoints Sample for Go using gRPC, I have a Dockerfile which copies application source code and installs any dependencies with go get
.
# /build/Dockerfile
FROM golang:alpine
# Alpine Linux package management
RUN apk update
RUN apk add git
COPY ../ /go/src/github.com/username/repository
# Downloads the packages named by the import paths, along with their
# dependencies. It then installs the named packages, like 'go install'.
# ****Don't do this in production! Use vendoring instead.****
RUN go get -v github.com/username/repository/foo-module
# Compiles and installs the packages named by the import paths.
RUN go install github.com/username/repository/foo-module
ENTRYPOINT ["/go/bin/foo-module"]
Following Standard Go Project Layout I place the aforementioned Dockerfile in /build
.
Since the Dockerfile is now in the /build
directory, I modified the COPY
command to copy the parent directory to find the application source code (COPY ../ /go/src/github.com/username/repository
).
The Docker build
command is not run directly, rather the build is started with Google Cloud Build
cloud-build-local --config=build/cloudbuild.yaml .
The cloudbuild.yaml
file is really simple and just kicks off the Docker build. The --file
flag points to build/Dockerfile
since the Cloud Build command is started from the project root and not from /build
)
# /build/cloudbuild.yaml
steps:
- id: Build
name: "gcr.io/cloud-builders/docker"
dir: ${_SOURCE}
args:
[
"build",
"--file build/Dockerfile",
".",
]
As expected, this fails
COPY failed: Forbidden path outside the build context: ../ ()
How to include files outside of Docker's build context? suggests using the --file
flag, however, this assumes the build is started from the root context. When using Google's Cloud Build, the build is started from cloudbuild.yaml
, which also located in /build
.
I could just place the Docker file in the root of my go module, but I would like to follow best practices where possible and keep cloudbuild.yaml
and Dockerfile
in /build
.
What is the correct way to achieve this while following the Standard Go Project Layout?
Upvotes: 2
Views: 1255
Reputation: 263726
That's a rather long question, so lets focus on the problem encountered:
COPY ../ /go/src/github.com/username/repository
which resulted in
COPY failed: Forbidden path outside the build context: ../ ()
You don't include files outside of the context, docker doesn't allow that. Instead you change your context to include the files you need to build your image, and make the paths in your COPY/ADD commands relative to that context. Make sure to reread that, these paths are not relative to the Dockerfile location.
So with a docker build
, if you have build/Dockerfile
, you would build from the parent directory with:
docker build -f build/Dockerfile .
That trailing dot is the path to the build context which gets sent to the docker engine to perform the build. It doesn't access files directly on the client, which is why you can't include files from outside of the context (plus you don't want malicious Dockerfiles extracting data from the build server).
Then inside the Dockerfile you'd define the paths relative to that context:
COPY . /go/src/github.com/username/repository
And if for some reason you cannot build from that parent directory because of the tooling, then make the context the parent folder with a relative path:
docker build -f Dockerfile ..
Upvotes: 2