Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bake: ulimits and shm-size support #2242

Merged
merged 4 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions bake/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/docker/buildx/util/platformutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/config"
dockeropts "github.com/docker/cli/opts"
hcl "github.com/hashicorp/hcl/v2"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb"
Expand Down Expand Up @@ -699,6 +700,8 @@ type Target struct {
NoCache *bool `json:"no-cache,omitempty" hcl:"no-cache,optional" cty:"no-cache"`
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 @@ -721,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 @@ -809,6 +813,12 @@ func (t *Target) Merge(t2 *Target) {
if t2.NoCacheFilter != nil { // merge
t.NoCacheFilter = append(t.NoCacheFilter, t2.NoCacheFilter...)
}
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 @@ -873,6 +883,10 @@ func (t *Target) AddOverrides(overrides map[string]Override) error {
t.NoCache = &noCache
case "no-cache-filter":
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 @@ -1233,6 +1247,12 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
if t.NetworkMode != nil {
networkMode = *t.NetworkMode
}
shmSize := new(dockeropts.MemBytes)
if t.ShmSize != nil {
if err := shmSize.Set(*t.ShmSize); err != nil {
return nil, errors.Errorf("invalid value %s for membytes key shm-size", *t.ShmSize)
}
}

bo := &build.Options{
Inputs: bi,
Expand All @@ -1244,6 +1264,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
Pull: pull,
NetworkMode: networkMode,
Linked: t.linked,
ShmSize: *shmSize,
}

platforms, err := platformutil.Parse(t.Platforms)
Expand Down Expand Up @@ -1321,6 +1342,14 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
return nil, err
}

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

return bo, nil
}

Expand Down
10 changes: 10 additions & 0 deletions bake/bake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ target "webDEP" {
VAR_BOTH = "webDEP"
}
no-cache = true
shm-size = "128m"
ulimits = ["nofile=1024:1024"]
}

target "webapp" {
Expand All @@ -45,6 +47,8 @@ target "webapp" {
require.Equal(t, ".", *m["webapp"].Context)
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 Expand Up @@ -129,6 +133,12 @@ target "webapp" {
require.Equal(t, []string{"webapp"}, g["default"].Targets)
})

t.Run("ShmSizeOverride", func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.shm-size=256m"}, nil)
require.NoError(t, err)
require.Equal(t, "256m", *m["webapp"].ShmSize)
})

