-
Notifications
You must be signed in to change notification settings - Fork 1
/
docker_in_docker.go
96 lines (85 loc) · 2.44 KB
/
docker_in_docker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package exec
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/docker/docker/api/types/mount"
"github.com/spf13/afero"
)
// baseDirRewrite is used to rewrite the work directory when executing
// jobs (this is for Docker-in-Docker setups).
type baseDirRewrite struct {
src string // bind or volume path (on host)
dst string // baseDir (in this container)
}
func (r *baseDirRewrite) MountConfig(path string) mount.Mount {
if r != nil {
path = filepath.Join(r.src, strings.TrimPrefix(path, r.dst))
}
return mount.Mount{
Type: mount.TypeBind,
Source: path,
Target: containerWd,
}
}
var ErrMissingWorkdirVolume = errors.New("missing Docker volume or bind mount for work directory")
// swapped in tests.
var (
dockerFs = afero.NewOsFs()
hostname = os.Hostname
)
func (dc *DockerClient) configureDinD(baseDir string) error {
if _, err := dockerFs.Stat("/.dockerenv"); errors.Is(err, os.ErrNotExist) {
return nil // we're not running inside a container
}
if baseDir == "" {
return nil // no --job-directory given, assuming no DIND setup
}
id, err := determineContainerID()
if err != nil {
return fmt.Errorf("cannot determine texd container ID: %w", err)
}
container, err := dc.cli.ContainerInspect(context.Background(), id)
if err != nil {
return fmt.Errorf("cannot determine texd container: %w", err)
}
for _, mp := range container.Mounts {
if mp.Destination != baseDir {
continue
}
switch mp.Type {
case mount.TypeVolume:
if mp.Driver != "local" {
return fmt.Errorf("%s volume binds are currently not supported", mp.Driver)
}
fallthrough
case mount.TypeBind:
dc.dirRewrite = &baseDirRewrite{mp.Source, baseDir}
return nil
}
}
return ErrMissingWorkdirVolume
}
// determineContainerID tries to determine the ID of the Docker container
// texd runs in.
//
// By default, this assumes the hostname is the (truncated) container ID,
// which is usually the case, unless the hostname was reconfigured.
//
// To work around this issue, we'll read a special file (/container.id)
// which, if it exists shall contain the ID. This file can be created at
// container start time:
//
// docker run ... --cidfile=/container.id digineode:texd
//
// There's currently no way to configure the path of that file.
func determineContainerID() (string, error) {
if cid, err := afero.ReadFile(dockerFs, "/container.id"); err == nil {
return string(bytes.TrimSpace(cid)), nil
}
return hostname()
}