Skip to content

Commit

Permalink
Add support for configs.file's and secrets.file's on remote docker hosts
Browse files Browse the repository at this point in the history
Copy configs.file's and secrets.file's instead of bind-mounting them to
make it possible to use file configs when working with remote docker
hosts (like setting DOCKER_HOST to a ssh address or setting docker
context)

Includes support for config.files and secrets.files as directories.

Note that file.Content as source of secrets is denied elsewhere with the
error "validating docker-compose.yml: secrets.content_secret Additional
property content is not allowed"

implements: docker#11867
  • Loading branch information
andoks committed Sep 25, 2024
1 parent 8b9fe89 commit 0e11384
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 176 deletions.
128 changes: 0 additions & 128 deletions pkg/compose/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -897,137 +897,9 @@ func fillBindMounts(p types.Project, s types.ServiceConfig, m map[string]mount.M
m[bindMount.Target] = bindMount
}

secrets, err := buildContainerSecretMounts(p, s)
if err != nil {
return nil, err
}
for _, s := range secrets {
if _, found := m[s.Target]; found {
continue
}
m[s.Target] = s
}

configs, err := buildContainerConfigMounts(p, s)
if err != nil {
return nil, err
}
for _, c := range configs {
if _, found := m[c.Target]; found {
continue
}
m[c.Target] = c
}
return m, nil
}

func buildContainerConfigMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) {
var mounts = map[string]mount.Mount{}

configsBaseDir := "/"
for _, config := range s.Configs {
target := config.Target
if config.Target == "" {
target = configsBaseDir + config.Source
} else if !isAbsTarget(config.Target) {
target = configsBaseDir + config.Target
}

if config.UID != "" || config.GID != "" || config.Mode != nil {
logrus.Warn("config `uid`, `gid` and `mode` are not supported, they will be ignored")
}

definedConfig := p.Configs[config.Source]
if definedConfig.External {
return nil, fmt.Errorf("unsupported external config %s", definedConfig.Name)
}

if definedConfig.Driver != "" {
return nil, errors.New("Docker Compose does not support configs.*.driver")
}
if definedConfig.TemplateDriver != "" {
return nil, errors.New("Docker Compose does not support configs.*.template_driver")
}

if definedConfig.Environment != "" || definedConfig.Content != "" {
continue
}

bindMount, err := buildMount(p, types.ServiceVolumeConfig{
Type: types.VolumeTypeBind,
Source: definedConfig.File,
Target: target,
ReadOnly: true,
})
if err != nil {
return nil, err
}
mounts[target] = bindMount
}
values := make([]mount.Mount, 0, len(mounts))
for _, v := range mounts {
values = append(values, v)
}
return values, nil
}

func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) {
var mounts = map[string]mount.Mount{}

secretsDir := "/run/secrets/"
for _, secret := range s.Secrets {
target := secret.Target
if secret.Target == "" {
target = secretsDir + secret.Source
} else if !isAbsTarget(secret.Target) {
target = secretsDir + secret.Target
}

if secret.UID != "" || secret.GID != "" || secret.Mode != nil {
logrus.Warn("secrets `uid`, `gid` and `mode` are not supported, they will be ignored")
}

definedSecret := p.Secrets[secret.Source]
if definedSecret.External {
return nil, fmt.Errorf("unsupported external secret %s", definedSecret.Name)
}

if definedSecret.Driver != "" {
return nil, errors.New("Docker Compose does not support secrets.*.driver")
}
if definedSecret.TemplateDriver != "" {
return nil, errors.New("Docker Compose does not support secrets.*.template_driver")
}

if definedSecret.Environment != "" {
continue
}

if _, err := os.Stat(definedSecret.File); os.IsNotExist(err) {
logrus.Warnf("secret file %s does not exist", definedSecret.Name)
}

mnt, err := buildMount(p, types.ServiceVolumeConfig{
Type: types.VolumeTypeBind,
Source: definedSecret.File,
Target: target,
ReadOnly: true,
Bind: &types.ServiceVolumeBind{
CreateHostPath: false,
},
})
if err != nil {
return nil, err
}
mounts[target] = mnt
}
values := make([]mount.Mount, 0, len(mounts))
for _, v := range mounts {
values = append(values, v)
}
return values, nil
}

func isAbsTarget(p string) bool {
return isUnixAbs(p) || isWindowsAbs(p)
}
Expand Down
Loading

0 comments on commit 0e11384

Please sign in to comment.