mirror of https://github.com/docker/compose.git
Do not bind mount configs and secrets when source is a file but copy it into the container
Signed-off-by: schaubl <schaubl@users.noreply.github.com>
This commit is contained in:
parent
d3d378b92a
commit
f54922f13f
|
@ -288,6 +288,12 @@ func (s *composeService) getCreateConfigs(ctx context.Context,
|
|||
return createConfigs{}, err
|
||||
}
|
||||
|
||||
// CONFIGS and SECRETS
|
||||
err = checkContainerConfigsSecrets(*p, service)
|
||||
if err != nil {
|
||||
return createConfigs{}, err
|
||||
}
|
||||
|
||||
// NETWORKING
|
||||
links, err := s.getLinks(ctx, p.Name, service, number)
|
||||
if err != nil {
|
||||
|
@ -915,128 +921,79 @@ 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{}
|
||||
func checkContainerConfigsSecrets(p types.Project, s types.ServiceConfig) error {
|
||||
err := checkContainerConfigs(p, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configsBaseDir := "/"
|
||||
err = checkContainerSecrets(p, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkContainerConfigs(p types.Project, s types.ServiceConfig) error {
|
||||
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)
|
||||
return fmt.Errorf("unsupported external config %s", definedConfig.Name)
|
||||
}
|
||||
|
||||
if definedConfig.Driver != "" {
|
||||
return nil, errors.New("Docker Compose does not support configs.*.driver")
|
||||
return errors.New("Docker Compose does not support configs.*.driver")
|
||||
}
|
||||
if definedConfig.TemplateDriver != "" {
|
||||
return nil, errors.New("Docker Compose does not support configs.*.template_driver")
|
||||
return errors.New("Docker Compose does not support configs.*.template_driver")
|
||||
}
|
||||
|
||||
if definedConfig.Environment != "" || definedConfig.Content != "" {
|
||||
if definedConfig.File != "" {
|
||||
_, err := os.Stat(definedConfig.File)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with source file of config %s: %s", definedConfig.Name, err.Error())
|
||||
}
|
||||
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
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) {
|
||||
var mounts = map[string]mount.Mount{}
|
||||
|
||||
secretsDir := "/run/secrets/"
|
||||
func checkContainerSecrets(p types.Project, s types.ServiceConfig) error {
|
||||
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)
|
||||
return fmt.Errorf("unsupported external secret %s", definedSecret.Name)
|
||||
}
|
||||
|
||||
if definedSecret.Driver != "" {
|
||||
return nil, errors.New("Docker Compose does not support secrets.*.driver")
|
||||
return errors.New("Docker Compose does not support secrets.*.driver")
|
||||
}
|
||||
if definedSecret.TemplateDriver != "" {
|
||||
return nil, errors.New("Docker Compose does not support secrets.*.template_driver")
|
||||
return errors.New("Docker Compose does not support secrets.*.template_driver")
|
||||
}
|
||||
|
||||
if definedSecret.Environment != "" {
|
||||
if definedSecret.File != "" {
|
||||
_, err := os.Stat(definedSecret.File)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with source file of secret %s: %s", definedSecret.Name, err.Error())
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
mnt, err := buildMount(p, types.ServiceVolumeConfig{
|
||||
Type: types.VolumeTypeBind,
|
||||
Source: definedSecret.File,
|
||||
Target: target,
|
||||
ReadOnly: true,
|
||||
})
|
||||
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
|
||||
return nil
|
||||
}
|
||||
|
||||
func isAbsTarget(p string) bool {
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
|
@ -31,7 +32,23 @@ import (
|
|||
func (s *composeService) injectSecrets(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error {
|
||||
for _, config := range service.Secrets {
|
||||
file := project.Secrets[config.Source]
|
||||
if file.Environment == "" {
|
||||
content := file.Content
|
||||
|
||||
if file.Environment != "" {
|
||||
env, ok := project.Environment[file.Environment]
|
||||
if !ok {
|
||||
return fmt.Errorf("environment variable %q required by file %q is not set", file.Environment, file.Name)
|
||||
}
|
||||
content = env
|
||||
} else if file.File != "" {
|
||||
data, err := os.ReadFile(file.File)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
content = string(data)
|
||||
}
|
||||
|
||||
if content == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -41,11 +58,7 @@ func (s *composeService) injectSecrets(ctx context.Context, project *types.Proje
|
|||
config.Target = "/run/secrets/" + config.Target
|
||||
}
|
||||
|
||||
env, ok := project.Environment[file.Environment]
|
||||
if !ok {
|
||||
return fmt.Errorf("environment variable %q required by file %q is not set", file.Environment, file.Name)
|
||||
}
|
||||
b, err := createTar(env, types.FileReferenceConfig(config))
|
||||
b, err := createTar(content, types.FileReferenceConfig(config))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -64,13 +77,21 @@ func (s *composeService) injectConfigs(ctx context.Context, project *types.Proje
|
|||
for _, config := range service.Configs {
|
||||
file := project.Configs[config.Source]
|
||||
content := file.Content
|
||||
|
||||
if file.Environment != "" {
|
||||
env, ok := project.Environment[file.Environment]
|
||||
if !ok {
|
||||
return fmt.Errorf("environment variable %q required by file %q is not set", file.Environment, file.Name)
|
||||
}
|
||||
content = env
|
||||
} else if file.File != "" {
|
||||
data, err := os.ReadFile(file.File)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
content = string(data)
|
||||
}
|
||||
|
||||
if content == "" {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ func TestLocalComposeVolume(t *testing.T) {
|
|||
res := c.RunDockerCmd(t, "inspect", "compose-e2e-volume-nginx2-1", "--format", "{{ json .Mounts }}")
|
||||
output := res.Stdout()
|
||||
assert.Assert(t, strings.Contains(output, `"Destination":"/usr/src/app/node_modules","Driver":"local","Mode":"z","RW":true,"Propagation":""`), output)
|
||||
assert.Assert(t, strings.Contains(output, `"Destination":"/myconfig","Mode":"","RW":false,"Propagation":"rprivate"`), output)
|
||||
assert.Assert(t, !strings.Contains(output, `"Destination":"/myconfig","Mode":"","RW":false,"Propagation":"rprivate"`), output)
|
||||
})
|
||||
|
||||
t.Run("check config content", func(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue