commit
7671a84fc2
|
@ -108,6 +108,7 @@ func TestIntegration(t *testing.T) {
|
||||||
testSecretMounts,
|
testSecretMounts,
|
||||||
testExtraHosts,
|
testExtraHosts,
|
||||||
testShmSize,
|
testShmSize,
|
||||||
|
testUlimit,
|
||||||
testNetworkMode,
|
testNetworkMode,
|
||||||
testFrontendMetadataReturn,
|
testFrontendMetadataReturn,
|
||||||
testFrontendUseSolveResults,
|
testFrontendUseSolveResults,
|
||||||
|
@ -560,6 +561,47 @@ func testShmSize(t *testing.T, sb integration.Sandbox) {
|
||||||
require.Contains(t, string(dt), `size=131072k`)
|
require.Contains(t, string(dt), `size=131072k`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testUlimit(t *testing.T, sb integration.Sandbox) {
|
||||||
|
c, err := New(sb.Context(), sb.Address())
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
busybox := llb.Image("busybox:latest")
|
||||||
|
st := llb.Scratch()
|
||||||
|
|
||||||
|
run := func(cmd string, ro ...llb.RunOption) {
|
||||||
|
st = busybox.Run(append(ro, llb.Shlex(cmd), llb.Dir("/wd"))...).AddMount("/wd", st)
|
||||||
|
}
|
||||||
|
|
||||||
|
run(`sh -c "ulimit -n > first"`, llb.AddUlimit(llb.UlimitNofile, 1062, 1062))
|
||||||
|
run(`sh -c "ulimit -n > second"`)
|
||||||
|
|
||||||
|
def, err := st.Marshal(sb.Context())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
destDir, err := ioutil.TempDir("", "buildkit")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.RemoveAll(destDir)
|
||||||
|
|
||||||
|
_, err = c.Solve(sb.Context(), def, SolveOpt{
|
||||||
|
Exports: []ExportEntry{
|
||||||
|
{
|
||||||
|
Type: ExporterLocal,
|
||||||
|
OutputDir: destDir,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
dt, err := ioutil.ReadFile(filepath.Join(destDir, "first"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `1062`, strings.TrimSpace(string(dt)))
|
||||||
|
|
||||||
|
dt2, err := ioutil.ReadFile(filepath.Join(destDir, "second"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEqual(t, `1062`, strings.TrimSpace(string(dt2)))
|
||||||
|
}
|
||||||
|
|
||||||
func testNetworkMode(t *testing.T, sb integration.Sandbox) {
|
func testNetworkMode(t *testing.T, sb integration.Sandbox) {
|
||||||
c, err := New(sb.Context(), sb.Address())
|
c, err := New(sb.Context(), sb.Address())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -213,6 +213,23 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
|
||||||
meta.ShmSize = *shmSize
|
meta.ShmSize = *shmSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ulimits, err := getUlimit(e.base)(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, nil, nil, err
|
||||||
|
}
|
||||||
|
if len(ulimits) > 0 {
|
||||||
|
addCap(&e.constraints, pb.CapExecMetaUlimit)
|
||||||
|
ul := make([]*pb.Ulimit, len(ulimits))
|
||||||
|
for i, u := range ulimits {
|
||||||
|
ul[i] = &pb.Ulimit{
|
||||||
|
Name: u.Name,
|
||||||
|
Soft: u.Soft,
|
||||||
|
Hard: u.Hard,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
meta.Ulimit = ul
|
||||||
|
}
|
||||||
|
|
||||||
network, err := getNetwork(e.base)(ctx, c)
|
network, err := getNetwork(e.base)(ctx, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, nil, nil, err
|
return "", nil, nil, nil, err
|
||||||
|
@ -513,6 +530,12 @@ func WithShmSize(kb int64) RunOption {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddUlimit(name UlimitName, soft int64, hard int64) RunOption {
|
||||||
|
return runOptionFunc(func(ei *ExecInfo) {
|
||||||
|
ei.State = ei.State.AddUlimit(name, soft, hard)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func With(so ...StateOption) RunOption {
|
func With(so ...StateOption) RunOption {
|
||||||
return runOptionFunc(func(ei *ExecInfo) {
|
return runOptionFunc(func(ei *ExecInfo) {
|
||||||
ei.State = ei.State.With(so...)
|
ei.State = ei.State.With(so...)
|
||||||
|
@ -682,3 +705,23 @@ const (
|
||||||
SecurityModeInsecure = pb.SecurityMode_INSECURE
|
SecurityModeInsecure = pb.SecurityMode_INSECURE
|
||||||
SecurityModeSandbox = pb.SecurityMode_SANDBOX
|
SecurityModeSandbox = pb.SecurityMode_SANDBOX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type UlimitName string
|
||||||
|
|
||||||
|
const (
|
||||||
|
UlimitCore UlimitName = "core"
|
||||||
|
UlimitCPU UlimitName = "cpu"
|
||||||
|
UlimitData UlimitName = "data"
|
||||||
|
UlimitFsize UlimitName = "fsize"
|
||||||
|
UlimitLocks UlimitName = "locks"
|
||||||
|
UlimitMemlock UlimitName = "memlock"
|
||||||
|
UlimitMsgqueue UlimitName = "msgqueue"
|
||||||
|
UlimitNice UlimitName = "nice"
|
||||||
|
UlimitNofile UlimitName = "nofile"
|
||||||
|
UlimitNproc UlimitName = "nproc"
|
||||||
|
UlimitRss UlimitName = "rss"
|
||||||
|
UlimitRtprio UlimitName = "rtprio"
|
||||||
|
UlimitRttime UlimitName = "rttime"
|
||||||
|
UlimitSigpending UlimitName = "sigpending"
|
||||||
|
UlimitStack UlimitName = "stack"
|
||||||
|
)
|
||||||
|
|
|
@ -18,10 +18,12 @@ var (
|
||||||
keyArgs = contextKeyT("llb.exec.args")
|
keyArgs = contextKeyT("llb.exec.args")
|
||||||
keyDir = contextKeyT("llb.exec.dir")
|
keyDir = contextKeyT("llb.exec.dir")
|
||||||
keyEnv = contextKeyT("llb.exec.env")
|
keyEnv = contextKeyT("llb.exec.env")
|
||||||
keyUser = contextKeyT("llb.exec.user")
|
|
||||||
keyHostname = contextKeyT("llb.exec.hostname")
|
|
||||||
keyExtraHost = contextKeyT("llb.exec.extrahost")
|
keyExtraHost = contextKeyT("llb.exec.extrahost")
|
||||||
|
keyHostname = contextKeyT("llb.exec.hostname")
|
||||||
keyShmSize = contextKeyT("llb.exec.shmsize")
|
keyShmSize = contextKeyT("llb.exec.shmsize")
|
||||||
|
keyUlimit = contextKeyT("llb.exec.ulimit")
|
||||||
|
keyUser = contextKeyT("llb.exec.user")
|
||||||
|
|
||||||
keyPlatform = contextKeyT("llb.platform")
|
keyPlatform = contextKeyT("llb.platform")
|
||||||
keyNetwork = contextKeyT("llb.network")
|
keyNetwork = contextKeyT("llb.network")
|
||||||
keySecurity = contextKeyT("llb.security")
|
keySecurity = contextKeyT("llb.security")
|
||||||
|
@ -253,6 +255,35 @@ func getShmSize(s State) func(context.Context, *Constraints) (*int64, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ulimit(name UlimitName, soft int64, hard int64) StateOption {
|
||||||
|
return func(s State) State {
|
||||||
|
return s.withValue(keyUlimit, func(ctx context.Context, c *Constraints) (interface{}, error) {
|
||||||
|
v, err := getUlimit(s)(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return append(v, pb.Ulimit{
|
||||||
|
Name: string(name),
|
||||||
|
Soft: soft,
|
||||||
|
Hard: hard,
|
||||||
|
}), nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUlimit(s State) func(context.Context, *Constraints) ([]pb.Ulimit, error) {
|
||||||
|
return func(ctx context.Context, c *Constraints) ([]pb.Ulimit, error) {
|
||||||
|
v, err := s.getValue(keyUlimit)(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if v != nil {
|
||||||
|
return v.([]pb.Ulimit), nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Network(v pb.NetMode) StateOption {
|
func Network(v pb.NetMode) StateOption {
|
||||||
return func(s State) State {
|
return func(s State) State {
|
||||||
return s.WithValue(keyNetwork, v)
|
return s.WithValue(keyNetwork, v)
|
||||||
|
|
|
@ -401,6 +401,10 @@ func (s State) WithShmSize(kb int64) State {
|
||||||
return shmSize(kb)(s)
|
return shmSize(kb)(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s State) AddUlimit(name UlimitName, soft int64, hard int64) State {
|
||||||
|
return ulimit(name, soft, hard)(s)
|
||||||
|
}
|
||||||
|
|
||||||
func (s State) isFileOpCopyInput() {}
|
func (s State) isFileOpCopyInput() {}
|
||||||
|
|
||||||
type output struct {
|
type output struct {
|
||||||
|
|
|
@ -19,6 +19,7 @@ type Meta struct {
|
||||||
ReadonlyRootFS bool
|
ReadonlyRootFS bool
|
||||||
ExtraHosts []HostIP
|
ExtraHosts []HostIP
|
||||||
ShmSize int64
|
ShmSize int64
|
||||||
|
Ulimit []*pb.Ulimit
|
||||||
NetMode pb.NetMode
|
NetMode pb.NetMode
|
||||||
SecurityMode pb.SecurityMode
|
SecurityMode pb.SecurityMode
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,12 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rlimitsOpts, err := generateRlimitOpts(meta.Ulimit); err == nil {
|
||||||
|
opts = append(opts, rlimitsOpts...)
|
||||||
|
} else {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
hostname := defaultHostname
|
hostname := defaultHostname
|
||||||
if meta.Hostname != "" {
|
if meta.Hostname != "" {
|
||||||
hostname = meta.Hostname
|
hostname = meta.Hostname
|
||||||
|
@ -100,13 +106,16 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(meta.Ulimit) == 0 {
|
||||||
|
// reset open files limit
|
||||||
|
s.Process.Rlimits = nil
|
||||||
|
}
|
||||||
|
|
||||||
// set the networking information on the spec
|
// set the networking information on the spec
|
||||||
if err := namespace.Set(s); err != nil {
|
if err := namespace.Set(s); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Process.Rlimits = nil // reset open files limit
|
|
||||||
|
|
||||||
sm := &submounts{}
|
sm := &submounts{}
|
||||||
|
|
||||||
var releasers []func() error
|
var releasers []func() error
|
||||||
|
|
|
@ -4,6 +4,8 @@ package oci
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
|
@ -78,6 +80,29 @@ func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateRlimitOpts(ulimits []*pb.Ulimit) ([]oci.SpecOpts, error) {
|
||||||
|
if len(ulimits) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var rlimits []specs.POSIXRlimit
|
||||||
|
for _, u := range ulimits {
|
||||||
|
if u == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rlimits = append(rlimits, specs.POSIXRlimit{
|
||||||
|
Type: fmt.Sprintf("RLIMIT_%s", strings.ToUpper(u.Name)),
|
||||||
|
Hard: uint64(u.Hard),
|
||||||
|
Soft: uint64(u.Soft),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return []oci.SpecOpts{
|
||||||
|
func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
|
||||||
|
s.Process.Rlimits = rlimits
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// withDefaultProfile sets the default seccomp profile to the spec.
|
// withDefaultProfile sets the default seccomp profile to the spec.
|
||||||
// Note: must follow the setting of process capabilities
|
// Note: must follow the setting of process capabilities
|
||||||
func withDefaultProfile() oci.SpecOpts {
|
func withDefaultProfile() oci.SpecOpts {
|
||||||
|
|
|
@ -35,3 +35,10 @@ func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
|
||||||
}
|
}
|
||||||
return nil, errors.New("no support for IdentityMapping on Windows")
|
return nil, errors.New("no support for IdentityMapping on Windows")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateRlimitOpts(ulimits []*pb.Ulimit) ([]oci.SpecOpts, error) {
|
||||||
|
if len(ulimits) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("no support for POSIXRlimit on Windows")
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
|
"github.com/docker/go-units"
|
||||||
controlapi "github.com/moby/buildkit/api/services/control"
|
controlapi "github.com/moby/buildkit/api/services/control"
|
||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
||||||
|
@ -55,6 +56,7 @@ const (
|
||||||
keyOverrideCopyImage = "override-copy-image" // remove after CopyOp implemented
|
keyOverrideCopyImage = "override-copy-image" // remove after CopyOp implemented
|
||||||
keyShmSize = "shm-size"
|
keyShmSize = "shm-size"
|
||||||
keyTargetPlatform = "platform"
|
keyTargetPlatform = "platform"
|
||||||
|
keyUlimit = "ulimit"
|
||||||
|
|
||||||
// Don't forget to update frontend documentation if you add
|
// Don't forget to update frontend documentation if you add
|
||||||
// a new build-arg: frontend/dockerfile/docs/syntax.md
|
// a new build-arg: frontend/dockerfile/docs/syntax.md
|
||||||
|
@ -122,6 +124,11 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
|
||||||
return nil, errors.Wrap(err, "failed to parse shm size")
|
return nil, errors.Wrap(err, "failed to parse shm size")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ulimit, err := parseUlimits(opts[keyUlimit])
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to parse ulimit")
|
||||||
|
}
|
||||||
|
|
||||||
defaultNetMode, err := parseNetMode(opts[keyForceNetwork])
|
defaultNetMode, err := parseNetMode(opts[keyForceNetwork])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -434,6 +441,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
|
||||||
PrefixPlatform: exportMap,
|
PrefixPlatform: exportMap,
|
||||||
ExtraHosts: extraHosts,
|
ExtraHosts: extraHosts,
|
||||||
ShmSize: shmSize,
|
ShmSize: shmSize,
|
||||||
|
Ulimit: ulimit,
|
||||||
ForceNetMode: defaultNetMode,
|
ForceNetMode: defaultNetMode,
|
||||||
OverrideCopyImage: opts[keyOverrideCopyImage],
|
OverrideCopyImage: opts[keyOverrideCopyImage],
|
||||||
LLBCaps: &caps,
|
LLBCaps: &caps,
|
||||||
|
@ -693,6 +701,30 @@ func parseShmSize(v string) (int64, error) {
|
||||||
return kb, nil
|
return kb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseUlimits(v string) ([]pb.Ulimit, error) {
|
||||||
|
if v == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
out := make([]pb.Ulimit, 0)
|
||||||
|
csvReader := csv.NewReader(strings.NewReader(v))
|
||||||
|
fields, err := csvReader.Read()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, field := range fields {
|
||||||
|
ulimit, err := units.ParseUlimit(field)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out = append(out, pb.Ulimit{
|
||||||
|
Name: ulimit.Name,
|
||||||
|
Soft: ulimit.Soft,
|
||||||
|
Hard: ulimit.Hard,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseNetMode(v string) (pb.NetMode, error) {
|
func parseNetMode(v string) (pb.NetMode, error) {
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return llb.NetModeSandbox, nil
|
return llb.NetModeSandbox, nil
|
||||||
|
|
|
@ -60,6 +60,7 @@ type ConvertOpt struct {
|
||||||
PrefixPlatform bool
|
PrefixPlatform bool
|
||||||
ExtraHosts []llb.HostIP
|
ExtraHosts []llb.HostIP
|
||||||
ShmSize int64
|
ShmSize int64
|
||||||
|
Ulimit []pb.Ulimit
|
||||||
ForceNetMode pb.NetMode
|
ForceNetMode pb.NetMode
|
||||||
OverrideCopyImage string
|
OverrideCopyImage string
|
||||||
LLBCaps *apicaps.CapSet
|
LLBCaps *apicaps.CapSet
|
||||||
|
@ -391,6 +392,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
|
||||||
targetPlatform: platformOpt.targetPlatform,
|
targetPlatform: platformOpt.targetPlatform,
|
||||||
extraHosts: opt.ExtraHosts,
|
extraHosts: opt.ExtraHosts,
|
||||||
shmSize: opt.ShmSize,
|
shmSize: opt.ShmSize,
|
||||||
|
ulimit: opt.Ulimit,
|
||||||
copyImage: opt.OverrideCopyImage,
|
copyImage: opt.OverrideCopyImage,
|
||||||
llbCaps: opt.LLBCaps,
|
llbCaps: opt.LLBCaps,
|
||||||
sourceMap: opt.SourceMap,
|
sourceMap: opt.SourceMap,
|
||||||
|
@ -522,6 +524,7 @@ type dispatchOpt struct {
|
||||||
buildPlatforms []ocispecs.Platform
|
buildPlatforms []ocispecs.Platform
|
||||||
extraHosts []llb.HostIP
|
extraHosts []llb.HostIP
|
||||||
shmSize int64
|
shmSize int64
|
||||||
|
ulimit []pb.Ulimit
|
||||||
copyImage string
|
copyImage string
|
||||||
llbCaps *apicaps.CapSet
|
llbCaps *apicaps.CapSet
|
||||||
sourceMap *llb.SourceMap
|
sourceMap *llb.SourceMap
|
||||||
|
@ -789,6 +792,12 @@ func dispatchRun(d *dispatchState, c *instructions.RunCommand, proxy *llb.ProxyE
|
||||||
opt = append(opt, networkOpt)
|
opt = append(opt, networkOpt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dopt.llbCaps != nil && dopt.llbCaps.Supports(pb.CapExecMetaUlimit) == nil {
|
||||||
|
for _, u := range dopt.ulimit {
|
||||||
|
opt = append(opt, llb.AddUlimit(llb.UlimitName(u.Name), u.Soft, u.Hard))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shlex := *dopt.shlex
|
shlex := *dopt.shlex
|
||||||
shlex.RawQuotes = true
|
shlex.RawQuotes = true
|
||||||
shlex.SkipUnsetEnv = true
|
shlex.SkipUnsetEnv = true
|
||||||
|
@ -804,6 +813,7 @@ func dispatchRun(d *dispatchState, c *instructions.RunCommand, proxy *llb.ProxyE
|
||||||
if dopt.shmSize > 0 {
|
if dopt.shmSize > 0 {
|
||||||
opt = append(opt, llb.WithShmSize(dopt.shmSize))
|
opt = append(opt, llb.WithShmSize(dopt.shmSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
d.state = d.state.Run(opt...).Root()
|
d.state = d.state.Run(opt...).Root()
|
||||||
return commitToHistory(&d.image, "RUN "+runCommandString(args, d.buildArgs, shell.BuildEnvs(env)), true, &d.state)
|
return commitToHistory(&d.image, "RUN "+runCommandString(args, d.buildArgs, shell.BuildEnvs(env)), true, &d.state)
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,8 @@ var allTests = []integration.Test{
|
||||||
testWildcardRenameCache,
|
testWildcardRenameCache,
|
||||||
testDockerfileInvalidInstruction,
|
testDockerfileInvalidInstruction,
|
||||||
testBuildInfo,
|
testBuildInfo,
|
||||||
|
testShmSize,
|
||||||
|
testUlimit,
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileOpTests = []integration.Test{
|
var fileOpTests = []integration.Test{
|
||||||
|
@ -5264,6 +5266,96 @@ COPY --from=buildx /buildx /usr/libexec/docker/cli-plugins/docker-buildx
|
||||||
assert.Equal(t, "sha256:419455202b0ef97e480d7f8199b26a721a417818bc0e2d106975f74323f25e6c", bi["sources"][3].Pin)
|
assert.Equal(t, "sha256:419455202b0ef97e480d7f8199b26a721a417818bc0e2d106975f74323f25e6c", bi["sources"][3].Pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testShmSize(t *testing.T, sb integration.Sandbox) {
|
||||||
|
f := getFrontend(t, sb)
|
||||||
|
dockerfile := []byte(`
|
||||||
|
FROM busybox AS base
|
||||||
|
RUN mount | grep /dev/shm > /shmsize
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=base /shmsize /
|
||||||
|
`)
|
||||||
|
|
||||||
|
dir, err := tmpdir(
|
||||||
|
fstest.CreateFile("Dockerfile", dockerfile, 0600),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
c, err := client.New(sb.Context(), sb.Address())
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
destDir, err := ioutil.TempDir("", "buildkit")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.RemoveAll(destDir)
|
||||||
|
|
||||||
|
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
|
||||||
|
FrontendAttrs: map[string]string{
|
||||||
|
"shm-size": "131072",
|
||||||
|
},
|
||||||
|
LocalDirs: map[string]string{
|
||||||
|
builder.DefaultLocalNameDockerfile: dir,
|
||||||
|
builder.DefaultLocalNameContext: dir,
|
||||||
|
},
|
||||||
|
Exports: []client.ExportEntry{
|
||||||
|
{
|
||||||
|
Type: client.ExporterLocal,
|
||||||
|
OutputDir: destDir,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
dt, err := ioutil.ReadFile(filepath.Join(destDir, "shmsize"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Contains(t, string(dt), `size=131072k`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUlimit(t *testing.T, sb integration.Sandbox) {
|
||||||
|
f := getFrontend(t, sb)
|
||||||
|
dockerfile := []byte(`
|
||||||
|
FROM busybox AS base
|
||||||
|
RUN ulimit -n > /ulimit
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=base /ulimit /
|
||||||
|
`)
|
||||||
|
|
||||||
|
dir, err := tmpdir(
|
||||||
|
fstest.CreateFile("Dockerfile", dockerfile, 0600),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
c, err := client.New(sb.Context(), sb.Address())
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
destDir, err := ioutil.TempDir("", "buildkit")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.RemoveAll(destDir)
|
||||||
|
|
||||||
|
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
|
||||||
|
FrontendAttrs: map[string]string{
|
||||||
|
"ulimit": "nofile=1062:1062",
|
||||||
|
},
|
||||||
|
LocalDirs: map[string]string{
|
||||||
|
builder.DefaultLocalNameDockerfile: dir,
|
||||||
|
builder.DefaultLocalNameContext: dir,
|
||||||
|
},
|
||||||
|
Exports: []client.ExportEntry{
|
||||||
|
{
|
||||||
|
Type: client.ExporterLocal,
|
||||||
|
OutputDir: destDir,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
dt, err := ioutil.ReadFile(filepath.Join(destDir, "ulimit"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `1062`, strings.TrimSpace(string(dt)))
|
||||||
|
}
|
||||||
|
|
||||||
func tmpdir(appliers ...fstest.Applier) (string, error) {
|
func tmpdir(appliers ...fstest.Applier) (string, error) {
|
||||||
tmpdir, err := ioutil.TempDir("", "buildkit-dockerfile")
|
tmpdir, err := ioutil.TempDir("", "buildkit-dockerfile")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -21,6 +21,7 @@ require (
|
||||||
// docker: the actual version is replaced in replace()
|
// docker: the actual version is replaced in replace()
|
||||||
github.com/docker/docker v20.10.7+incompatible // master (v21.xx-dev)
|
github.com/docker/docker v20.10.7+incompatible // master (v21.xx-dev)
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
|
github.com/docker/go-units v0.4.0
|
||||||
github.com/gofrs/flock v0.7.3
|
github.com/gofrs/flock v0.7.3
|
||||||
github.com/gogo/googleapis v1.4.0
|
github.com/gogo/googleapis v1.4.0
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
|
@ -92,7 +93,6 @@ require (
|
||||||
github.com/docker/docker-credential-helpers v0.6.4 // indirect
|
github.com/docker/docker-credential-helpers v0.6.4 // indirect
|
||||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||||
github.com/docker/go-metrics v0.0.1 // indirect
|
github.com/docker/go-metrics v0.0.1 // indirect
|
||||||
github.com/docker/go-units v0.4.0 // indirect
|
|
||||||
github.com/felixge/httpsnoop v1.0.2 // indirect
|
github.com/felixge/httpsnoop v1.0.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/uuid v1.2.0 // indirect
|
github.com/google/uuid v1.2.0 // indirect
|
||||||
|
|
|
@ -316,6 +316,7 @@ func (e *execOp) Exec(ctx context.Context, g session.Group, inputs []solver.Resu
|
||||||
ReadonlyRootFS: p.ReadonlyRootFS,
|
ReadonlyRootFS: p.ReadonlyRootFS,
|
||||||
ExtraHosts: extraHosts,
|
ExtraHosts: extraHosts,
|
||||||
ShmSize: e.op.Meta.ShmSize,
|
ShmSize: e.op.Meta.ShmSize,
|
||||||
|
Ulimit: e.op.Meta.Ulimit,
|
||||||
NetMode: e.op.Network,
|
NetMode: e.op.Network,
|
||||||
SecurityMode: e.op.Security,
|
SecurityMode: e.op.Security,
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,12 @@ const (
|
||||||
CapBuildOpLLBFileName apicaps.CapID = "source.buildop.llbfilename"
|
CapBuildOpLLBFileName apicaps.CapID = "source.buildop.llbfilename"
|
||||||
|
|
||||||
CapExecMetaBase apicaps.CapID = "exec.meta.base"
|
CapExecMetaBase apicaps.CapID = "exec.meta.base"
|
||||||
CapExecMetaProxy apicaps.CapID = "exec.meta.proxyenv"
|
|
||||||
CapExecMetaNetwork apicaps.CapID = "exec.meta.network"
|
CapExecMetaNetwork apicaps.CapID = "exec.meta.network"
|
||||||
|
CapExecMetaProxy apicaps.CapID = "exec.meta.proxyenv"
|
||||||
CapExecMetaSecurity apicaps.CapID = "exec.meta.security"
|
CapExecMetaSecurity apicaps.CapID = "exec.meta.security"
|
||||||
|
CapExecMetaSecurityDeviceWhitelistV1 apicaps.CapID = "exec.meta.security.devices.v1"
|
||||||
CapExecMetaSetsDefaultPath apicaps.CapID = "exec.meta.setsdefaultpath"
|
CapExecMetaSetsDefaultPath apicaps.CapID = "exec.meta.setsdefaultpath"
|
||||||
|
CapExecMetaUlimit apicaps.CapID = "exec.meta.ulimit"
|
||||||
CapExecMountBind apicaps.CapID = "exec.mount.bind"
|
CapExecMountBind apicaps.CapID = "exec.mount.bind"
|
||||||
CapExecMountBindReadWriteNoOuput apicaps.CapID = "exec.mount.bind.readwrite-nooutput"
|
CapExecMountBindReadWriteNoOuput apicaps.CapID = "exec.mount.bind.readwrite-nooutput"
|
||||||
CapExecMountCache apicaps.CapID = "exec.mount.cache"
|
CapExecMountCache apicaps.CapID = "exec.mount.cache"
|
||||||
|
@ -50,8 +52,6 @@ const (
|
||||||
CapExecMountSSH apicaps.CapID = "exec.mount.ssh"
|
CapExecMountSSH apicaps.CapID = "exec.mount.ssh"
|
||||||
CapExecCgroupsMounted apicaps.CapID = "exec.cgroup"
|
CapExecCgroupsMounted apicaps.CapID = "exec.cgroup"
|
||||||
|
|
||||||
CapExecMetaSecurityDeviceWhitelistV1 apicaps.CapID = "exec.meta.security.devices.v1"
|
|
||||||
|
|
||||||
CapFileBase apicaps.CapID = "file.base"
|
CapFileBase apicaps.CapID = "file.base"
|
||||||
CapFileRmWildcard apicaps.CapID = "file.rm.wildcard"
|
CapFileRmWildcard apicaps.CapID = "file.rm.wildcard"
|
||||||
CapFileCopyIncludeExcludePatterns apicaps.CapID = "file.copy.includeexcludepatterns"
|
CapFileCopyIncludeExcludePatterns apicaps.CapID = "file.copy.includeexcludepatterns"
|
||||||
|
@ -236,6 +236,12 @@ func init() {
|
||||||
Status: apicaps.CapStatusExperimental,
|
Status: apicaps.CapStatusExperimental,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Caps.Init(apicaps.Cap{
|
||||||
|
ID: CapExecMetaUlimit,
|
||||||
|
Enabled: true,
|
||||||
|
Status: apicaps.CapStatusExperimental,
|
||||||
|
})
|
||||||
|
|
||||||
Caps.Init(apicaps.Cap{
|
Caps.Init(apicaps.Cap{
|
||||||
ID: CapExecMountBind,
|
ID: CapExecMountBind,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
|
|
1076
solver/pb/ops.pb.go
1076
solver/pb/ops.pb.go
File diff suppressed because it is too large
Load Diff
|
@ -59,6 +59,18 @@ message Meta {
|
||||||
repeated HostIP extraHosts = 6;
|
repeated HostIP extraHosts = 6;
|
||||||
string hostname = 7;
|
string hostname = 7;
|
||||||
int64 shmSize = 8;
|
int64 shmSize = 8;
|
||||||
|
repeated Ulimit ulimit = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HostIP {
|
||||||
|
string Host = 1;
|
||||||
|
string IP = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Ulimit {
|
||||||
|
string Name = 1;
|
||||||
|
int64 Soft = 2;
|
||||||
|
int64 Hard = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum NetMode {
|
enum NetMode {
|
||||||
|
@ -244,11 +256,6 @@ message Definition {
|
||||||
Source Source = 3;
|
Source Source = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message HostIP {
|
|
||||||
string Host = 1;
|
|
||||||
string IP = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message FileOp {
|
message FileOp {
|
||||||
repeated FileAction actions = 2;
|
repeated FileAction actions = 2;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue