Skip to content
Merged
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
28 changes: 17 additions & 11 deletions cmd/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,17 @@ func Adapt(fn Command) func(cmd *cobra.Command, args []string) error {
}

type ProjectOptions struct {
ProjectName string
Profiles []string
ConfigPaths []string
WorkDir string
ProjectDir string
EnvFiles []string
Compatibility bool
Progress string
Offline bool
All bool
ProjectName string
Profiles []string
ConfigPaths []string
WorkDir string
ProjectDir string
EnvFiles []string
Compatibility bool
Progress string
Offline bool
All bool
insecureRegistries []string
}

// ProjectFunc does stuff within a types.Project
Expand Down Expand Up @@ -216,6 +217,8 @@ func (o *ProjectOptions) addProjectFlags(f *pflag.FlagSet) {
f.StringArrayVar(&o.Profiles, "profile", []string{}, "Specify a profile to enable")
f.StringVarP(&o.ProjectName, "project-name", "p", "", "Project name")
f.StringArrayVarP(&o.ConfigPaths, "file", "f", []string{}, "Compose configuration files")
f.StringArrayVar(&o.insecureRegistries, "insecure-registry", []string{}, "Use insecure registry to pull Compose OCI artifacts. Doesn't apply to images")
_ = f.MarkHidden("insecure-registry")
f.StringArrayVar(&o.EnvFiles, "env-file", defaultStringArrayVar(ComposeEnvFiles), "Specify an alternate environment file")
f.StringVar(&o.ProjectDir, "project-directory", "", "Specify an alternate working directory\n(default: the path of the, first specified, Compose file)")
f.StringVar(&o.WorkDir, "workdir", "", "DEPRECATED! USE --project-directory INSTEAD.\nSpecify an alternate working directory\n(default: the path of the, first specified, Compose file)")
Expand Down Expand Up @@ -337,6 +340,9 @@ func (o *ProjectOptions) ToProject(ctx context.Context, dockerCli command.Cli, b
Compatibility: o.Compatibility,
ProjectOptionsFns: po,
LoadListeners: []api.LoadListener{metricsListener},
OCI: api.OCIOptions{
InsecureRegistries: o.insecureRegistries,
},
}

project, err := backend.LoadProject(ctx, loadOpts)
Expand All @@ -352,7 +358,7 @@ func (o *ProjectOptions) remoteLoaders(dockerCli command.Cli) []loader.ResourceL
return nil
}
git := remote.NewGitRemoteLoader(dockerCli, o.Offline)
oci := remote.NewOCIRemoteLoader(dockerCli, o.Offline)
oci := remote.NewOCIRemoteLoader(dockerCli, o.Offline, api.OCIOptions{})
return []loader.ResourceLoader{git, oci}
}

Expand Down
5 changes: 5 additions & 0 deletions cmd/compose/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type publishOptions struct {
withEnvironment bool
assumeYes bool
app bool
insecureRegistry bool
}

func publishCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *BackendOptions) *cobra.Command {
Expand All @@ -56,6 +57,7 @@ func publishCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Ba
flags.BoolVar(&opts.withEnvironment, "with-env", false, "Include environment variables in the published OCI artifact")
flags.BoolVarP(&opts.assumeYes, "yes", "y", false, `Assume "yes" as answer to all prompts`)
flags.BoolVar(&opts.app, "app", false, "Published compose application (includes referenced images)")
flags.BoolVar(&opts.insecureRegistry, "insecure-registry", false, "Use insecure registry")
flags.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
// assumeYes was introduced by mistake as `--y`
if name == "y" {
Expand All @@ -64,6 +66,8 @@ func publishCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Ba
}
return pflag.NormalizedName(name)
})
// Should **only** be used for testing purpose, we don't want to promote use of insecure registries
_ = flags.MarkHidden("insecure-registry")

