@@ -37,6 +37,7 @@ import (
37
37
"github.com/docker/compose/v2/pkg/prompt"
38
38
"github.com/docker/compose/v2/pkg/utils"
39
39
"github.com/docker/docker/api/types/blkiodev"
40
+ "github.com/docker/cli/cli/config/configfile"
40
41
"github.com/docker/docker/api/types/container"
41
42
"github.com/docker/docker/api/types/filters"
42
43
"github.com/docker/docker/api/types/mount"
@@ -50,6 +51,11 @@ import (
50
51
cdi "tags.cncf.io/container-device-interface/pkg/parser"
51
52
)
52
53
54
+ const (
55
+ secretsDir = "/run/secrets/"
56
+ dockerConfigPathInContainer = secretsDir + "/docker/config.json"
57
+ )
58
+
53
59
type createOptions struct {
54
60
AutoRemove bool
55
61
AttachStdin bool
@@ -241,6 +247,11 @@ func (s *composeService) getCreateConfigs(ctx context.Context,
241
247
proxyConfig := types .MappingWithEquals (s .configFile ().ParseProxyConfig (s .apiClient ().DaemonHost (), nil ))
242
248
env := proxyConfig .OverrideBy (service .Environment )
243
249
250
+ if hasAPISocket (service ) {
251
+ // Inject the Docker API socket credentials path in the environment.
252
+ env = append (env , "DOCKER_CONFIG=" + path .Dir (dockerConfigPathInContainer ))
253
+ }
254
+
244
255
var mainNwName string
245
256
var mainNw * types.ServiceNetworkConfig
246
257
if len (service .Networks ) > 0 {
@@ -371,6 +382,14 @@ func (s *composeService) getCreateConfigs(ctx context.Context,
371
382
return cfgs , nil
372
383
}
373
384
385
+ func hasAPISocket (service types.ServiceConfig ) bool {
386
+ for _ , v := range service .Volumes {
387
+ if v .Type == "api-socket" {
388
+ return true
389
+ }
390
+ }
391
+ }
392
+
374
393
// prepareContainerMACAddress handles the service-level mac_address field and the newer mac_address field added to service
375
394
// network config. This newer field is only compatible with the Engine API v1.44 (and onwards), and this API version
376
395
// also deprecates the container-wide mac_address field. Thus, this method will validate service config and mutate the
@@ -1001,7 +1020,7 @@ func (s *composeService) buildContainerMountOptions(ctx context.Context, p types
1001
1020
}
1002
1021
}
1003
1022
1004
- mounts , err := fillBindMounts (p , service , mounts )
1023
+ mounts , err := s . fillBindMounts (p , service , mounts )
1005
1024
if err != nil {
1006
1025
return nil , err
1007
1026
}
@@ -1013,9 +1032,9 @@ func (s *composeService) buildContainerMountOptions(ctx context.Context, p types
1013
1032
return values , nil
1014
1033
}
1015
1034
1016
- func fillBindMounts (p types.Project , s types.ServiceConfig , m map [string ]mount.Mount ) (map [string ]mount.Mount , error ) {
1035
+ func ( s * composeService ) fillBindMounts (p types.Project , service types.ServiceConfig , m map [string ]mount.Mount ) (map [string ]mount.Mount , error ) {
1017
1036
for _ , v := range s .Volumes {
1018
- bindMount , err := buildMount (p , v )
1037
+ bindMount , err := s . buildMount (p , v )
1019
1038
if err != nil {
1020
1039
return nil , err
1021
1040
}
@@ -1096,11 +1115,13 @@ func buildContainerConfigMounts(p types.Project, s types.ServiceConfig) ([]mount
1096
1115
return values , nil
1097
1116
}
1098
1117
1099
- func buildContainerSecretMounts (p types.Project , s types.ServiceConfig ) ([]mount.Mount , error ) {
1118
+ func ( s * composeService ) buildContainerSecretMounts (p types.Project , service types.ServiceConfig ) ([]mount.Mount , error ) {
1100
1119
mounts := map [string ]mount.Mount {}
1101
1120
1102
- secretsDir := "/run/secrets/"
1103
- for _ , secret := range s .Secrets {
1121
+ var secrets []types.ServiceSecretConfig
1122
+
1123
+
1124
+ for _ , secret := range secrets {
1104
1125
target := secret .Target
1105
1126
if secret .Target == "" {
1106
1127
target = secretsDir + secret .Source
@@ -1171,7 +1192,7 @@ func isWindowsAbs(p string) bool {
1171
1192
return false
1172
1193
}
1173
1194
1174
- func buildMount (project types.Project , volume types.ServiceVolumeConfig ) (mount.Mount , error ) {
1195
+ func ( s * composeService ) buildMount (project types.Project , volume types.ServiceVolumeConfig ) (mount.Mount , error ) {
1175
1196
source := volume .Source
1176
1197
// on windows, filepath.IsAbs(source) is false for unix style abs path like /var/run/docker.sock.
1177
1198
// do not replace these with filepath.Abs(source) that will include a default drive.
@@ -1192,14 +1213,33 @@ func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.
1192
1213
}
1193
1214
}
1194
1215
1216
+ vtype := mount .Type (volume .Type )
1217
+ if volume .Type == "api-socket" { // TODO: use VolumeTypeAPISocket when compose-go PR merged
1218
+ vtype = mount .TypeBind // rewrite to a bind mount
1219
+
1220
+ if volume .Source == "" {
1221
+ socketPath := s .dockerCli .DockerEndpoint ().Host
1222
+ if ! strings .HasPrefix (socket , "unix://" ) {
1223
+ return "" , fmt .Errorf ("flag --use-api-socket can only be used with unix sockets: docker endpoint %s incompatible" , socket )
1224
+ }
1225
+ socket = strings .TrimPrefix (socket , "unix://" ) // should we confirm absolute path?
1226
+ volume .Source = socketPath
1227
+ }
1228
+
1229
+ if volume .Target == "" {
1230
+ volume .Target = "/var/run/docker.sock"
1231
+ }
1232
+ }
1233
+
1195
1234
bind , vol , tmpfs , img := buildMountOptions (volume )
1196
1235
1197
1236
if bind != nil {
1198
- volume . Type = types . VolumeTypeBind
1237
+ vtype = mount . TypeBind
1199
1238
}
1200
1239
1240
+
1201
1241
return mount.Mount {
1202
- Type : mount . Type ( volume . Type ) ,
1242
+ Type : vtype ,
1203
1243
Source : source ,
1204
1244
Target : volume .Target ,
1205
1245
ReadOnly : volume .ReadOnly ,
@@ -1212,7 +1252,7 @@ func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.
1212
1252
}
1213
1253
1214
1254
func buildMountOptions (volume types.ServiceVolumeConfig ) (* mount.BindOptions , * mount.VolumeOptions , * mount.TmpfsOptions , * mount.ImageOptions ) {
1215
- if volume .Type != types .VolumeTypeBind && volume .Bind != nil {
1255
+ if ( volume .Type != types .VolumeTypeBind && volume .Type != "api-socket" && volume . Bind != nil { // TODO: use VolumeTypeAPISocket when compose-go PR merged
1216
1256
logrus .Warnf ("mount of type `%s` should not define `bind` option" , volume .Type )
1217
1257
}
1218
1258
if volume .Type != types .VolumeTypeVolume && volume .Volume != nil {
@@ -1228,6 +1268,8 @@ func buildMountOptions(volume types.ServiceVolumeConfig) (*mount.BindOptions, *m
1228
1268
switch volume .Type {
1229
1269
case "bind" :
1230
1270
return buildBindOption (volume .Bind ), nil , nil , nil
1271
+ case "api-socket" :
1272
+ return nil , nil , nil , nil // defer to defaults when binding the API socket
1231
1273
case "volume" :
1232
1274
return nil , buildVolumeOptions (volume .Volume ), nil , nil
1233
1275
case "tmpfs" :
@@ -1242,6 +1284,7 @@ func buildBindOption(bind *types.ServiceVolumeBind) *mount.BindOptions {
1242
1284
if bind == nil {
1243
1285
return nil
1244
1286
}
1287
+
1245
1288
opts := & mount.BindOptions {
1246
1289
Propagation : mount .Propagation (bind .Propagation ),
1247
1290
CreateMountpoint : bind .CreateHostPath ,
0 commit comments