docs community blog github
Edit

How to Build Go Apps with Paketo Buildpacks

This documentation explains how to use the Paketo Go Buildpack to build applications for several common use-cases. For more in-depth description of the buildpack’s behavior and configuration see the Paketo Go Buildpack Reference documentation.

Build a Sample Go Application

You can quickly build a sample Go app into a runnable OCI image on your local machine with Paketo buildpacks.

Prerequisites

  • docker CLI
  • pack CLI
  1. Clone the Paketo samples and navigate to a Go sample app.

    git clone https://github.com/paketo-buildpacks/samples
    cd samples/go/mod
    
    copy to clipboard
    Copied!

  2. Use the pack CLI with the Paketo Go Buildpack to build the sample app.

    pack build my-app --buildpack paketo-buildpacks/go \
      --builder paketobuildpacks/builder:base
    
    copy to clipboard
    Copied!

  3. Run the app using instructions found in its README.

Note: Though the example above uses the Paketo Base Builder, this buildpack is also compatible with the Paketo Full Builder and Paketo Tiny Builder.

Override the Detected Go Version

The Paketo Go buildpack will attempt to automatically detect the correct version of Go to install based on the version in your app’s go.mod. It is possible to override this version by setting the BP_GO_VERSION environment variable at build time.

BP_GO_VERSION can be set to any valid semver version or version constraint (e.g. 1.14.1, 1.14.*). For the versions available in the buildpack, see the buildpack’s releases page. Specifying a version of Go is not required. In the case that is not specified, the buildpack will provide the default version, which can be seen in the buildpack.toml file.

With pack and a Command-Line Flag

When building with the pack CLI, set BP_GO_VERSION at build time with the --env flag.

pack build my-app --buildpack paketo-buildpacks/go \
  --env BP_GO_VERSION="1.14.1"
copy to clipboard
Copied!

With pack and a project.toml

When building with the pack CLI, create a project.toml file in your app directory that sets BP_GO_VERSION at build time.

# project.toml
[ build ]
  [[ build.env ]]
    name="BP_GO_VERSION"
    value="1.41.1"
copy to clipboard
Copied!

The pack CLI will automatically detect the project file at build time.

Configure the go build Command

The Paketo Go buildpack compiles Go source code with the go build command, with certain opinionated flags by default. (See reference documentation for information about the default flagset.) It is possible to override or add to these defaults by setting the BP_GO_BUILD_FLAGS and BP_GO_BUILD_LDFLAGS environment variables at build time.

Set -ldflags for go build

The Paketo Go buildpack has a dedicated environment variable for setting the value of -ldflags.

With pack and a Command-Line Flag

When building with the pack CLI, set BP_GO_BUILD_LDFLAGS at build time with the --env flag. For example, to add -ldflags="-X main.variable=some-value" to the build flagset, set the environment variable as follows:

pack build my-app --buildpack paketo-buildpacks/go \
  --env BP_GO_BUILD_LDFLAGS="-X main.variable=some-value"
copy to clipboard
Copied!

With pack and a project.toml

When building with the pack CLI, create a project.toml file in your app directory that sets BP_GO_BUILD_LDFLAGS at build time. For example, to add -ldflags="-X main.variable=some-value" to the build flagset, set the environment variable as follows:

# project.toml
[ build ]
  [[ build.env ]]
    name="BP_GO_BUILD_LDFLAGS"
    value="-X main.variable=some-value"
copy to clipboard
Copied!

The pack CLI will automatically detect the project file at build time.

Set Other Flags for go build

Setting BP_GO_BUILD_FLAGS will add to the Paketo Go buildpack’s default flagset. Any value that you set for a given flag will override the value set by the buildpack. See reference documentation for information about default configuration.

With pack and a Command-Line Flag

When building with the pack CLI, set BP_GO_BUILD_FLAGS at build time with the --env flag. For example, to add -buildmode=default -tags=paketo to the build flagset, set the environment variable as follows:

pack build my-app --buildpack paketo-buildpacks/go \
  --env BP_GO_BUILD_FLAGS="-buildmode=default -tags=paketo"
copy to clipboard
Copied!

With pack and a project.toml

When building with the pack CLI, create a project.toml file in your app directory that sets BP_GO_BUILD_FLAGS at build time. For example, to add -buildmode=default -tags=paketo to the build flagset, set the environment variable as follows:

# project.toml
[ build ]
  [[ build.env ]]
    name="BP_GO_BUILD_FLAGS"
    value="-buildmode=default -tags=paketo"
