Skip to content

Commit 3b848c3

Browse files
committed
add (temporary) support for use_api_socket
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 455c018 commit 3b848c3

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

pkg/compose/apiSocket.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
Copyright 2020 Docker Compose CLI authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package compose
18+
19+
import (
20+
"bytes"
21+
"fmt"
22+
"strings"
23+
24+
"github.com/compose-spec/compose-go/v2/types"
25+
"github.com/docker/cli/cli/config/configfile"
26+
)
27+
28+
// --use-api-socket is not actually supported by the Docker Engine
29+
// but is a client-side hack (see https://github.com/docker/cli/blob/master/cli/command/container/create.go#L246)
30+
// we replicate here by transforming the project model
31+
32+
func (s *composeService) useAPISocket(project *types.Project) (*types.Project, error) {
33+
useAPISocket := false
34+
for _, service := range project.Services {
35+
if service.UseAPISocket {
36+
useAPISocket = true
37+
break
38+
}
39+
}
40+
if !useAPISocket {
41+
return project, nil
42+
}
43+
44+
socket := s.dockerCli.DockerEndpoint().Host
45+
if !strings.HasPrefix(socket, "unix://") {
46+
return nil, fmt.Errorf("use_api_socket can only be used with unix sockets: docker endpoint %s is incompatible", socket)
47+
}
48+
socket = strings.TrimPrefix(socket, "unix://") // should we confirm absolute path?
49+
50+
creds, err := s.dockerCli.ConfigFile().GetAllCredentials()
51+
if err != nil {
52+
return nil, fmt.Errorf("resolving credentials failed: %w", err)
53+
}
54+
newConfig := &configfile.ConfigFile{
55+
AuthConfigs: creds,
56+
}
57+
var configBuf bytes.Buffer
58+
if err := newConfig.SaveToWriter(&configBuf); err != nil {
59+
return nil, fmt.Errorf("saving creds for API socket: %w", err)
60+
}
61+
62+
project.Configs["#apisocket"] = types.ConfigObjConfig{
63+
Content: configBuf.String(),
64+
}
65+
66+
for name, service := range project.Services {
67+
service.Volumes = append(service.Volumes, types.ServiceVolumeConfig{
68+
Type: types.VolumeTypeBind,
69+
Source: socket,
70+
Target: "/var/run/docker.sock",
71+
})
72+
73+
_, envvarPresent := service.Environment["DOCKER_CONFIG"]
74+
75+
// If the DOCKER_CONFIG env var is already present, we assume the client knows
76+
// what they're doing and don't inject the creds.
77+
if !envvarPresent {
78+
// Set our special little location for the config file.
79+
path := "/run/secrets/docker"
80+
service.Environment["DOCKER_CONFIG"] = &path
81+
}
82+
83+
service.Configs = append(service.Configs, types.ServiceConfigObjConfig{
84+
Source: "#apisocket",
85+
Target: "/run/secrets/docker/config.json",
86+
})
87+
project.Services[name] = service
88+
}
89+
return project, nil
90+
}

pkg/compose/create.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ func (s *composeService) create(ctx context.Context, project *types.Project, opt
114114
"--remove-orphans flag to clean it up.", orphans.names())
115115
}
116116
}
117+
118+
// Temporary implementation of use_api_socket until we get actual support inside docker engine
119+
project, err = s.useAPISocket(project)
120+
if err != nil {
121+
return err
122+
}
123+
117124
return newConvergence(options.Services, observedState, networks, volumes, s).apply(ctx, project, options)
118125
}
119126

pkg/compose/run.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types.
5959
}
6060

6161
func (s *composeService) prepareRun(ctx context.Context, project *types.Project, opts api.RunOptions) (string, error) {
62+
// Temporary implementation of use_api_socket until we get actual support inside docker engine
63+
project, err := s.useAPISocket(project)
64+
if err != nil {
65+
return "", err
66+
}
67+
6268
err = progress.Run(ctx, func(ctx context.Context) error {
6369
return s.startDependencies(ctx, project, opts)
6470
}, s.stdinfo())
@@ -171,7 +177,7 @@ func applyRunOptions(project *types.Project, service *types.ServiceConfig, opts
171177

172178
func (s *composeService) startDependencies(ctx context.Context, project *types.Project, options api.RunOptions) error {
173179
var dependencies []string
174-
for name, _ := range project.Services {
180+
for name := range project.Services {
175181
if name != options.Service {
176182
dependencies = append(dependencies, name)
177183
}

0 commit comments

Comments
 (0)