mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 07:41:27 +00:00
feat(services): builder selection, resource reservations, static builder (C3)
services.builder picks the build strategy per service: auto detects from repo contents (Dockerfile → railpack → nixpacks), explicit overrides force a builder, and static builds assets in a node stage then serves them from an nginx image (static_build_cmd/static_dir, port 80 default). - cpu_reserve/memory_reserve → Docker CPU shares + MemoryReservation; cpu/memory stay hard caps (NanoCPUs/Memory). Empty string clears. - app_settings.default_cpu/default_memory override service-create fallbacks; capacity_policy=block fails deploys whose requested memory exceeds node capacity (default warn logs via slog). - Resource specs are validated — "512mb" fails instead of silently dropping the limit. - Fixes: deployments.go hardcoded nixpacks (auto-detect was dead code); DockerfileBuilder passed the Dockerfile *path* as build-context content; BuildImage never drained the daemon stream so builds could abort and errors went unseen — stream is now consumed and errorDetail surfaced. - CLI: --builder/--cpu-reserve/--memory-reserve/--static-cmd/--static-dir on create+update; MCP args on services create/update; UI Build & Resources card; OpenAPI + llms.txt + CLI.md. Verified live: static build of a real repo → nginx image → deployed; reserves reach HostConfig (shares=256, MemoryReservation=128Mi); validation rejects bad specs; builder persists + clears. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
e995c98d05
commit
912f6f5142
22 files changed
+798
-59
No files matched your search
@@ -156,8 +156,10 @@ func (c *Client) CreateContainer(ctx context.Context, config ContainerConfig) (s
|
||||
PortBindings: config.PortBindings,
|
||||
Mounts: config.Mounts,
|
||||
Resources: container.Resources{
|
||||
Memory: config.Memory,
|
||||
NanoCPUs: config.NanoCPUs,
|
||||
Memory: config.Memory,
|
||||
MemoryReservation: config.MemoryReservation,
|
||||
NanoCPUs: config.NanoCPUs,
|
||||
CPUShares: config.CPUShares,
|
||||
},
|
||||
NetworkMode: container.NetworkMode(config.NetworkMode),
|
||||
}
|
||||
@@ -291,7 +293,7 @@ func (c *Client) PullImageWait(ctx context.Context, ref string, auth registry.Au
|
||||
|
||||
// BuildImage builds an image from a Dockerfile
|
||||
func (c *Client) BuildImage(ctx context.Context, buildContext io.Reader, options BuildOptions) (types.ImageBuildResponse, error) {
|
||||
return c.cli.ImageBuild(ctx, buildContext, types.ImageBuildOptions{
|
||||
resp, err := c.cli.ImageBuild(ctx, buildContext, types.ImageBuildOptions{
|
||||
Dockerfile: options.Dockerfile,
|
||||
Tags: options.Tags,
|
||||
BuildArgs: options.BuildArgs,
|
||||
@@ -299,6 +301,34 @@ func (c *Client) BuildImage(ctx context.Context, buildContext io.Reader, options
|
||||
Remove: options.Remove,
|
||||
NoCache: options.NoCache,
|
||||
})
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
// The daemon aborts the build if the response stream isn't consumed,
|
||||
// and reports failures only inside that stream.
|
||||
defer resp.Body.Close()
|
||||
var buildErr string
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
for {
|
||||
var line struct {
|
||||
ErrorDetail struct {
|
||||
Message string `json:"message"`
|
||||
} `json:"errorDetail"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
if err := dec.Decode(&line); err != nil {
|
||||
break
|
||||
}
|
||||
if line.ErrorDetail.Message != "" {
|
||||
buildErr = line.ErrorDetail.Message
|
||||
} else if line.Error != "" {
|
||||
buildErr = line.Error
|
||||
}
|
||||
}
|
||||
if buildErr != "" {
|
||||
return resp, fmt.Errorf("docker build failed: %s", buildErr)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// RemoveImage removes an image
|
||||
|
||||
Reference in new issue
Block a user