GuidesLanguage guides
Go
Ferry compiles a Go app in a build image, then runs the binary in a small image.
Ferry finds go.mod. The build image has the Go version of go.mod.
1 / 4
A minimal example
go.mod
main.go
module example.com/hello
go 1.23package 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))
}ferry up hello-go --followWhat Ferry generates
| Step | What Ferry generates |
|---|---|
| Build image | golang:<version>-alpine, with the go version of go.mod (1.23 by default). go mod download runs in its own layer, which Docker keeps in its cache. |
| Build | CGO_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 image | alpine: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 binary to /out:
| Flag | Example |
|---|---|
--build-cmd | "go build -o /out/api ./cmd/api" |
--start-cmd | api (or the full path) |