Skip to content

Commit

Permalink
Added MAIN_PATH and DOCKER_BUILD_CONTEXT customizable parameters
Browse files Browse the repository at this point in the history
Updated README for new special options
  • Loading branch information
matt-deboer committed May 3, 2016
1 parent 63a09d9 commit 42ee700
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 19 deletions.
33 changes: 29 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,26 @@ The *golang-builder* assumes that your "main" package (the package containing yo

In the example above, the `hello.go` source file defines the "main" package for this project and lives at the root of the project directory structure. This project defines other packages ("api" and "greeting") but those are subdirectories off the root.

This convention is in place so that the *golang-builder* knows where to find the "main" package in the project structure. In a future release, we may make this a configurable option in order to support projects with different directory structures.
This convention is in place so that the *golang-builder* knows where to find the "main" package in the project structure.

If your "main" package does not reside at the root of your project structure, you can accomodate this by specifying the `MAIN_PATH` environment variable which references the relative path to your main package.

For example, suppose your structure is like the following (slightly modified from above so that your "main" package resides in the "cli" subfolder):

.
├─Dockerfile
├─api
| ├─api.go
| └─api_test.go
├─greeting
| ├─greeting.go
| └─greeting_test.go
└─cli
├─hello.go
└─hello_test.go

You would then add `MAIN_PATH=cli` to your environment specification.


### Canonical Import Path
In addition to knowing where to find the "main" package, the *golang-builder* also needs to know the fully-qualified package name for your application. For the "hello" application shown above, the fully-qualified package name for the executable is "github.com/CenturyLink/hello" but there is no way to determine that just by looking at the project directory structure (during the development, the project directory would likely be mounted at `$GOPATH/src/github.com/CenturyLink/hello` so that the Go tools can determine the package name).
Expand All @@ -63,9 +82,13 @@ The problem with doing a `go get` with each build is that *golang-builder* may e
If you are using Godep to manage your dependencies *golang-builder* will reference the packages in your `Godeps/_workspace` directory instead of downloading them via `go get`.

### Dockerfile
If you would like to have *golang-builder* package your compiled Go application into a Docker image automatically then the final requirement is that your Dockerfile be placed at the root of your project directory structure. After compiling your Go application, *golang-builder* will execute a `docker build` with your Dockerfile.
If you would like to have *golang-builder* package your compiled Go application into a Docker image automatically then the final requirement is that your Dockerfile be placed at the root of your project directory structure.

If your Dockerfile resides somewhere else, you can acommodate this by specifying the `DOCKER_BUILD_CONTEXT` env var. This will be used to override the default value of `"."`.

After compiling your Go application, *golang-builder* will execute a `docker build` with your Dockerfile.

The compiled binary will be placed in the root of your project directory so your Dockerfile can be written with the assumption that the application binary is in the same directory as the Dockerfile itself:
The compiled binary will be placed (by default) in the root of your project directory so your Dockerfile can be written with the assumption that the application binary is in the same directory as the Dockerfile itself:

FROM scratch
EXPOSE 3000
Expand All @@ -74,7 +97,7 @@ The compiled binary will be placed in the root of your project directory so your

In this case, the *hello* binary will be copied right to the root of the image and used as the entrypoint. Since we're using the empty *scratch* image as our base, there is no need to set-up any sort of directory structure inside the image.

If *golang-builder* does **NOT** see a Dockerfile in your project directory it will simply stop after compiling your application.
If *golang-builder* does **NOT** see a Dockerfile in your project directory (or `DOCKER_BUILD_CONTEXT` directory) it will simply stop after compiling your application.

## Usage

Expand Down Expand Up @@ -112,6 +135,8 @@ If you just want to compile your application without packaging it in a Docker im
* LDFLAGS - flags to pass to the linker (defaults to '-s')
* COMPRESS_BINARY - if set to true, will use UPX to compress the final binary (defaults to false)
* OUTPUT - if set, will use the `-o` option with `go build` to output the final binary to the value of this env var
* MAIN_PATH - if set, this (relative) path will be used as the location of the "main" package
* DOCKER_BUILD_CONTEXT - if set, this (relative) path will be used as the build context location (where the Dockerfile should reside)

The above are environment variables to be passed to the docker run command:

Expand Down
30 changes: 23 additions & 7 deletions builder/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,23 @@ name=${pkgName##*/}
# to the named output file
#
output=""
outputFile=""
if [[ ! -z "${OUTPUT}" ]];
then
output="-o ${OUTPUT}"
outputFile="${OUTPUT}"
#
# If OUTPUT env var ends with "/", assume an output directory
# was specified, and we should append the executable name.
#
if [[ "$outputFile" == *"/" ]];
then
outputFile="${outputFile}${name}"
fi
output="-o ${outputFile}"
fi

# Compile statically linked version of package
echo "Building $pkgName"
echo "Building $pkgName => ${outputFile}"
(
CGO_ENABLED=${CGO_ENABLED:-0} \
go build \
Expand All @@ -30,19 +40,25 @@ echo "Building $pkgName"

if [[ "$COMPRESS_BINARY" == "true" ]];
then
if [[ ! -z "${OUTPUT}" ]];
if [[ ! -z "${outputFile}" ]];
then
goupx ${OUTPUT}
goupx "${outputFile}"
else
goupx $name
fi
fi

if [[ -e "/var/run/docker.sock" && -e "./Dockerfile" ]];
dockerContextPath="."
if [ ! -z "${DOCKER_BUILD_CONTEXT}" ];
then
dockerContextPath="${DOCKER_BUILD_CONTEXT}"
fi

if [[ -e "/var/run/docker.sock" && -e "${dockerContextPath}/Dockerfile" ]];
then
# Default TAG_NAME to package name if not set explicitly
tagName=${tagName:-"$name":latest}

# Build the image from the Dockerfile in the package directory
docker build -t $tagName .
fi
docker build -t $tagName "$dockerContextPath"
fi
25 changes: 17 additions & 8 deletions builder/build_environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,29 @@ then
exit 990
fi

# Grab Go package name
pkgName="$(go list -e -f '{{.ImportComment}}' 2>/dev/null || true)"
# Construct Go package path
if [ ! -z "${MAIN_PATH}" ];
then
pkgName="$(go list -e -f '{{.ImportComment}}' ./... 2>/dev/null | grep ${MAIN_PATH} || true)"
path=$(cd /src && ls -d -1 ${MAIN_PATH})
pkgBase=${pkgName%/$path}
else
pkgName="$(go list -e -f '{{.ImportComment}}' 2>/dev/null || true)"
pkgBase="$pkgName"
fi

echo "using pkgName: $pkgName, pkgBase: $pkgBase"

if [ -z "$pkgName" ];
then
echo "Error: Must add canonical import path to root package"
echo "Error: Must add canonical import path to root package, or specify the MAIN_PATH env var"
exit 992
fi

# Grab just first path listed in GOPATH
goPath="${GOPATH%%:*}"

# Construct Go package path
pkgPath="$goPath/src/$pkgName"
pkgPath="$goPath/src/$pkgBase"

# Set-up src directory tree in GOPATH
mkdir -p "$(dirname "$pkgPath")"
Expand All @@ -31,13 +40,13 @@ ln -sf /src "$pkgPath"

if [ -e "$pkgPath/vendor" ];
then
# Enable vendor experiment
export GO15VENDOREXPERIMENT=1
# Enable vendor experiment
export GO15VENDOREXPERIMENT=1
elif [ -e "$pkgPath/Godeps/_workspace" ];
then
# Add local godeps dir to GOPATH
GOPATH=$pkgPath/Godeps/_workspace:$GOPATH
else
# Get all package dependencies
go get -t -d -v ./...
fi
fi

0 comments on commit 42ee700

Please sign in to comment.