Documentation
¶
Overview ¶
Package imagebuilder ports the v26.2.7 image builder module forward into the v26.5.1 AGPL build. It tracks Dockerfile build jobs against the local Docker daemon, persists a small library of starter templates, and (when configured) hooks each successful build into the existing imagesign service so the resulting image gets a Sigstore cosign signature on the way out.
Improvements vs v26.2.7:
- Build logs stream through Redis pub/sub instead of being buffered in memory inside the service. The handler subscribes per-build and bridges the stream into a WebSocket / SSE response. The output column on the row is filled only at the end with a tail-window of the log so the table view stays bounded.
- The build daemon is invoked through the docker.ClientAPI surface the rest of the codebase already depends on; no new socket mount is opened.
- Build context uploads are capped at 256 MiB by default (configurable). The cap is enforced at the service boundary so an oversized payload is rejected before it reaches the daemon.
- The starter template seeder writes a curated set of AGPL-safe Dockerfile snippets on first start. Each template is tagged IsBuiltin so the UI can hide the delete button.
- The optional imagesign hook signs the resulting image when cfg.Sign.Enabled is true; failures are logged but do not flip the build to failed (the image is already on disk by then).
- No biz gating, no edition checks, no call-home.
Index ¶
- Constants
- Variables
- type BuildJobRepository
- type Config
- type DockerBuilder
- type LogPublisher
- type RedisLogPublisher
- type Service
- func (s *Service) CreateTemplate(ctx context.Context, hostID uuid.UUID, ...) (*models.DockerfileTemplate, error)
- func (s *Service) DeleteTemplate(ctx context.Context, id uuid.UUID) error
- func (s *Service) GetBuild(ctx context.Context, id uuid.UUID) (*models.ImageBuildJob, error)
- func (s *Service) GetStats(ctx context.Context, hostID uuid.UUID) (*models.ImageBuildJobStats, error)
- func (s *Service) GetTemplate(ctx context.Context, id uuid.UUID) (*models.DockerfileTemplate, error)
- func (s *Service) ListBuilds(ctx context.Context, hostID uuid.UUID, limit, offset int) ([]models.ImageBuildJob, int, error)
- func (s *Service) ListTemplates(ctx context.Context, hostID uuid.UUID) ([]models.DockerfileTemplate, error)
- func (s *Service) LogChannel(buildID uuid.UUID) string
- func (s *Service) MaxContextBytes() int64
- func (s *Service) SeedBuiltinTemplates(ctx context.Context, hostID uuid.UUID) error
- func (s *Service) SetSignHook(hook SignHook)
- func (s *Service) StartBuild(ctx context.Context, opts StartBuildOptions) (*models.ImageBuildJob, error)
- type SignHook
- type StartBuildOptions
- type TemplateRepository
Constants ¶
const DefaultLogTailBytes = 64 * 1024
DefaultLogTailBytes is the size of the trailing slice of the build log persisted to image_build_jobs.output. The Redis pub/sub stream carries the full log during the run; the database column only retains the tail so a single bad build cannot bloat the row.
const DefaultMaxContextBytes int64 = 256 * 1024 * 1024
DefaultMaxContextBytes caps the build-context upload at 256 MiB. The figure matches the value documented in session-08-image-builder.md (Risks section). Operators raise the cap via Config.MaxContextBytes when their Dockerfiles ship genuinely large assets.
Variables ¶
var ( // ErrInvalidInput is returned when the caller supplies malformed // fields (empty Dockerfile, no tag, etc.). ErrInvalidInput = stderrors.New("imagebuilder: invalid input") // ErrContextTooLarge is returned when the build-context upload // exceeds Config.MaxContextBytes. ErrContextTooLarge = stderrors.New("imagebuilder: build context exceeds maximum size") // configured (typically because the socket is not mounted). ErrBuilderUnavailable = stderrors.New("imagebuilder: docker client not configured") // ErrBuiltinDelete is returned when a caller tries to delete a // built-in template. ErrBuiltinDelete = stderrors.New("imagebuilder: built-in templates cannot be deleted") )
Sentinel errors. API and web handlers map these to typed responses.
Functions ¶
This section is empty.
Types ¶
type BuildJobRepository ¶
type BuildJobRepository interface {
Create(ctx context.Context, job *models.ImageBuildJob) error
GetByID(ctx context.Context, id uuid.UUID) (*models.ImageBuildJob, error)
Update(ctx context.Context, job *models.ImageBuildJob) error
ListByHost(ctx context.Context, hostID uuid.UUID, limit, offset int) ([]models.ImageBuildJob, int, error)
GetStats(ctx context.Context, hostID uuid.UUID) (*models.ImageBuildJobStats, error)
}
BuildJobRepository defines persistence for image build jobs.
type Config ¶
type Config struct {
// MaxContextBytes caps the build-context tar upload. Defaults to
// DefaultMaxContextBytes (256 MiB).
MaxContextBytes int64
// LogTailBytes is the number of trailing bytes of the build log
// persisted to the row. Defaults to DefaultLogTailBytes (64 KiB).
LogTailBytes int
// LogChannelPrefix is the Redis pub/sub channel prefix. Builds are
// published to "<prefix>:<build_id>". Empty disables publishing.
LogChannelPrefix string
}
Config holds runtime knobs for the image builder.
type DockerBuilder ¶
type DockerBuilder interface {
ImageBuild(ctx context.Context, buildContext io.Reader, opts types.ImageBuildOptions) (types.ImageBuildResponse, error)
}
DockerBuilder is the narrow surface the service consumes from the docker package. Declaring it here lets the unit tests pass a fake.
type LogPublisher ¶
LogPublisher abstracts Redis pub/sub. Production wires in a thin adapter over *redis.PubSub; unit tests pass a memory channel so they can assert what gets published.
type RedisLogPublisher ¶
type RedisLogPublisher struct {
// contains filtered or unexported fields
}
RedisLogPublisher adapts *redis.PubSub onto the LogPublisher interface the service depends on. The build path stays free of pub-sub specifics so unit tests can substitute a memory channel.
func NewRedisLogPublisher ¶
func NewRedisLogPublisher(pub *redis.PubSub) *RedisLogPublisher
NewRedisLogPublisher returns a publisher backed by the given pub/sub client. Pass nil pub when Redis is not configured; the resulting publisher is a no-op so the build path still completes.
func (*RedisLogPublisher) PubSub ¶
func (p *RedisLogPublisher) PubSub() *redis.PubSub
PubSub exposes the underlying pub-sub so the API handler can subscribe on the same instance. Returns nil when Redis is not configured.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service implements the image builder business logic.
func NewService ¶
func NewService(builds BuildJobRepository, templates TemplateRepository, docker DockerBuilder, publisher LogPublisher, cfg Config, log *logger.Logger) *Service
NewService creates a new image builder service. docker, publisher and signHook are optional — the service degrades gracefully when any of them is nil. A nil logger is replaced with a no-op.
func (*Service) CreateTemplate ¶
func (s *Service) CreateTemplate(ctx context.Context, hostID uuid.UUID, name, description, category, dockerfile string, userID *uuid.UUID) (*models.DockerfileTemplate, error)
CreateTemplate creates a new user-defined Dockerfile template. Builtin templates are seeded via SeedBuiltinTemplates and never created via this entry point.
func (*Service) DeleteTemplate ¶
DeleteTemplate deletes a Dockerfile template, refusing to delete one that the binary seeded.
func (*Service) GetStats ¶
func (s *Service) GetStats(ctx context.Context, hostID uuid.UUID) (*models.ImageBuildJobStats, error)
GetStats returns aggregate build statistics for a host.
func (*Service) GetTemplate ¶
func (s *Service) GetTemplate(ctx context.Context, id uuid.UUID) (*models.DockerfileTemplate, error)
GetTemplate returns a template by ID.
func (*Service) ListBuilds ¶
func (s *Service) ListBuilds(ctx context.Context, hostID uuid.UUID, limit, offset int) ([]models.ImageBuildJob, int, error)
ListBuilds returns paginated build jobs for a host.
func (*Service) ListTemplates ¶
func (s *Service) ListTemplates(ctx context.Context, hostID uuid.UUID) ([]models.DockerfileTemplate, error)
ListTemplates returns all Dockerfile templates for a host.
func (*Service) LogChannel ¶
LogChannel returns the Redis pub/sub channel for a given build. The API handler uses the same helper so the publisher and subscriber stay in lock-step.
func (*Service) MaxContextBytes ¶
MaxContextBytes returns the configured upload cap. Exported so the API handler can produce a precise 413 error.
func (*Service) SeedBuiltinTemplates ¶
SeedBuiltinTemplates ensures the curated AGPL-compatible starter templates are present for the given host. Calling SeedBuiltinTemplates twice is a no-op — the seeder skips templates whose name + IsBuiltin pair already exists.
Each shipped template is a minimal Dockerfile snippet that pulls only from public, AGPL-compatible upstreams (alpine, debian-slim, the official language image families). Operators add proprietary content via user-defined templates.
func (*Service) SetSignHook ¶
SetSignHook installs (or replaces) the optional image signing hook. Pass nil to disable signing.
func (*Service) StartBuild ¶
func (s *Service) StartBuild(ctx context.Context, opts StartBuildOptions) (*models.ImageBuildJob, error)
StartBuild creates a new build job, queues the build, and returns the job row. The actual docker build runs synchronously inside StartBuild so callers that want to stream logs subscribe to LogChannel(job.ID) before the call returns. The handler handles the dispatch.
Improvements vs v26.2.7: explicit context-size enforcement, real Docker invocation (the v26.2.7 service stubbed it out with a fake "build completed" string), Redis log streaming with a bounded tail persisted, and the optional imagesign hook on success.
type SignHook ¶
SignHook is the optional integration with the imagesign service. When non-nil and the build succeeds, the service calls Sign with the resulting image reference. The returned signature reference (SHA256 of the cosign payload, or empty if signing was disabled) is recorded on the job row.
type StartBuildOptions ¶
type StartBuildOptions struct {
HostID uuid.UUID
Name string
Tags []string
Dockerfile string
ContextPath string
BuildContext []byte // raw tar.gz of the build context. May be nil for the inline-Dockerfile case.
BuildArgs map[string]string
Labels map[string]string
NoCache bool
Pull bool
Platform string
Target string
UserID *uuid.UUID
}
StartBuildOptions bundles the per-build parameters. Promoted to a struct so the API handler does not have to track an ever-lengthening positional argument list.
type TemplateRepository ¶
type TemplateRepository interface {
Create(ctx context.Context, t *models.DockerfileTemplate) error
GetByID(ctx context.Context, id uuid.UUID) (*models.DockerfileTemplate, error)
List(ctx context.Context, hostID uuid.UUID) ([]models.DockerfileTemplate, error)
Update(ctx context.Context, t *models.DockerfileTemplate) error
Delete(ctx context.Context, id uuid.UUID) error
}
TemplateRepository defines persistence for Dockerfile templates.