Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/cli/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func serveBuildOptions(cmd *cobra.Command) model.BuildOptions {
UseCogBaseImage: DetermineUseCogBaseImage(cmd),
ProgressOutput: buildProgressOutput,
ExcludeSource: true,
SkipLabels: true,
BaseImageOnly: true,
}
}

Expand Down
7 changes: 7 additions & 0 deletions pkg/config/image_name.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@ func DockerImageName(projectDir string) string {

return projectName
}

// BaseDockerImageName returns the Docker image name for base images
// used by dev-mode commands (cog serve, predict, run, train).
// These are tagged with "-base" to avoid overwriting images built by "cog build".
func BaseDockerImageName(projectDir string) string {
return DockerImageName(projectDir) + "-base"
}
7 changes: 7 additions & 0 deletions pkg/config/image_name_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ func TestDockerImageName(t *testing.T) {
require.Equal(t, "cog-my-great-model", DockerImageName("/home/joe/my great model"))
require.Equal(t, 30, len(DockerImageName("/home/joe/verylongverylongverylongverylongverylongverylongverylong")))
}

func TestBaseDockerImageName(t *testing.T) {
require.Equal(t, "cog-foo-base", BaseDockerImageName("/home/joe/foo"))
require.Equal(t, "cog-foo-base", BaseDockerImageName("/home/joe/Foo"))
require.Equal(t, "cog-foo-base", BaseDockerImageName("/home/joe/cog-foo"))
require.Equal(t, "cog-my-great-model-base", BaseDockerImageName("/home/joe/my great model"))
}
6 changes: 3 additions & 3 deletions pkg/image/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func Build(
precompile bool,
excludeSource bool,
skipSchemaValidation bool,
skipLabels bool,
baseImageOnly bool,
annotations map[string]string,
dockerCommand command.Command,
client registry.Client) (string, error) {
Expand Down Expand Up @@ -241,10 +241,10 @@ func Build(
}
}

// When skipLabels is true (cog run/predict/serve/train), skip the expensive
// When baseImageOnly is true (cog run/predict/serve/train), skip the expensive
// label-adding phase. This image is for local use only and won't be distributed,
// so we don't need metadata labels, pip freeze, schema bundling, or git info.
if skipLabels {
if baseImageOnly {
return tmpImageId, nil
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/model/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (f *DockerfileFactory) Build(ctx context.Context, src *Source, opts BuildOp
opts.Precompile,
opts.ExcludeSource,
opts.SkipSchemaValidation,
opts.SkipLabels,
opts.BaseImageOnly,
opts.Annotations,
f.docker,
f.registry,
Expand Down
20 changes: 14 additions & 6 deletions pkg/model/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,26 @@ type BuildOptions struct {
// a predictor or trainer defined in cog.yaml.
SkipSchemaValidation bool

// SkipLabels skips adding Cog metadata labels to the built image.
// Used by `cog run`, `cog predict`, `cog serve`, and `cog train` where
// the image is for local use only and not being distributed.
SkipLabels bool
// BaseImageOnly builds only the base image without Cog metadata labels.
// Used by dev-mode commands (`cog run`, `cog predict`, `cog serve`,
// `cog train`) where the image is ephemeral and for local use only.
// When true, the default image name gets a "-base" suffix to avoid
// overwriting images built by `cog build`.
BaseImageOnly bool
}

// WithDefaults returns a copy of BuildOptions with defaults applied from Source.
// This fills in sensible defaults for any unset fields.
func (o BuildOptions) WithDefaults(src *Source) BuildOptions {
// Default image name from project directory
// Default image name from project directory.
// Dev-mode builds (BaseImageOnly: serve, predict, run, train) use a
// "-base" suffix so they don't overwrite images built by "cog build".
if o.ImageName == "" {
o.ImageName = config.DockerImageName(src.ProjectDir)
if o.BaseImageOnly {
o.ImageName = config.BaseDockerImageName(src.ProjectDir)
} else {
o.ImageName = config.DockerImageName(src.ProjectDir)
}
}

// Default progress output
Expand Down
26 changes: 26 additions & 0 deletions pkg/model/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,32 @@ func TestBuildOptions_AllFieldsPreserved(t *testing.T) {
require.Equal(t, "/path/to/weights.lock", result.WeightsLockPath)
}

func TestBuildOptions_WithDefaults_DevModeUsesBaseSuffix(t *testing.T) {
src := &Source{
Config: &config.Config{Build: &config.Build{}},
ProjectDir: "/path/to/my-project",
}

// Dev-mode builds (BaseImageOnly=true) should get "-base" suffix
opts := BuildOptions{BaseImageOnly: true}
opts = opts.WithDefaults(src)

require.Equal(t, "cog-my-project-base", opts.ImageName)
}

func TestBuildOptions_WithDefaults_DevModePreservesExplicitImageName(t *testing.T) {
src := &Source{
Config: &config.Config{Build: &config.Build{}},
ProjectDir: "/path/to/my-project",
}

// Explicit image name should be preserved even in dev mode
opts := BuildOptions{ImageName: "my-custom-image", BaseImageOnly: true}
opts = opts.WithDefaults(src)

require.Equal(t, "my-custom-image", opts.ImageName)
}

func TestBuildOptions_WeightsLockPath(t *testing.T) {
opts := BuildOptions{
WeightsLockPath: "/custom/weights.lock",
Expand Down
Loading