FerryDocs

Go

Ferry compiles a Go app in a build image, then runs the binary in a small image.

Edit on GitHub
go buildYour sourcego.mod, main.goBuild imagegolang:1.23-alpineBinary/out/appRuntime imagealpine:3.20

Ferry finds go.mod. The build image has the Go version of go.mod.

1 / 4

A minimal example

go.mod
main.go
go.mod
module example.com/hello

go 1.23
main.go
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
)

func main() {
	port := os.Getenv("PORT")
	if port == "" {
		port = "3000"
	}
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "Hello from Go on Ferry")
	})
	log.Printf("listening on :%s", port)
	log.Fatal(http.ListenAndServe(":"+port, nil))
}
Terminal
ferry up hello-go --follow

What Ferry generates

StepWhat Ferry generates
Build imagegolang:<version>-alpine, with the go version of go.mod (1.23 by default). go mod download runs in its own , which Docker keeps in its cache.
BuildCGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/app <package>. The package is the root, if the root is package main. If not, it is the only main package below cmd/<name>.
Runtime imagealpine:3.20 with ca-certificates and tzdata. The binaries of /out go to /usr/local/bin. Ferry copies your source tree to /app (the work directory). Thus templates and static files are there.
Start/usr/local/bin/app

More than one command

Your project can have more than one command below cmd/, or a different layout. Then set a build command that writes the to /out:

FlagExample
--build-cmd"go build -o /out/api ./cmd/api"
--start-cmdapi (or the full path)

On this page