@@ -168,9 +168,11 @@ type DockerLoggingOpts struct {
168
168
}
169
169
170
170
type DockerMount struct {
171
+ Type string `mapstructure:"type"`
171
172
Target string `mapstructure:"target"`
172
173
Source string `mapstructure:"source"`
173
174
ReadOnly bool `mapstructure:"readonly"`
175
+ BindOptions []* DockerBindOptions `mapstructure:"bind_options"`
174
176
VolumeOptions []* DockerVolumeOptions `mapstructure:"volume_options"`
175
177
}
176
178
@@ -180,6 +182,10 @@ type DockerDevice struct {
180
182
CgroupPermissions string `mapstructure:"cgroup_permissions"`
181
183
}
182
184
185
+ type DockerBindOptions struct {
186
+ Propagation string `mapstructure:"propagation"`
187
+ }
188
+
183
189
type DockerVolumeOptions struct {
184
190
NoCopy bool `mapstructure:"no_copy"`
185
191
Labels []map [string ]string `mapstructure:"labels"`
@@ -390,8 +396,29 @@ func NewDockerDriverConfig(task *structs.Task, env *env.TaskEnv) (*DockerDriverC
390
396
dconf .Mounts [i ].Target = env .ReplaceEnv (m .Target )
391
397
dconf .Mounts [i ].Source = env .ReplaceEnv (m .Source )
392
398
399
+ if m .Type == "" {
400
+ // default to `volume` type for backwards compatibility
401
+ m .Type = "volume"
402
+ }
403
+
404
+ if m .Type != "bind" && m .Type != "volume" {
405
+ return nil , fmt .Errorf (`Docker mount type must be "bind" or "volume"` )
406
+ }
407
+
408
+ if m .Type == "bind" && len (m .VolumeOptions ) > 0 {
409
+ return nil , fmt .Errorf (`volume_options invalid on "bind" mount type` )
410
+ }
411
+
412
+ if m .Type == "volume" && len (m .BindOptions ) > 0 {
413
+ return nil , fmt .Errorf (`bind_options invalid on "volume" mount type` )
414
+ }
415
+
416
+ if len (m .BindOptions ) > 1 {
417
+ return nil , fmt .Errorf ("only one bind_options stanza allowed" )
418
+ }
419
+
393
420
if len (m .VolumeOptions ) > 1 {
394
- return nil , fmt .Errorf ("Only one volume_options stanza allowed" )
421
+ return nil , fmt .Errorf ("only one volume_options stanza allowed" )
395
422
}
396
423
397
424
if len (m .VolumeOptions ) == 1 {
@@ -1342,26 +1369,51 @@ func (d *DockerDriver) createContainerConfig(ctx *ExecContext, task *structs.Tas
1342
1369
hm := docker.HostMount {
1343
1370
Target : m .Target ,
1344
1371
Source : m .Source ,
1345
- Type : "volume" , // Only type supported
1372
+ Type : m . Type ,
1346
1373
ReadOnly : m .ReadOnly ,
1347
1374
}
1348
- if len (m .VolumeOptions ) == 1 {
1349
- vo := m .VolumeOptions [0 ]
1350
- hm .VolumeOptions = & docker.VolumeOptions {
1351
- NoCopy : vo .NoCopy ,
1352
- }
1353
1375
1354
- if len (vo .DriverConfig ) == 1 {
1355
- dc := vo .DriverConfig [0 ]
1356
- hm .VolumeOptions .DriverConfig = docker.VolumeDriverConfig {
1357
- Name : dc .Name ,
1376
+ if hm .Type == "bind" {
1377
+ volumesEnabled := d .config .ReadBoolDefault (dockerVolumesConfigOption , dockerVolumesConfigDefault )
1378
+ hm .Source = filepath .Clean (hm .Source )
1379
+
1380
+ if filepath .IsAbs (hm .Source ) {
1381
+ d .logger .Println ("[DEBUG] driver.docker: Job contains an absolute path." )
1382
+ if ! volumesEnabled {
1383
+ // Disallow mounting arbitrary absolute paths
1384
+ return c , fmt .Errorf ("%s is false; cannot bind mount host paths: %+q" , dockerVolumesConfigOption , m .Source )
1358
1385
}
1359
- if len (dc .Options ) == 1 {
1360
- hm .VolumeOptions .DriverConfig .Options = dc .Options [0 ]
1386
+ } else {
1387
+ // Expand path relative to alloc dir
1388
+ hm .Source = filepath .Join (ctx .TaskDir .Dir , m .Source )
1389
+ d .logger .Printf ("[DEBUG] driver.docker: Job contains a relative path; expanding to %v" , hm .Source )
1390
+ }
1391
+
1392
+ if len (m .BindOptions ) == 1 {
1393
+ bo := m .BindOptions [0 ]
1394
+ hm .BindOptions = & docker.BindOptions {
1395
+ Propagation : bo .Propagation ,
1361
1396
}
1362
1397
}
1363
- if len (vo .Labels ) == 1 {
1364
- hm .VolumeOptions .Labels = vo .Labels [0 ]
1398
+ } else {
1399
+ if len (m .VolumeOptions ) == 1 {
1400
+ vo := m .VolumeOptions [0 ]
1401
+ hm .VolumeOptions = & docker.VolumeOptions {
1402
+ NoCopy : vo .NoCopy ,
1403
+ }
1404
+
1405
+ if len (vo .DriverConfig ) == 1 {
1406
+ dc := vo .DriverConfig [0 ]
1407
+ hm .VolumeOptions .DriverConfig = docker.VolumeDriverConfig {
1408
+ Name : dc .Name ,
1409
+ }
1410
+ if len (dc .Options ) == 1 {
1411
+ hm .VolumeOptions .DriverConfig .Options = dc .Options [0 ]
1412
+ }
1413
+ }
1414
+ if len (vo .Labels ) == 1 {
1415
+ hm .VolumeOptions .Labels = vo .Labels [0 ]
1416
+ }
1365
1417
}
1366
1418
}
1367
1419
hostConfig .Mounts = append (hostConfig .Mounts , hm )
0 commit comments