copy to clipboard
Copied!

The pack CLI will automatically detect the project file at build time.

Build Non-Default Package(s)

The Paketo Go Buildpack will compile the package in the app’s root directory by default. It is possible to build a non-default package (or packages) by setting the BP_GO_TARGETS environment variable at build time.

The following examples will build the second package in an app source directory with the structure:

app-directory
├── first
│   └── main.go
├── second
│   └── main.go
└── third
    └── main.go

With pack and a Command-Line Flag

When building with the pack CLI, set BP_GO_TARGETS at build time with the --env flag.

pack build my-app --buildpack paketo-buildpacks/go \
  --env BP_GO_TARGETS="./second"
copy to clipboard
Copied!

With pack and a project.toml

When building with the pack CLI, create a project.toml file in your app directory that sets BP_GO_TARGETS at build time.

# project.toml
[ build ]
  [[ build.env ]]
    name="BP_GO_TARGETS"
    value="./second"
copy to clipboard
Copied!

The pack CLI will automatically detect the project file at build time.

Build Multiple Packages In One App Image

The BP_GO_TARGETS environment variable can accept a colon-delimited list of target packages. Each binary will be set as a launch process of the same name in the app image. The following examples will build both the first and second packages in the same multi-package app directory as above.

With pack and a Command-Line Flag

When building with the pack CLI, set BP_GO_TARGETS at build time with the --env flag.

pack build my-app --buildpack paketo-buildpacks/go \
  --env BP_GO_TARGETS="./first:./second"
copy to clipboard
Copied!

With pack and a project.toml

When building with the pack CLI, create a project.toml file in your app directory that sets BP_GO_TARGETS at build time.

# project.toml
[ build ]
  [[ build.env ]]
    name="BP_GO_TARGETS"
    value="./first:./second"
copy to clipboard
Copied!

Import Private Go Modules

The Go buildpack can build apps that import private Go modules. Credentials to access private Go modules are provided via a service binding.

  1. Set up a directory for the service binding:

    mkdir /tmp/git-binding
    echo "git-credentials" > /tmp/git-binding/type
    touch /tmp/git-binding/credentials
    
    copy to clipboard
    Copied!

  2. Add git credentials for accessing the private modules to /tmp/git-binding/credentials, following the git credentials structure. For example, to access a private module github.com/private-org/private-module with a Github username and service account key, add the following to /tmp/git-binding/credentials:

url=https://github.com
username=<USERNAME>
password=<SERVICE ACCOUNT KEY>
copy to clipboard
Copied!
  1. Provide the service binding and $GOPRIVATE environment variable at build time:
    pack build myapp --buildpack paketo-buildpacks/go \
                     --env GOPRIVATE="github.com/private-org/private-module" \
                     --env SERVICE_BINDING_ROOT="/bindings" \
                     --volume /tmp/git-binding:/bindings/git-binding
    
    copy to clipboard
    Copied!

You’ll see that the build successfully pulls your app’s private dependencies. The secrets stored in the service binding will not be stored in the built app image.

Build an App that Imports Its Own Sub-Packages

If you are building a $GOPATH application that imports its own sub-packages, you will need to specify the import paths for those sub-packages. The Paketo Go Buildpack supports setting these import paths with the $BP_GO_BUILD_IMPORT_PATH environment variable at build time.

The following examples will configure the buildpack to build an app whose directory structure looks like:

app-directory
├── handlers
│   └── details.go
└── main.go

and whose main.go imports:

import (
	"github.com/app-developer/app-directory/handlers"
)

With pack and a Command-Line Flag

When building with the pack CLI, set $BP_GO_BUILD_IMPORT_PATH at build time with the --env flag.

pack build my-app --buildpack paketo-buildpacks/go \
  --env BP_GO_BUILD_IMPORT_PATH="github.com/app-developer/app-directory"
copy to clipboard
Copied!

With pack and a project.toml

When building with the pack CLI, create a project.toml file in your app directory that sets $BP_GO_BUILD_IMPORT_PATH at build time.

# project.toml
[ build ]
  [[ build.env ]]
    name="BP_GO_BUILD_IMPORT_PATH"
    value="github.com/app-developer/app-directory"
copy to clipboard
Copied!

Prevent Source Files From Being Deleted

By default, the Paketo Go Buildpack deletes the contents of your app source directory (except for built artifacts). To preserve certain static assets that are needed in the app image, you can set the BP_KEEP_FILES environment variable at build time.