t.Run("PullOverride", func(t *testing.T) {
t.Parallel()
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.pull=false"}, nil)
Expand Down
23 changes: 23 additions & 0 deletions bake/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package bake

import (
"context"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/compose-spec/compose-go/v2/dotenv"
"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 @@ -86,6 +89,24 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf
}
}

var shmSize *string
if s.Build.ShmSize > 0 {
shmSizeBytes := dockeropts.MemBytes(s.Build.ShmSize)
shmSizeStr := shmSizeBytes.String()
shmSize = &shmSizeStr
}

var ulimits []string
if s.Build.Ulimits != nil {
for n, u := range s.Build.Ulimits {
ulimit, err := units.ParseUlimit(fmt.Sprintf("%s=%d:%d", n, u.Soft, u.Hard))
if err != nil {
return nil, err
}
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 @@ -122,6 +143,8 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf
CacheTo: s.Build.CacheTo,
NetworkMode: &s.Build.Network,
Secrets: secrets,
ShmSize: shmSize,
Ulimits: ulimits,
}
if err = t.composeExtTarget(s.Build.Extensions); err != nil {
return nil, err
Expand Down
7 changes: 7 additions & 0 deletions bake/compose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,11 @@ services:
args:
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 @@ -332,6 +337,8 @@ services:
require.Equal(t, []string{"linux/arm64"}, c.Targets[1].Platforms)
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
2 changes: 1 addition & 1 deletion commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions, debugConfig *debug.D

flags.StringArrayVar(&options.secrets, "secret", []string{}, `Secret to expose to the build (format: "id=mysecret[,src=/local/secret]")`)

flags.Var(&options.shmSize, "shm-size", `Size of "/dev/shm"`)
flags.Var(&options.shmSize, "shm-size", `Shared memory size for build containers`)

flags.StringArrayVar(&options.ssh, "ssh", []string{}, `SSH agent socket or keys to expose to the build (format: "default|<id>[=<socket>|<key>[,<key>]]")`)

Expand Down
53 changes: 52 additions & 1 deletion docs/bake-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ target "webapp" {
The following table shows the complete list of attributes that you can assign to a target:

| Name | Type | Description |
| ----------------------------------------------- | ------- | -------------------------------------------------------------------- |
|-------------------------------------------------|---------|----------------------------------------------------------------------|
| [`args`](#targetargs) | Map | Build arguments |
| [`annotations`](#targetannotations) | List | Exporter annotations |
| [`attest`](#targetattest) | List | Build attestations |
Expand All @@ -233,9 +233,11 @@ The following table shows the complete list of attributes that you can assign to
| [`platforms`](#targetplatforms) | List | Target platforms |
| [`pull`](#targetpull) | Boolean | Always pull images |
| [`secret`](#targetsecret) | List | Secrets to expose to the build |
| [`shm-size`](#targetshm-size) | List | Size of `/dev/shm` |
| [`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 @@ -832,6 +834,29 @@ RUN --mount=type=secret,id=KUBECONFIG \
KUBECONFIG=$(cat /run/secrets/KUBECONFIG) helm upgrade --install
```

### `target.shm-size`
crazy-max marked this conversation as resolved.
Show resolved Hide resolved

Sets the size of the shared memory allocated for build containers when using
`RUN` instructions.

The format is `<number><unit>`. `number` must be greater than `0`. Unit is
optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g`
(gigabytes). If you omit the unit, the system uses bytes.

This is the same as the `--shm-size` flag for `docker build`.

```hcl
target "default" {
shm-size = "128m"
}
```

> **Note**
>
> In most cases, it is recommended to let the builder automatically determine
> the appropriate configurations. Manual adjustments should only be considered
> when specific performance tuning is required for complex build scenarios.

### `target.ssh`

Defines SSH agent sockets or keys to expose to the build.
Expand Down Expand Up @@ -878,6 +903,32 @@ target "default" {
}
```

### `target.ulimits`

Ulimits overrides the default ulimits of build's containers when using `RUN`
instructions and 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.

> **Note**
>
> In most cases, it is recommended to let the builder automatically determine
> the appropriate configurations. Manual adjustments should only be considered
> when specific performance tuning is required for complex build scenarios.

## Group

Groups allow you to invoke multiple builds (targets) at once.
Expand Down
22 changes: 19 additions & 3 deletions docs/reference/buildx_build.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Start a build
| [`--sbom`](#sbom) | `string` | | Shorthand for `--attest=type=sbom` |
| [`--secret`](#secret) | `stringArray` | | Secret to expose to the build (format: `id=mysecret[,src=/local/secret]`) |
| `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) (EXPERIMENTAL) |
| [`--shm-size`](#shm-size) | `bytes` | `0` | Size of `/dev/shm` |
| [`--shm-size`](#shm-size) | `bytes` | `0` | Shared memory size for build containers |
| [`--ssh`](#ssh) | `stringArray` | | SSH agent socket or keys to expose to the build (format: `default\|<id>[=<socket>\|<key>[,<key>]]`) |
| [`-t`](https://docs.docker.com/reference/cli/docker/image/build/#tag), [`--tag`](https://docs.docker.com/reference/cli/docker/image/build/#tag) | `stringArray` | | Name and optionally a tag (format: `name:tag`) |
| [`--target`](https://docs.docker.com/reference/cli/docker/image/build/#target) | `string` | | Set the target build stage to build |
Expand Down Expand Up @@ -653,12 +653,21 @@ RUN --mount=type=bind,target=. \
$ SECRET_TOKEN=token docker buildx build --secret id=SECRET_TOKEN .
```

### <a name="shm-size"></a> Size of /dev/shm (--shm-size)
### <a name="shm-size"></a> Shared memory size for build containers (--shm-size)

Sets the size of the shared memory allocated for build containers when using
`RUN` instructions.

The format is `<number><unit>`. `number` must be greater than `0`. Unit is
optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g`
(gigabytes). If you omit the unit, the system uses bytes.

> **Note**
crazy-max marked this conversation as resolved.
Show resolved Hide resolved
>
> In most cases, it is recommended to let the builder automatically determine
> the appropriate configurations. Manual adjustments should only be considered
> when specific performance tuning is required for complex build scenarios.

### <a name="ssh"></a> SSH agent socket or keys to expose to the build (--ssh)

```text
Expand Down Expand Up @@ -692,7 +701,8 @@ $ docker buildx build --ssh default=$SSH_AUTH_SOCK .

### <a name="ulimit"></a> Set ulimits (--ulimit)

`--ulimit` is specified with a soft and hard limit as such:
`--ulimit` overrides the default ulimits of build's containers when using `RUN`
instructions and are specified with a soft and hard limit as such:
`<type>=<soft limit>[:<hard limit>]`, for example:

```console
Expand All @@ -704,3 +714,9 @@ $ docker buildx build --ulimit nofile=1024:1024 .
> If you don't provide a `hard limit`, the `soft limit` is used
> for both values. If no `ulimits` are set, they're inherited from
> the default `ulimits` set on the daemon.

> **Note**
>
> In most cases, it is recommended to let the builder automatically determine
> the appropriate configurations. Manual adjustments should only be considered
> when specific performance tuning is required for complex build scenarios.
2 changes: 1 addition & 1 deletion docs/reference/buildx_debug_build.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Start a build
| `--sbom` | `string` | | Shorthand for `--attest=type=sbom` |
| `--secret` | `stringArray` | | Secret to expose to the build (format: `id=mysecret[,src=/local/secret]`) |
| `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) (EXPERIMENTAL) |
| `--shm-size` | `bytes` | `0` | Size of `/dev/shm` |
| `--shm-size` | `bytes` | `0` | Shared memory size for build containers |
| `--ssh` | `stringArray` | | SSH agent socket or keys to expose to the build (format: `default\|<id>[=<socket>\|<key>[,<key>]]`) |
| [`-t`](https://docs.docker.com/reference/cli/docker/image/build/#tag), [`--tag`](https://docs.docker.com/reference/cli/docker/image/build/#tag) | `stringArray` | | Name and optionally a tag (format: `name:tag`) |
| [`--target`](https://docs.docker.com/reference/cli/docker/image/build/#target) | `string` | | Set the target build stage to build |
Expand Down
Loading
Loading