Learning Fiber - Deployment and Docker
Series/Learn Fiber/Episode 21
Episode 21 of 23

Learning Fiber - Deployment and Docker

This episode covers deploying a Fiber application: a multi-stage Dockerfile with a static CGO_ENABLED=0 build, a minimal runtime image, configuration management via environment variables, health checks, and deployment options to Vercel and a regular server.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Writing a Fiber application is only half the journey. Episode 21 covers the rest: deployment and Docker — building a small, secure image, running the app in a container, managing configuration, and production target choices.

Go applications have a unique advantage: they can be compiled into a static binary that runs without any runtime. With the right strategy, a Fiber image can be tens of megabytes and ready to run anywhere — from a VPS to a container orchestrator.

The Multi-Stage Dockerfile

Separate Build and Runtime

Multi-stage builds the binary in one image and copies the result into a slim runtime image:

Dockerfile multi-stage
FROM golang:1.23-alpine AS builder
 
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
 
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/main .
 
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
 
WORKDIR /app
COPY --from=builder /app/main /app/main
EXPOSE 3000
CMD ["/app/main"]

The builder stage downloads modules and compiles the binary with CGO_ENABLED=0 for a static build. The runtime stage contains only the binary plus CA certificates and timezone data — no Go toolchain in the production image.

Keeping the Image Slim

-ldflags="-s -w" strips symbols and the debug table, shrinking the binary drastically. For an even smaller image, swap the alpine base for scratch — make sure the binary is truly static and CA certificates are added:

Runtime minimal
FROM scratch
COPY --from=builder /app/main /main
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
EXPOSE 3000
ENTRYPOINT ["/main"]

scratch produces the smallest image, but you're responsible for everything needed — like CAs for outbound TLS connections. alpine is a balanced choice when you need a shell for debugging.

Configuration and Environment

Twelve-Factor Config

Don't hardcode configuration values. Read them from environment variables with sensible defaults:

Baca konfigurasi dari env
app := fiber.New(fiber.Config{
    Prefork: os.Getenv("PREFORK") == "true",
})
 
port := os.Getenv("PORT")
if port == "" {
    port = "3000"
}
app.Listen(":" + port)

This pattern follows the twelve-factor app: configuration comes from the environment, not from code. Docker passes env with -e or a .env file, and cloud platforms have their own mechanisms. Local defaults make development easy without setup.

Health Checks and Startup

The /healthz Endpoint

Orchestrators need to know when the app is ready to accept traffic:

Health check
app.Get("/healthz", func(c fiber.Ctx) error {
    return c.JSON(fiber.Map{"status": "ok"})
})
 
app.Get("/readyz", func(c fiber.Ctx) error {
    if !databaseConnected() {
        return fiber.NewError(fiber.StatusServiceUnavailable, "db belum siap")
    }
    return c.JSON(fiber.Map{"status": "ready"})
})

/healthz signals the process is alive; /readyz signals that dependencies (database, cache) are ready. The Dockerfile references both via HEALTHCHECK:

HEALTHCHECK
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
  CMD wget -q -O - http://localhost:3000/healthz || exit 1

Deploying to Vercel

Fiber as a Serverless Function

For serverless functions on Vercel, the Fiber adaptor can be called from a Go handler:

Vercel serverless
import "github.com/gofiber/adaptor/v2"
 
func handler(w http.ResponseWriter, r *http.Request) {
    adaptor.FiberApp(app)(w, r)
}
 
func main() {
    vercel.Serverless(handler)
}

adaptor.FiberApp(app) converts a Fiber application into an http.Handler, and vercel.Serverless(handler) wraps it for the serverless platform. The same approach works on Netlify and other platforms supporting Go. Note: calls that depend on a single instance (like in-memory sessions) need adjustment because serverless can spin up new instances.

Testing

Build dan jalankan image
docker build -t fiber-app .
docker run --rm -p 3000:3000 -e PORT=3000 fiber-app
curl http://localhost:3000/healthz

docker build produces the image according to the Dockerfile; docker run runs it with the port and env passed through. If the health check returns {"status":"ok"}, the app is ready for traffic. Check the image size with docker images — compare before and after -ldflags.

Closing

Key takeaways:

  • Multi-stage Dockerfile: build with CGO_ENABLED=0, minimal runtime (alpine or scratch).
  • -ldflags="-s -w" shrinks the binary size.
  • Read configuration from environment variables with local defaults.
  • Provide /healthz and /readyz for orchestrator health checks.
  • HEALTHCHECK in the Dockerfile keeps the container healthy.
  • Fiber can be deployed to Vercel/Netlify via github.com/gofiber/adaptor/v2.

In the next episode, episode 22 — the final one — we discuss the wrap-up with a complete CRUD project example that ties together routing, middleware, binding, error handling, and deployment.