The following examples configure the buildpack to prevent the assets/ and public/ directories from being removed in the app image.

With pack and a Command-Line Flag

When building with the pack CLI, set $BP_KEEP_FILES at build time with the --env flag.

pack build my-app --buildpack paketo-buildpacks/go \
  --env BP_KEEP_FILES="assets/*:public/*"
copy to clipboard
Copied!

With pack and a project.toml

When building with the pack CLI, create a project.toml file in your app directory that sets $BP_KEEP_FILES at build time.

# project.toml
[ build ]
  [[ build.env ]]
    name="BP_KEEP_FILES"
    value="assets/*:public/*"
copy to clipboard
Copied!

Enable Process Reloading

By default, your Go binary will be the only process running in your app container at runtime. You can enable restarting the binary process when files in the app’s working directory change, which may facilitate a shorter feedback loop for iterating on code changes. This feature may be used in conjunction with a dev orchestrator like Tilt.

Using BP_LIVE_RELOAD_ENABLED

To enable reloadable processes, set the $BP_LIVE_RELOAD_ENABLED environment variable at build time, either by passing a flag to the platform or by adding it to your project.toml. See the Cloud Native Buildpacks documentation to learn more about project.toml files.

With a pack build flag

pack build myapp --env BP_LIVE_RELOAD_ENABLED=true
copy to clipboard
Copied!

In a project.toml file

[[ build.env ]]
  name = 'BP_LIVE_RELOAD_ENABLED'
  value = 'true'
copy to clipboard
Copied!

In a Tiltfile with the pack resource

You can use the Paketo Go buildpack with Tilt. This example uses the pack extension for Tilt, and shows how to configure watched files.

pack('my-app',
  buildpacks=["paketo-buildpacks/go"],
  path='./src',
  env_vars=["BP_LIVE_RELOAD_ENABLED=true"],
  deps=['./src/build'],
  live_update=[
    sync('./src/build', '/workspace/build'),
    run('cp -rf /workspace/build/* /layers/paketo-buildpacks_go-build/targets/bin', trigger=['./src/build']),
  ])

# (Re)build locally when source code changes
local_resource('go-build',
  cmd='GOOS=linux GOARCH=amd64 go build -o ./build/ -buildmode pie .',
  deps=['./src'],
  ignore=['./src/build'],
  dir='./src'
)
copy to clipboard
Copied!
Notes
  • The Go Paketo buildpack works best with Tilt and hot reloading when all of your app’s source code is in a subdirectory (./src in the above example). Use the path parameter of the pack() resource to specify the location of the source code.
  • The Go Paketo buildpack will not recompile your source code inside the running app container. You must use a local_resource to rebuild your app when source code changes, and copy the built artifacts into the container with sync and run steps, as shown.
  • The cmd that is run as part of the go-build local resource above matches the command that the Go buildpack runs to build the app, including cross-compiling the binary for the app container’s operating system.

Install a Custom CA Certificate

Go buildpack users can provide their own CA certificates and have them included in the container root truststore at build-time and runtime by following the instructions outlined in the CA Certificates section of our configuration docs.

Override the Start Process Set by the Buildpack

Go buildpack users can set custom start processes for their app image by following the instructions in the Procfiles section of our configuration docs.

Set Environment Variables for App Launch Time

Go buildpack users can embed launch-time environment variables in their app image by following the documentation for the Environment Variables Buildpack.

Add Custom Labels to the App Image

Go buildpack users can add labels to their app image by following the instructions in the Applying Custom Labels section of our configuration docs.

Extract Go Module Information From A Build

The Go buildpack produces a software bill of materials (SBOM) for the dependencies installed in the app image during a build. It is possible to extract information about the Go modules used in the build using the build-time SBOM.

With pack and a Command-Line Flag

  1. When building with the pack CLI, use the flag --sbom-output-dir to extract SBOMs from the build:
pack build my-app --buildpack paketo-buildpacks/go \
                  --sbom-output-dir /tmp/sbom-output
copy to clipboard
Copied!
  1. To view the Go modules used in the build, inspect one of the SBOMs generated by the Go Mod Vendor buildpack. For instance, to view the SBOM as CycloneDX JSON:
cat /tmp/sbom-output/build/paketo-buildpacks_go-mod-vendor/sbom.cdx.json
copy to clipboard
Copied!
Edit

Last modified: August 3, 2022