Skip to content

Commit

Permalink
bake: ulimits support
Browse files Browse the repository at this point in the history
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
  • Loading branch information
crazy-max committed Feb 5, 2024
1 parent 3abc8ba commit 0bdee7c
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 0 deletions.
15 changes: 15 additions & 0 deletions bake/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@ type Target struct {
NetworkMode *string `json:"-" hcl:"-" cty:"-"`
NoCacheFilter []string `json:"no-cache-filter,omitempty" hcl:"no-cache-filter,optional" cty:"no-cache-filter"`
ShmSize *string `json:"shm-size,omitempty" hcl:"shm-size,optional"`
Ulimits []string `json:"ulimits,omitempty" hcl:"ulimits,optional"`
// IMPORTANT: if you add more fields here, do not forget to update newOverrides and docs/bake-reference.md.

// linked is a private field to mark a target used as a linked one
Expand All @@ -723,6 +724,7 @@ func (t *Target) normalize() {
t.CacheTo = removeDupes(t.CacheTo)
t.Outputs = removeDupes(t.Outputs)
t.NoCacheFilter = removeDupes(t.NoCacheFilter)
t.Ulimits = removeDupes(t.Ulimits)

for k, v := range t.Contexts {
if v == "" {
Expand Down Expand Up @@ -814,6 +816,9 @@ func (t *Target) Merge(t2 *Target) {
if t2.ShmSize != nil { // no merge
t.ShmSize = t2.ShmSize
}
if t2.Ulimits != nil { // merge
t.Ulimits = append(t.Ulimits, t2.Ulimits...)
}
t.Inherits = append(t.Inherits, t2.Inherits...)
}

Expand Down Expand Up @@ -880,6 +885,8 @@ func (t *Target) AddOverrides(overrides map[string]Override) error {
t.NoCacheFilter = o.ArrValue
case "shm-size":
t.ShmSize = &value
case "ulimits":
t.Ulimits = o.ArrValue
case "pull":
pull, err := strconv.ParseBool(value)
if err != nil {
Expand Down Expand Up @@ -1335,6 +1342,14 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
return nil, err
}

var ulimits *dockeropts.UlimitOpt
for _, field := range t.Ulimits {
if err := ulimits.Set(field); err != nil {
return nil, err
}
}
bo.Ulimits = ulimits

return bo, nil
}

Expand Down
2 changes: 2 additions & 0 deletions bake/bake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ target "webDEP" {
}
no-cache = true
shm-size = "128m"
ulimits = ["nofile=1024:1024"]
}
target "webapp" {
Expand All @@ -47,6 +48,7 @@ target "webapp" {
require.Equal(t, ptrstr("webDEP"), m["webapp"].Args["VAR_INHERITED"])
require.Equal(t, true, *m["webapp"].NoCache)
require.Equal(t, "128m", *m["webapp"].ShmSize)
require.Equal(t, []string{"nofile=1024:1024"}, m["webapp"].Ulimits)
require.Nil(t, m["webapp"].Pull)

require.Equal(t, 1, len(g))
Expand Down
14 changes: 14 additions & 0 deletions bake/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bake

import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
Expand All @@ -10,6 +11,7 @@ import (
"github.com/compose-spec/compose-go/v2/loader"
composetypes "github.com/compose-spec/compose-go/v2/types"
dockeropts "github.com/docker/cli/opts"
"github.com/docker/go-units"
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
)
Expand Down Expand Up @@ -94,6 +96,17 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf
shmSize = &shmSizeStr
}

var ulimits []string
if s.Build.Ulimits != nil {
for n, u := range s.Build.Ulimits {
if ulimit, err := units.ParseUlimit(fmt.Sprintf("%s=%d:%d", n, u.Soft, u.Hard)); err != nil {
return nil, err
} else {
ulimits = append(ulimits, ulimit.String())
}
}
}

var secrets []string
for _, bs := range s.Build.Secrets {
secret, err := composeToBuildkitSecret(bs, cfg.Secrets[bs.Source])
Expand Down Expand Up @@ -131,6 +144,7 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf
NetworkMode: &s.Build.Network,
Secrets: secrets,
ShmSize: shmSize,
Ulimits: ulimits,
}
if err = t.composeExtTarget(s.Build.Extensions); err != nil {
return nil, err
Expand Down
5 changes: 5 additions & 0 deletions bake/compose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ services:
CT_ECR: foo
CT_TAG: bar
shm_size: 128m
ulimits:
nofile:
soft: 1024
hard: 1024
x-bake:
secret:
- id=mysecret,src=/local/secret
Expand Down Expand Up @@ -334,6 +338,7 @@ services:
require.Equal(t, []string{"type=docker"}, c.Targets[1].Outputs)
require.Equal(t, newBool(true), c.Targets[1].NoCache)
require.Equal(t, ptrstr("128MiB"), c.Targets[1].ShmSize)
require.Equal(t, []string{"nofile=1024:1024"}, c.Targets[1].Ulimits)
}

func TestComposeExtDedup(t *testing.T) {
Expand Down
20 changes: 20 additions & 0 deletions docs/bake-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ The following table shows the complete list of attributes that you can assign to
| [`ssh`](#targetssh) | List | SSH agent sockets or keys to expose to the build |
| [`tags`](#targettags) | List | Image names and tags |
| [`target`](#targettarget) | String | Target build stage |
| [`ulimits`](#targetulimits) | List | Ulimit options |

### `target.args`

Expand Down Expand Up @@ -893,6 +894,25 @@ target "default" {
}
```

### `target.ulimits`

Ulimits are specified with a soft and hard limit as such:
`<type>=<soft limit>[:<hard limit>]`, for example:

```hcl
target "app" {
ulimits = [
"nofile=1024:1024"
]
}
```

> **Note**
>
> If you do not provide a `hard limit`, the `soft limit` is used
> for both values. If no `ulimits` are set, they are inherited from
> the default `ulimits` set on the daemon.
## Group

Groups allow you to invoke multiple builds (targets) at once.
Expand Down
33 changes: 33 additions & 0 deletions tests/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
testBakeRemoteLocalContextRemoteDockerfile,
testBakeEmpty,
testBakeShmSize,
testBakeUlimits,
}

func testBakeLocal(t *testing.T, sb integration.Sandbox) {
Expand Down Expand Up @@ -553,3 +554,35 @@ target "default" {
require.NoError(t, err)
require.Contains(t, string(dt), `size=131072k`)
}

func testBakeUlimits(t *testing.T, sb integration.Sandbox) {
dockerfile := []byte(`
FROM busybox AS build
RUN ulimit -n > first > /ulimit
FROM scratch
COPY --from=build /ulimit /
`)
bakefile := []byte(`
target "default" {
ulimits = ["nofile=1024:1024"]
}
`)
dir := tmpdir(
t,
fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0600),
)

dirDest := t.TempDir()

out, err := bakeCmd(
sb,
withDir(dir),
withArgs("--set", "*.output=type=local,dest="+dirDest),
)
require.NoError(t, err, out)

Check failure on line 583 in tests/bake.go

View workflow job for this annotation

GitHub Actions / test-integration (docker, ./tests)

Failed: tests/TestIntegration/TestBakeUlimits/worker=docker

=== RUN TestIntegration/TestBakeUlimits/worker=docker === PAUSE TestIntegration/TestBakeUlimits/worker=docker === CONT TestIntegration/TestBakeUlimits/worker=docker bake.go:583: Error Trace: /src/tests/bake.go:583 /src/vendor/github.com/moby/buildkit/util/testutil/integration/run.go:93 /src/vendor/github.com/moby/buildkit/util/testutil/integration/run.go:207 Error: Received unexpected error: exit status 2 Test: TestIntegration/TestBakeUlimits/worker=docker Messages: panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xad1d36] goroutine 1 [running]: github.com/docker/cli/opts.(*UlimitOpt).Set(0x0, {0xc000279700?, 0xc000279ae0?}) github.com/docker/cli@v25.0.1+incompatible/opts/ulimit.go:30 +0x36 github.com/docker/buildx/bake.toBuildOpt(0xc00051d380, 0x0) github.com/docker/buildx/bake/bake.go:1347 +0x19cc github.com/docker/buildx/bake.TargetsToBuildOpt(0xc000520fc0, 0x11?) github.com/docker/buildx/bake/bake.go:1034 +0x245 github.com/docker/buildx/commands.runBake({0x269b1b0?, 0xc00028c000?}, {0x26aef40?, 0xc000052d00}, {0xc000354740, 0x0, 0x4}, {{0x38a7020, 0x0, 0x0}, ...}, ...) github.com/docker/buildx/commands/bake.go:180 +0x14a5 github.com/docker/buildx/commands.bakeCmd.func1(0xc0002a0300, {0xc000354740, 0x0, 0x4}) github.com/docker/buildx/commands/bake.go:266 +0x265 github.com/spf13/cobra.(*Command).execute(0xc0002a0300, {0xc0000e4140, 0x4, 0x4}) github.com/spf13/cobra@v1.8.0/command.go:983 +0xabc github.com/spf13/cobra.(*Command).ExecuteC(0xc000005b00) github.com/spf13/cobra@v1.8.0/command.go:1115 +0x3ff github.com/spf13/cobra.(*Command).Execute(...) github.com/spf13/cobra@v1.8.0/command.go:1039 main.runStandalone(0x23524f9?) github.com/docker/buildx/cmd/buildx/main.go:42 +0x6e main.main() github.com/docker/buildx/cmd/buildx/main.go:62 +0xf4 sandbox.go:128: stdout: /usr/bin/dockerd sandbox.go:128: stderr: /usr/bin/dockerd sandbox.go:131: > startCmd 2024-02-05 14:29:09.43308022 +0000 UTC m=+36.368288984 /usr/bin/dockerd --data-root /tmp/integration1500555618/dv4guhjm38pst/root --exec-root /tmp/dxr/dv4guhjm38pst --pidfile /tmp/integration1500555618/dv4guhjm38pst/docker.pid --containerd-namespace dv4guhjm38pst --containerd-plugins-namespace dv4guhjm38pstp --host unix:///tmp/docker-integration/dv4guhjm38pst.sock --config-file /tmp/integration1500555618/daemon.json --userland-proxy=false --tls=false --debug sandbox.go:131: time="2024-02-05T14:29:09.461928604Z" level=info msg="Starting up" sandbox.go:131: time="2024-02-05T14:29:09.463454600Z" level=warning msg="could not change group /tmp/docker-integration/dv4guhjm38pst.sock to docker: group docker not found" sandbox.go:131: time="2024-02-05T14:29:09.463605844Z" level=debug msg="Listener created for HTTP on unix (/tmp/docker-integration/dv4guhjm38pst.sock)" sandbox.go:131: time="2024-02-05T14:29:09.463622966Z" level=info msg="containerd not running, starting managed containerd" sandbox.go:131: time="2024-02-05T14:29:09.464205376Z" level=info msg="started new containerd process" address=/tmp/dxr/dv4guhjm38pst/containerd/containerd.sock module=libcontainerd pid=6942 sandbox.go:131: time="2024-02-05T14:29:09.464653555Z" level=debug msg="created containerd monitoring client" address=/tmp/dxr/dv4guhjm38pst/containerd/containerd.sock module=libcontainerd sandbox.go:131: time="2024-02-05T14:29:09.464857350Z" level=debug msg=

Check failure on line 583 in tests/bake.go

View workflow job for this annotation

GitHub Actions / test-integration (docker\+containerd, ./tests)

Failed: tests/TestIntegration/TestBakeUlimits/worker=docker+containerd

=== RUN TestIntegration/TestBakeUlimits/worker=docker+containerd === PAUSE TestIntegration/TestBakeUlimits/worker=docker+containerd === CONT TestIntegration/TestBakeUlimits/worker=docker+containerd bake.go:583: Error Trace: /src/tests/bake.go:583 /src/vendor/github.com/moby/buildkit/util/testutil/integration/run.go:93 /src/vendor/github.com/moby/buildkit/util/testutil/integration/run.go:207 Error: Received unexpected error: exit status 2 Test: TestIntegration/TestBakeUlimits/worker=docker+containerd Messages: panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xad1d36] goroutine 1 [running]: github.com/docker/cli/opts.(*UlimitOpt).Set(0x0, {0xc00060ec10?, 0xc00060f2f0?}) github.com/docker/cli@v25.0.1+incompatible/opts/ulimit.go:30 +0x36 github.com/docker/buildx/bake.toBuildOpt(0xc0004e6b60, 0x0) github.com/docker/buildx/bake/bake.go:1347 +0x19cc github.com/docker/buildx/bake.TargetsToBuildOpt(0xc0004c59b0, 0x11?) github.com/docker/buildx/bake/bake.go:1034 +0x245 github.com/docker/buildx/commands.runBake({0x269b1b0?, 0xc0001d72c0?}, {0x26aef40?, 0xc00017c800}, {0xc0001fb740, 0x0, 0x4}, {{0x38a7020, 0x0, 0x0}, ...}, ...) github.com/docker/buildx/commands/bake.go:180 +0x14a5 github.com/docker/buildx/commands.bakeCmd.func1(0xc000378000, {0xc0001fb740, 0x0, 0x4}) github.com/docker/buildx/commands/bake.go:266 +0x265 github.com/spf13/cobra.(*Command).execute(0xc000378000, {0xc000050200, 0x4, 0x4}) github.com/spf13/cobra@v1.8.0/command.go:983 +0xabc github.com/spf13/cobra.(*Command).ExecuteC(0xc000005800) github.com/spf13/cobra@v1.8.0/command.go:1115 +0x3ff github.com/spf13/cobra.(*Command).Execute(...) github.com/spf13/cobra@v1.8.0/command.go:1039 main.runStandalone(0x23524f9?) github.com/docker/buildx/cmd/buildx/main.go:42 +0x6e main.main() github.com/docker/buildx/cmd/buildx/main.go:62 +0xf4 sandbox.go:128: stdout: /usr/bin/dockerd sandbox.go:128: stderr: /usr/bin/dockerd sandbox.go:131: > startCmd 2024-02-05 14:29:10.667440218 +0000 UTC m=+36.667339497 /usr/bin/dockerd --data-root /tmp/integration409631414/dnke5rb1whlai/root --exec-root /tmp/dxr/dnke5rb1whlai --pidfile /tmp/integration409631414/dnke5rb1whlai/docker.pid --containerd-namespace dnke5rb1whlai --containerd-plugins-namespace dnke5rb1whlaip --host unix:///tmp/docker-integration/dnke5rb1whlai.sock --config-file /tmp/integration409631414/daemon.json --userland-proxy=false --tls=false --debug sandbox.go:131: time="2024-02-05T14:29:10.696337551Z" level=info msg="Starting up" sandbox.go:131: time="2024-02-05T14:29:10.697570966Z" level=warning msg="could not change group /tmp/docker-integration/dnke5rb1whlai.sock to docker: group docker not found" sandbox.go:131: time="2024-02-05T14:29:10.697706488Z" level=debug msg="Listener created for HTTP on unix (/tmp/docker-integration/dnke5rb1whlai.sock)" sandbox.go:131: time="2024-02-05T14:29:10.697722939Z" level=info msg="containerd not running, starting managed containerd" sandbox.go:131: time="2024-02-05T14:29:10.698262380Z" level=info msg="started new containerd process" address=/tmp/dxr/dnke5rb1whlai/containerd/containerd.sock module=libcontainerd pid=6661 sandbox.go:131: time="2024-02-05T14:29:10.698872485Z" level=debug msg="created containerd monitoring client" address=/tmp/dxr/dnke5rb1whlai/containerd/containerd.sock module=libcontainerd sandbox.go:131: time="2024-0

Check failure on line 583 in tests/bake.go

View workflow job for this annotation

GitHub Actions / test-integration (docker-container, ./tests)

Failed: tests/TestIntegration/TestBakeUlimits/worker=docker-container

=== RUN TestIntegration/TestBakeUlimits/worker=docker-container === PAUSE TestIntegration/TestBakeUlimits/worker=docker-container === CONT TestIntegration/TestBakeUlimits/worker=docker-container bake.go:583: Error Trace: /src/tests/bake.go:583 /src/vendor/github.com/moby/buildkit/util/testutil/integration/run.go:93 /src/vendor/github.com/moby/buildkit/util/testutil/integration/run.go:207 Error: Received unexpected error: exit status 2 Test: TestIntegration/TestBakeUlimits/worker=docker-container Messages: panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xad1d36] goroutine 1 [running]: github.com/docker/cli/opts.(*UlimitOpt).Set(0x0, {0xc000310480?, 0xc0003108e0?}) github.com/docker/cli@v25.0.1+incompatible/opts/ulimit.go:30 +0x36 github.com/docker/buildx/bake.toBuildOpt(0xc0003436c0, 0x0) github.com/docker/buildx/bake/bake.go:1347 +0x19cc github.com/docker/buildx/bake.TargetsToBuildOpt(0xc000371170, 0x11?) github.com/docker/buildx/bake/bake.go:1034 +0x245 github.com/docker/buildx/commands.runBake({0x269b1b0?, 0xc000512000?}, {0x26aef40?, 0xc00011b300}, {0xc00031d0c0, 0x0, 0x4}, {{0x38a7020, 0x0, 0x0}, ...}, ...) github.com/docker/buildx/commands/bake.go:180 +0x14a5 github.com/docker/buildx/commands.bakeCmd.func1(0xc0004ee000, {0xc00031d0c0, 0x0, 0x4}) github.com/docker/buildx/commands/bake.go:266 +0x265 github.com/spf13/cobra.(*Command).execute(0xc0004ee000, {0xc000050200, 0x4, 0x4}) github.com/spf13/cobra@v1.8.0/command.go:983 +0xabc github.com/spf13/cobra.(*Command).ExecuteC(0xc0004a1800) github.com/spf13/cobra@v1.8.0/command.go:1115 +0x3ff github.com/spf13/cobra.(*Command).Execute(...) github.com/spf13/cobra@v1.8.0/command.go:1039 main.runStandalone(0x23524f9?) github.com/docker/buildx/cmd/buildx/main.go:42 +0x6e main.main() github.com/docker/buildx/cmd/buildx/main.go:62 +0xf4 --- FAIL: TestIntegration/TestBakeUlimits/worker=docker-container (1.17s)

Check failure on line 583 in tests/bake.go

View workflow job for this annotation

GitHub Actions / test-integration (remote, ./tests)

Failed: tests/TestIntegration/TestBakeUlimits/worker=remote

=== RUN TestIntegration/TestBakeUlimits/worker=remote === PAUSE TestIntegration/TestBakeUlimits/worker=remote === CONT TestIntegration/TestBakeUlimits/worker=remote bake.go:583: Error Trace: /src/tests/bake.go:583 /src/vendor/github.com/moby/buildkit/util/testutil/integration/run.go:93 /src/vendor/github.com/moby/buildkit/util/testutil/integration/run.go:207 Error: Received unexpected error: exit status 2 Test: TestIntegration/TestBakeUlimits/worker=remote Messages: panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xad1d36] goroutine 1 [running]: github.com/docker/cli/opts.(*UlimitOpt).Set(0x0, {0xc0004a9d30?, 0xc000180720?}) github.com/docker/cli@v25.0.1+incompatible/opts/ulimit.go:30 +0x36 github.com/docker/buildx/bake.toBuildOpt(0xc000602680, 0x0) github.com/docker/buildx/bake/bake.go:1347 +0x19cc github.com/docker/buildx/bake.TargetsToBuildOpt(0xc0005f1ec0, 0x11?) github.com/docker/buildx/bake/bake.go:1034 +0x245 github.com/docker/buildx/commands.runBake({0x269b1b0?, 0xc000386780?}, {0x26aef40?, 0xc00035d300}, {0xc0003bfe80, 0x0, 0x4}, {{0x38a7020, 0x0, 0x0}, ...}, ...) github.com/docker/buildx/commands/bake.go:180 +0x14a5 github.com/docker/buildx/commands.bakeCmd.func1(0xc0005b0000, {0xc0003bfe80, 0x0, 0x4}) github.com/docker/buildx/commands/bake.go:266 +0x265 github.com/spf13/cobra.(*Command).execute(0xc0005b0000, {0xc0000ec140, 0x4, 0x4}) github.com/spf13/cobra@v1.8.0/command.go:983 +0xabc github.com/spf13/cobra.(*Command).ExecuteC(0xc00022f800) github.com/spf13/cobra@v1.8.0/command.go:1115 +0x3ff github.com/spf13/cobra.(*Command).Execute(...) github.com/spf13/cobra@v1.8.0/command.go:1039 main.runStandalone(0x23524f9?) github.com/docker/buildx/cmd/buildx/main.go:42 +0x6e main.main() github.com/docker/buildx/cmd/buildx/main.go:62 +0xf4 sandbox.go:128: stderr: /usr/bin/buildkitd --oci-worker=true --containerd-worker=false --oci-worker-gc=false --oci-worker-labels=org.mobyproject.buildkit.worker.sandbox=true --config=/tmp/bktest_config3301801092/buildkitd.toml --root /tmp/bktest_buildkitd2661707369 --addr unix:///tmp/bktest_buildkitd2661707369/buildkitd.sock --debug sandbox.go:131: > StartCmd 2024-02-05 14:28:27.580899022 +0000 UTC m=+10.372760264 /usr/bin/buildkitd --oci-worker=true --containerd-worker=false --oci-worker-gc=false --oci-worker-labels=org.mobyproject.buildkit.worker.sandbox=true --config=/tmp/bktest_config3301801092/buildkitd.toml --root /tmp/bktest_buildkitd2661707369 --addr unix:///tmp/bktest_buildkitd2661707369/buildkitd.sock --debug sandbox.go:131: time="2024-02-05T14:28:27Z" level=info msg="auto snapshotter: using overlayfs" sandbox.go:131: time="2024-02-05T14:28:27Z" level=warning msg="using host network as the default" sandbox.go:131: time="2024-02-05T14:28:27Z" level=info msg="found worker \"vmvt43zrd2ggdoqjkjpdq6qn7\", labels=map[org.mobyproject.buildkit.worker.executor:oci org.mobyproject.buildkit.worker.hostname:43418b3f3ed3 org.mobyproject.buildkit.worker.network:host org.mobyproject.buildkit.worker.oci.process-mode:sandbox org.mobyproject.buildkit.worker.sandbox:true org.mobyproject.buildkit.worker.selinux.enabled:false org.mobyproject.buildkit.worker.snapshotter:overlayfs], platforms=[linux/amd64 linux/amd64/v2 linux/amd64/v3 linux/arm64 linux/riscv64 linux/ppc64le linux/s390x linux/386 linux/mips64le linux/mips64 linux/arm/v7 linux/arm/v6]" san

dt, err := os.ReadFile(filepath.Join(dirDest, "ulimit"))
require.NoError(t, err)
require.Contains(t, string(dt), `1024`)
}

0 comments on commit 0bdee7c

Please sign in to comment.