return cmd
}
Expand Down Expand Up @@ -92,5 +96,6 @@ func runPublish(ctx context.Context, dockerCli command.Cli, backendOptions *Back
Application: opts.app,
OCIVersion: api.OCIVersion(opts.ociVersion),
WithEnvironment: opts.withEnvironment,
InsecureRegistry: opts.insecureRegistry,
})
}
11 changes: 11 additions & 0 deletions docs/reference/docker_compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,17 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: insecure-registry
value_type: stringArray
default_value: '[]'
description: |
Use insecure registry to pull Compose OCI artifacts. Doesn't apply to images
deprecated: false
hidden: true
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: no-ansi
value_type: bool
default_value: "false"
Expand Down
10 changes: 10 additions & 0 deletions docs/reference/docker_compose_alpha_publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: insecure-registry
value_type: bool
default_value: "false"
description: Use insecure registry
deprecated: false
hidden: true
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: oci-version
value_type: string
description: |
Expand Down
10 changes: 10 additions & 0 deletions docs/reference/docker_compose_publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: insecure-registry
value_type: bool
default_value: "false"
description: Use insecure registry
deprecated: false
hidden: true
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: oci-version
value_type: string
description: |
Expand Down
11 changes: 5 additions & 6 deletions internal/oci/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"context"
"io"
"net/url"
"os"
"slices"
"strings"

"github.com/containerd/containerd/v2/core/remotes"
Expand All @@ -35,7 +35,7 @@ import (
)

// NewResolver setup an OCI Resolver based on docker/cli config to provide registry credentials
func NewResolver(config *configfile.ConfigFile) remotes.Resolver {
func NewResolver(config *configfile.ConfigFile, insecureRegistries ...string) remotes.Resolver {
return docker.NewResolver(docker.ResolverOptions{
Hosts: docker.ConfigureDefaultRegistries(
docker.WithAuthorizer(docker.NewDockerAuthorizer(
Expand All @@ -51,10 +51,9 @@ func NewResolver(config *configfile.ConfigFile) remotes.Resolver {
return auth.Username, auth.Password, nil
}),
)),
docker.WithPlainHTTP(func(s string) (bool, error) {
// Used for testing **only**
_, b := os.LookupEnv("__TEST__INSECURE__REGISTRY__")
return b, nil
docker.WithPlainHTTP(func(domain string) (bool, error) {
// Should be used for testing **only**
return slices.Contains(insecureRegistries, domain), nil
}),
),
})
Expand Down
11 changes: 9 additions & 2 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ type ProjectLoadOptions struct {
// All registered listeners will be notified of events.
// This is optional - pass nil or empty slice if not needed.
LoadListeners []LoadListener

OCI OCIOptions
}

type OCIOptions struct {
InsecureRegistries []string
}

// Compose is the API interface one can use to programmatically use docker/compose in a third-party software
Expand Down Expand Up @@ -484,8 +490,9 @@ type PublishOptions struct {
ResolveImageDigests bool
Application bool
WithEnvironment bool

OCIVersion OCIVersion
OCIVersion OCIVersion
// Use plain HTTP to access registry. Should only be used for testing purpose
InsecureRegistry bool
}

func (e Event) String() string {
Expand Down
10 changes: 5 additions & 5 deletions pkg/compose/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
// It loads and validates a Compose project from configuration files.
func (s *composeService) LoadProject(ctx context.Context, options api.ProjectLoadOptions) (*types.Project, error) {
// Setup remote loaders (Git, OCI)
remoteLoaders := s.createRemoteLoaders(options.Offline)
remoteLoaders := s.createRemoteLoaders(options)

projectOptions, err := s.buildProjectOptions(options, remoteLoaders)
if err != nil {
Expand Down Expand Up @@ -66,12 +66,12 @@ func (s *composeService) LoadProject(ctx context.Context, options api.ProjectLoa
}

// createRemoteLoaders creates Git and OCI remote loaders if not in offline mode
func (s *composeService) createRemoteLoaders(offline bool) []loader.ResourceLoader {
if offline {
func (s *composeService) createRemoteLoaders(options api.ProjectLoadOptions) []loader.ResourceLoader {
if options.Offline {
return nil
}
git := remote.NewGitRemoteLoader(s.dockerCli, offline)
oci := remote.NewOCIRemoteLoader(s.dockerCli, offline)
git := remote.NewGitRemoteLoader(s.dockerCli, options.Offline)
oci := remote.NewOCIRemoteLoader(s.dockerCli, options.Offline, options.OCI)
return []loader.ResourceLoader{git, oci}
}

Expand Down
7 changes: 6 additions & 1 deletion pkg/compose/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ func (s *composeService) publish(ctx context.Context, project *types.Project, re
return err
}

resolver := oci.NewResolver(s.configFile())
var insecureRegistries []string
if options.InsecureRegistry {
insecureRegistries = append(insecureRegistries, reference.Domain(named))
}

resolver := oci.NewResolver(s.configFile(), insecureRegistries...)

descriptor, err := oci.PushManifest(ctx, resolver, named, layers, options.OCIVersion)
if err != nil {
Expand Down
18 changes: 8 additions & 10 deletions pkg/e2e/publish_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,19 +186,17 @@ func TestPublish(t *testing.T) {
c.RunDockerCmd(t, "rm", "--force", registryName)
})

cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/publish/oci/compose.yaml", "-f", "./fixtures/publish/oci/compose-override.yaml",
"-p", projectName, "publish", "--with-env", "--yes", registry+"/test:test")
icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
cmd.Env = append(cmd.Env, "__TEST__INSECURE__REGISTRY__=true")
}).Assert(t, icmd.Expected{ExitCode: 0})
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/publish/oci/compose.yaml", "-f", "./fixtures/publish/oci/compose-override.yaml",
"-p", projectName, "publish", "--with-env", "--yes", "--insecure-registry", registry+"/test:test")
res.Assert(t, icmd.Expected{ExitCode: 0})

// docker exec -it compose-e2e-publish-registry tree /var/lib/registry/docker/registry/v2/

cmd = c.NewDockerComposeCmd(t, "--verbose", "--project-name=oci", "-f", fmt.Sprintf("oci://%s/test:test", registry), "config")
res := icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
cmd.Env = append(cmd.Env,
"XDG_CACHE_HOME="+t.TempDir(),
"__TEST__INSECURE__REGISTRY__=true")
cmd := c.NewDockerComposeCmd(t, "--verbose", "--project-name=oci",
"--insecure-registry", registry,
"-f", fmt.Sprintf("oci://%s/test:test", registry), "config")
res = icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
cmd.Env = append(cmd.Env, "XDG_CACHE_HOME="+t.TempDir())
})
res.Assert(t, icmd.Expected{ExitCode: 0})
assert.Equal(t, res.Stdout(), `name: oci
Expand Down
19 changes: 11 additions & 8 deletions pkg/remote/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/distribution/reference"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/internal/oci"
"github.com/docker/compose/v2/pkg/api"
spec "github.com/opencontainers/image-spec/specs-go/v1"
)

Expand Down Expand Up @@ -76,18 +77,20 @@ func ociRemoteLoaderEnabled() (bool, error) {
return true, nil
}

func NewOCIRemoteLoader(dockerCli command.Cli, offline bool) loader.ResourceLoader {
func NewOCIRemoteLoader(dockerCli command.Cli, offline bool, options api.OCIOptions) loader.ResourceLoader {
return ociRemoteLoader{
dockerCli: dockerCli,
offline: offline,
known: map[string]string{},
dockerCli: dockerCli,
offline: offline,
known: map[string]string{},
insecureRegistries: options.InsecureRegistries,
}
}

type ociRemoteLoader struct {
dockerCli command.Cli
offline bool
known map[string]string
dockerCli command.Cli
offline bool
known map[string]string
insecureRegistries []string
}

func (g ociRemoteLoader) Accept(path string) bool {
Expand Down Expand Up @@ -115,7 +118,7 @@ func (g ociRemoteLoader) Load(ctx context.Context, path string) (string, error)
return "", err
}

resolver := oci.NewResolver(g.dockerCli.ConfigFile())
resolver := oci.NewResolver(g.dockerCli.ConfigFile(), g.insecureRegistries...)

descriptor, content, err := oci.Get(ctx, resolver, ref)
if err != nil {
Expand Down