github.com/rish1988/moby@v25.0.2+incompatible/builder/builder-next/executor_linux.go (about) 1 package buildkit 2 3 import ( 4 "context" 5 "net" 6 "os" 7 "path/filepath" 8 "strconv" 9 "sync" 10 11 "github.com/containerd/log" 12 "github.com/docker/docker/daemon/config" 13 "github.com/docker/docker/libnetwork" 14 "github.com/docker/docker/pkg/idtools" 15 "github.com/docker/docker/pkg/stringid" 16 "github.com/moby/buildkit/executor" 17 "github.com/moby/buildkit/executor/oci" 18 "github.com/moby/buildkit/executor/resources" 19 "github.com/moby/buildkit/executor/runcexecutor" 20 "github.com/moby/buildkit/identity" 21 "github.com/moby/buildkit/solver/pb" 22 "github.com/moby/buildkit/util/network" 23 specs "github.com/opencontainers/runtime-spec/specs-go" 24 ) 25 26 const networkName = "bridge" 27 28 func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfig *oci.DNSConfig, rootless bool, idmap idtools.IdentityMapping, apparmorProfile string) (executor.Executor, error) { 29 netRoot := filepath.Join(root, "net") 30 networkProviders := map[pb.NetMode]network.Provider{ 31 pb.NetMode_UNSET: &bridgeProvider{Controller: net, Root: netRoot}, 32 pb.NetMode_HOST: network.NewHostProvider(), 33 pb.NetMode_NONE: network.NewNoneProvider(), 34 } 35 36 // make sure net state directory is cleared from previous state 37 fis, err := os.ReadDir(netRoot) 38 if err == nil { 39 for _, fi := range fis { 40 fp := filepath.Join(netRoot, fi.Name()) 41 if err := os.RemoveAll(fp); err != nil { 42 log.G(context.TODO()).WithError(err).Errorf("failed to delete old network state: %v", fp) 43 } 44 } 45 } 46 47 // Returning a non-nil but empty *IdentityMapping breaks BuildKit: 48 // https://github.com/moby/moby/pull/39444 49 pidmap := &idmap 50 if idmap.Empty() { 51 pidmap = nil 52 } 53 54 rm, err := resources.NewMonitor() 55 if err != nil { 56 return nil, err 57 } 58 59 return runcexecutor.New(runcexecutor.Opt{ 60 Root: filepath.Join(root, "executor"), 61 CommandCandidates: []string{"runc"}, 62 DefaultCgroupParent: cgroupParent, 63 Rootless: rootless, 64 NoPivot: os.Getenv("DOCKER_RAMDISK") != "", 65 IdentityMapping: pidmap, 66 DNS: dnsConfig, 67 ApparmorProfile: apparmorProfile, 68 ResourceMonitor: rm, 69 }, networkProviders) 70 } 71 72 type bridgeProvider struct { 73 *libnetwork.Controller 74 Root string 75 } 76 77 func (p *bridgeProvider) New(ctx context.Context, hostname string) (network.Namespace, error) { 78 n, err := p.NetworkByName(networkName) 79 if err != nil { 80 return nil, err 81 } 82 83 iface := &lnInterface{ready: make(chan struct{}), provider: p} 84 iface.Once.Do(func() { 85 go iface.init(p.Controller, n) 86 }) 87 88 return iface, nil 89 } 90 91 func (p *bridgeProvider) Close() error { 92 return nil 93 } 94 95 type lnInterface struct { 96 ep *libnetwork.Endpoint 97 sbx *libnetwork.Sandbox 98 sync.Once 99 err error 100 ready chan struct{} 101 provider *bridgeProvider 102 } 103 104 func (iface *lnInterface) init(c *libnetwork.Controller, n *libnetwork.Network) { 105 defer close(iface.ready) 106 id := identity.NewID() 107 108 ep, err := n.CreateEndpoint(id, libnetwork.CreateOptionDisableResolution()) 109 if err != nil { 110 iface.err = err 111 return 112 } 113 114 sbx, err := c.NewSandbox(id, libnetwork.OptionUseExternalKey(), libnetwork.OptionHostsPath(filepath.Join(iface.provider.Root, id, "hosts")), 115 libnetwork.OptionResolvConfPath(filepath.Join(iface.provider.Root, id, "resolv.conf"))) 116 if err != nil { 117 iface.err = err 118 return 119 } 120 121 if err := ep.Join(sbx); err != nil { 122 iface.err = err 123 return 124 } 125 126 iface.sbx = sbx 127 iface.ep = ep 128 } 129 130 // TODO(neersighted): Unstub Sample(), and collect data from the libnetwork Endpoint. 131 func (iface *lnInterface) Sample() (*network.Sample, error) { 132 return &network.Sample{}, nil 133 } 134 135 func (iface *lnInterface) Set(s *specs.Spec) error { 136 <-iface.ready 137 if iface.err != nil { 138 log.G(context.TODO()).WithError(iface.err).Error("failed to set networking spec") 139 return iface.err 140 } 141 shortNetCtlrID := stringid.TruncateID(iface.provider.Controller.ID()) 142 // attach netns to bridge within the container namespace, using reexec in a prestart hook 143 s.Hooks = &specs.Hooks{ 144 Prestart: []specs.Hook{{ 145 Path: filepath.Join("/proc", strconv.Itoa(os.Getpid()), "exe"), 146 Args: []string{"libnetwork-setkey", "-exec-root=" + iface.provider.Config().ExecRoot, iface.sbx.ContainerID(), shortNetCtlrID}, 147 }}, 148 } 149 return nil 150 } 151 152 func (iface *lnInterface) Close() error { 153 <-iface.ready 154 if iface.sbx != nil { 155 go func() { 156 if err := iface.sbx.Delete(); err != nil { 157 log.G(context.TODO()).WithError(err).Errorf("failed to delete builder network sandbox") 158 } 159 if err := os.RemoveAll(filepath.Join(iface.provider.Root, iface.sbx.ContainerID())); err != nil { 160 log.G(context.TODO()).WithError(err).Errorf("failed to delete builder sandbox directory") 161 } 162 }() 163 } 164 return iface.err 165 } 166 167 func getDNSConfig(cfg config.DNSConfig) *oci.DNSConfig { 168 if cfg.DNS != nil || cfg.DNSSearch != nil || cfg.DNSOptions != nil { 169 return &oci.DNSConfig{ 170 Nameservers: ipAddresses(cfg.DNS), 171 SearchDomains: cfg.DNSSearch, 172 Options: cfg.DNSOptions, 173 } 174 } 175 return nil 176 } 177 178 func ipAddresses(ips []net.IP) []string { 179 var addrs []string 180 for _, ip := range ips { 181 addrs = append(addrs, ip.String()) 182 } 183 return addrs 184 }