Compare commits

..

27 Commits

Author SHA1 Message Date
Tõnis Tiigi
c967f1d570 Merge pull request #124 from tiborvass/update-docs
Update docs
2019-08-01 16:41:26 -07:00
Tibor Vass
be3efc979b docs: add documentation for --buildkitd-flags, --config, --driver-opt on create
Signed-off-by: Tibor Vass <tibor@docker.com>
2019-08-01 16:15:11 -07:00
Tibor Vass
5c5f54c6d6 docs: Update install instructions with Docker CE 19.03
Signed-off-by: Tibor Vass <tibor@docker.com>
2019-08-01 15:23:02 -07:00
Tibor Vass
6f8f04e1f8 Merge pull request #122 from tonistiigi/custom-image
driver: allow setting driver opts
2019-08-01 11:41:49 -07:00
Tonis Tiigi
afd821010d docker-container: allow setting custom buildkit image
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2019-07-31 22:46:37 -07:00
Tonis Tiigi
bcc882cbf1 docker-container: allow using host network
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2019-07-31 17:42:49 -07:00
Tonis Tiigi
75b80c277f driver: allow setting driver opts
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2019-07-31 17:25:25 -07:00
Tibor Vass
096d1befc9 Merge pull request #104 from tonistiigi/entitlements
build: add allowed entitlements
2019-07-31 15:36:13 -07:00
Tibor Vass
2bf6187a88 Merge pull request #121 from tonistiigi/config
driver: allow setting buildkit config file
2019-07-31 15:21:17 -07:00
Tonis Tiigi
8ed8795268 driver: allow setting buildkit config file
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Co-Authored-By: Tibor Vass <tiborvass@users.noreply.github.com>
2019-07-31 15:08:26 -07:00
Tõnis Tiigi
6e32ea3418 Merge pull request #118 from tiborvass/bake-no-cache-pull
bake: honor --no-cache and --pull
2019-07-31 10:59:59 -07:00
Tibor Vass
8b2171f78a bake: honor --no-cache and --pull
Signed-off-by: Tibor Vass <tibor@docker.com>
2019-07-30 19:39:01 -07:00
Tibor Vass
92f1234aaa Merge pull request #116 from tonistiigi/build-arg-default
build: load default build args from env
2019-07-30 19:20:09 -07:00
Tibor Vass
73645c8348 Merge pull request #117 from tonistiigi/compose-env
bake: replace env in compose files
2019-07-30 19:14:21 -07:00
Tonis Tiigi
662c0768cb bake: replace env in compose files
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2019-07-30 16:44:05 -07:00
Tonis Tiigi
43150ef849 build: load default build args from env
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2019-07-30 16:32:36 -07:00
Tibor Vass
3f18b659a0 Merge pull request #102 from tonistiigi/buildkitd-flags
driver: allow configuring buildkitd flags
2019-07-09 17:27:17 -07:00
Tonis Tiigi
6b81b0bed6 build: add allowed entitlements
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2019-07-08 15:59:53 -07:00
Tonis Tiigi
f0af89a204 driver: allow configuring buildkitd flags
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2019-07-08 15:29:43 -07:00
Tõnis Tiigi
550c2b9042 Merge pull request #100 from FernandoMiguel/patch-1
add chmod
2019-07-06 12:38:08 -07:00
Fernando Miguel
c8cda08209 add chmod 2019-07-05 12:14:40 +01:00
Tõnis Tiigi
2b03339235 Merge pull request #93 from zelahi/enable-fossa-scan
[TAR-853] ADDED .fossa file for fossa scans
2019-06-17 09:21:16 -07:00
zelahi
6e1fd0eab6 ADDED .fossa file for fossa scans 2019-06-14 10:49:12 -07:00
Tõnis Tiigi
5336e74bd4 Merge pull request #89 from khs1994/master
Fix Dockerfile format
2019-06-05 13:56:29 -07:00
Tõnis Tiigi
afeaed790f Merge pull request #86 from AkihiroSuda/driver-ls
Put driver names to create --help
2019-06-05 13:55:44 -07:00
khs1994
aed531a8a9 Fix Dockerfile format
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-06-04 17:43:39 +08:00
Akihiro Suda
eee78c6c10 Put driver names to create --help
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2019-06-02 00:02:20 +09:00
19 changed files with 310 additions and 82 deletions

14
.fossa.yml Executable file
View File

@@ -0,0 +1,14 @@
# Generated by FOSSA CLI (https://github.com/fossas/fossa-cli)
# Visit https://fossa.com to learn more
version: 2
cli:
server: https://app.fossa.io
fetcher: custom
project: git@github.com:docker/buildx
analyze:
modules:
- name: github.com/docker/buildx/cmd/buildx
type: go
target: github.com/docker/buildx/cmd/buildx
path: cmd/buildx

View File

@@ -41,30 +41,21 @@ _buildx is Tech Preview_
# Installing # Installing
Using `buildx` as a docker CLI plugin requires using Docker 19.03.0 beta. A limited set of functionality works with older versions of Docker when invoking the binary directly. Using `buildx` as a docker CLI plugin requires using Docker 19.03. A limited set of functionality works with older versions of Docker when invoking the binary directly.
### Docker Desktop (Edge) ### Docker CE
`buildx` is included with Docker Desktop Edge builds since 19.03.0-beta3. `buildx` comes bundled with Docker CE starting with 19.03, but requires experimental mode to be enabled on the Docker CLI.
To enable it, `"experimental": "enabled"` can be added to the CLI configuration file `~/.docker/config.json`. An alternative is to set the `DOCKER_CLI_EXPERIMENTAL=enabled` environment variable.
For more information see https://docs.docker.com/docker-for-mac/edge-release-notes/
### Docker CE nightly builds
`buildx` comes bundled with the Docker CE nightly builds.
- Mac: https://download.docker.com/mac/static/nightly/
- Linux:
```
$ # uncomment next line to uninstall previous Docker CE installation if present
$ # apt purge docker-ce docker-ce-cli
$ curl -fsSL https://get.docker.com/ -o docker-install.sh
$ CHANNEL=nightly sh docker-install.sh
```
### Binary release ### Binary release
Download the latest binary release from https://github.com/docker/buildx/releases/latest and copy it to `~/.docker/cli-plugins` folder with name `docker-buildx`. Download the latest binary release from https://github.com/docker/buildx/releases/latest and copy it to `~/.docker/cli-plugins` folder with name `docker-buildx`.
Change the permission to execute:
```sh
chmod a+x ~/.docker/cli-plugins/docker-buildx
```
After installing you can run `docker buildx` to see the new commands. After installing you can run `docker buildx` to see the new commands.
@@ -142,7 +133,7 @@ $ docker buildx build --platform linux/amd64,linux/arm64 .
Finally, depending on your project, the language that you use may have good support for cross-compilation. In that case, multi-stage builds in Dockerfiles can be effectively used to build binaries for the platform specified with `--platform` using the native architecture of the build node. List of build arguments like `BUILDPLATFORM` and `TARGETPLATFORM` are available automatically inside your Dockerfile and can be leveraged by the processes running as part of your build. Finally, depending on your project, the language that you use may have good support for cross-compilation. In that case, multi-stage builds in Dockerfiles can be effectively used to build binaries for the platform specified with `--platform` using the native architecture of the build node. List of build arguments like `BUILDPLATFORM` and `TARGETPLATFORM` are available automatically inside your Dockerfile and can be leveraged by the processes running as part of your build.
``` ```
FROM --platform $BUILDPLATFORM golang:alpine AS build FROM --platform=$BUILDPLATFORM golang:alpine AS build
ARG TARGETPLATFORM ARG TARGETPLATFORM
ARG BUILDPLATFORM ARG BUILDPLATFORM
RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" > /log RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" > /log
@@ -340,21 +331,16 @@ Options:
| Flag | Description | | Flag | Description |
| --- | --- | | --- | --- |
| --append | Append a node to builder instead of changing it | --append | Append a node to builder instead of changing it
| --driver string | Driver to use (eg. docker-container) | --buildkitd-flags string | Flags for buildkitd daemon
| --leave | Remove a node from builder instead of changing it | --config string | BuildKit config file
| --name string | Builder instance name | --driver string | Driver to use (eg. docker-container)
| --node string | Create/modify node with given name | --driver-opt stringArray | Options for the driver
| --platform stringArray | Fixed platforms for current node | --leave | Remove a node from builder instead of changing it
| --use | Set the current builder instance | --name string | Builder instance name
| --node string | Create/modify node with given name
#### `--driver DRIVER` | --platform stringArray | Fixed platforms for current node
| --use | Set the current builder instance
Sets the builder driver to be used. There are two available drivers, each have their own specificities.
- `docker` - Uses the builder that is built into the docker daemon. With this driver, the [`--load`](#--load) flag is implied by default on `buildx build`. However, building multi-platform images or exporting cache is not currently supported.
- `docker-container` - Uses a buildkit container that will be spawned via docker. With this driver, both building multi-platform images and exporting cache are supported. However, images built will not automatically appear in `docker images` (see [`build --load`](#--load)).
#### `--append` #### `--append`
@@ -368,6 +354,41 @@ $ docker buildx create --name eager_beaver --append mycontext2
eager_beaver eager_beaver
``` ```
#### `--buildkitd-flags FLAGS`
Adds flags when starting the buildkitd daemon. They take precedence over the configuration file specified by `--config`. See `buildkitd --help` for the available flags.
Example:
```
--buildkitd-flags '--debug --debugaddr 0.0.0.0:6666'
```
#### `--config FILE`
Specifies the configuration file for the buildkitd daemon to use. The configuration can be overridden by `--buildkitd-flags`. See an [example buildkitd configuration file](https://github.com/moby/buildkit/blob/master/docs/buildkitd.toml.md).
#### `--driver DRIVER`
Sets the builder driver to be used. There are two available drivers, each have their own specificities.
- `docker` - Uses the builder that is built into the docker daemon. With this driver, the [`--load`](#--load) flag is implied by default on `buildx build`. However, building multi-platform images or exporting cache is not currently supported.
- `docker-container` - Uses a buildkit container that will be spawned via docker. With this driver, both building multi-platform images and exporting cache are supported. However, images built will not automatically appear in `docker images` (see [`build --load`](#--load)).
#### `--driver-opt OPTIONS`
Passes additional driver-specific options. Details for each driver:
- `docker` - No driver options
- `docker-container`
- `image` - Sets the container image to be used for running buildkit.
- `network` - Sets the network mode for running the buildkit container.
- Example:
```
--driver docker-container --driver-opt image=moby/buildkit:master,network=host
```
#### `--leave` #### `--leave`
Changes the action of the command to removes a node from a builder. The builder needs to be specified with `--name` and node that is removed is set with `--node`. Changes the action of the command to removes a node from a builder. The builder needs to be specified with `--name` and node that is removed is set with `--node`.

View File

@@ -248,10 +248,10 @@ func (t *Target) normalize() {
t.Outputs = removeDupes(t.Outputs) t.Outputs = removeDupes(t.Outputs)
} }
func TargetsToBuildOpt(m map[string]Target) (map[string]build.Options, error) { func TargetsToBuildOpt(m map[string]Target, noCache, pull bool) (map[string]build.Options, error) {
m2 := make(map[string]build.Options, len(m)) m2 := make(map[string]build.Options, len(m))
for k, v := range m { for k, v := range m {
bo, err := toBuildOpt(v) bo, err := toBuildOpt(v, noCache, pull)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -260,7 +260,7 @@ func TargetsToBuildOpt(m map[string]Target) (map[string]build.Options, error) {
return m2, nil return m2, nil
} }
func toBuildOpt(t Target) (*build.Options, error) { func toBuildOpt(t Target, noCache, pull bool) (*build.Options, error) {
if v := t.Context; v != nil && *v == "-" { if v := t.Context; v != nil && *v == "-" {
return nil, errors.Errorf("context from stdin not allowed in bake") return nil, errors.Errorf("context from stdin not allowed in bake")
} }
@@ -289,6 +289,8 @@ func toBuildOpt(t Target) (*build.Options, error) {
Tags: t.Tags, Tags: t.Tags,
BuildArgs: t.Args, BuildArgs: t.Args,
Labels: t.Labels, Labels: t.Labels,
NoCache: noCache,
Pull: pull,
} }
platforms, err := platformutil.Parse(t.Platforms) platforms, err := platformutil.Parse(t.Platforms)

View File

@@ -2,7 +2,9 @@ package bake
import ( import (
"fmt" "fmt"
"os"
"reflect" "reflect"
"strings"
"github.com/docker/cli/cli/compose/loader" "github.com/docker/cli/cli/compose/loader"
composetypes "github.com/docker/cli/cli/compose/types" composetypes "github.com/docker/cli/cli/compose/types"
@@ -19,9 +21,22 @@ func parseCompose(dt []byte) (*composetypes.Config, error) {
Config: parsed, Config: parsed,
}, },
}, },
Environment: envMap(os.Environ()),
}) })
} }
func envMap(env []string) map[string]string {
result := make(map[string]string, len(env))
for _, s := range env {
kv := strings.SplitN(s, "=", 2)
if len(kv) != 2 {
continue
}
result[kv[0]] = kv[1]
}
return result
}
func ParseCompose(dt []byte) (*Config, error) { func ParseCompose(dt []byte) (*Config, error) {
cfg, err := parseCompose(dt) cfg, err := parseCompose(dt)
if err != nil { if err != nil {
@@ -86,6 +101,8 @@ func toMap(in composetypes.MappingWithEquals) map[string]string {
for k, v := range in { for k, v := range in {
if v != nil { if v != nil {
m[k] = *v m[k] = *v
} else {
m[k] = os.Getenv(k)
} }
} }
return m return m

View File

@@ -24,6 +24,7 @@ import (
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
"github.com/moby/buildkit/session" "github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/upload/uploadprovider" "github.com/moby/buildkit/session/upload/uploadprovider"
"github.com/moby/buildkit/util/entitlements"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
@@ -55,6 +56,7 @@ type Options struct {
CacheFrom []client.CacheOptionsEntry CacheFrom []client.CacheOptionsEntry
CacheTo []client.CacheOptionsEntry CacheTo []client.CacheOptionsEntry
Allow []entitlements.Entitlement
// DockerTarget // DockerTarget
} }
@@ -324,11 +326,12 @@ func toSolveOpt(d driver.Driver, multiDriver bool, opt Options, dl dockerLoadCal
} }
so := client.SolveOpt{ so := client.SolveOpt{
Frontend: "dockerfile.v0", Frontend: "dockerfile.v0",
FrontendAttrs: map[string]string{}, FrontendAttrs: map[string]string{},
LocalDirs: map[string]string{}, LocalDirs: map[string]string{},
CacheExports: opt.CacheTo, CacheExports: opt.CacheTo,
CacheImports: opt.CacheFrom, CacheImports: opt.CacheFrom,
AllowedEntitlements: opt.Allow,
} }
if multiDriver { if multiDriver {
@@ -454,6 +457,7 @@ func toSolveOpt(d driver.Driver, multiDriver bool, opt Options, dl dockerLoadCal
switch opt.NetworkMode { switch opt.NetworkMode {
case "host", "none": case "host", "none":
so.FrontendAttrs["force-network-mode"] = opt.NetworkMode so.FrontendAttrs["force-network-mode"] = opt.NetworkMode
so.AllowedEntitlements = append(so.AllowedEntitlements, entitlements.EntitlementNetworkHost)
case "", "default": case "", "default":
default: default:
return nil, nil, errors.Errorf("network mode %q not supported by buildkit", opt.NetworkMode) return nil, nil, errors.Errorf("network mode %q not supported by buildkit", opt.NetworkMode)

21
build/entitlements.go Normal file
View File

@@ -0,0 +1,21 @@
package build
import (
"github.com/moby/buildkit/util/entitlements"
"github.com/pkg/errors"
)
func ParseEntitlements(in []string) ([]entitlements.Entitlement, error) {
out := make([]entitlements.Entitlement, 0, len(in))
for _, v := range in {
switch v {
case "security.insecure":
out = append(out, entitlements.EntitlementSecurityInsecure)
case "network.host":
out = append(out, entitlements.EntitlementNetworkHost)
default:
return nil, errors.Errorf("invalid entitlement: %v", v)
}
}
return out, nil
}

View File

@@ -51,7 +51,7 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) error {
return nil return nil
} }
bo, err := bake.TargetsToBuildOpt(m) bo, err := bake.TargetsToBuildOpt(m, in.noCache, in.pull)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -44,6 +44,8 @@ type buildOptions struct {
squash bool squash bool
quiet bool quiet bool
allow []string
// hidden // hidden
// untrusted bool // untrusted bool
// ulimits *opts.UlimitOpt // ulimits *opts.UlimitOpt
@@ -84,8 +86,8 @@ func runBuild(dockerCli command.Cli, in buildOptions) error {
InStream: os.Stdin, InStream: os.Stdin,
}, },
Tags: in.tags, Tags: in.tags,
Labels: listToMap(in.labels), Labels: listToMap(in.labels, false),
BuildArgs: listToMap(in.buildArgs), BuildArgs: listToMap(in.buildArgs, true),
Pull: in.pull, Pull: in.pull,
NoCache: in.noCache, NoCache: in.noCache,
Target: in.target, Target: in.target,
@@ -167,6 +169,12 @@ func runBuild(dockerCli command.Cli, in buildOptions) error {
} }
opts.CacheTo = cacheExports opts.CacheTo = cacheExports
allow, err := build.ParseEntitlements(in.allow)
if err != nil {
return err
}
opts.Allow = allow
return buildTargets(ctx, dockerCli, map[string]build.Options{"default": opts}, in.progress) return buildTargets(ctx, dockerCli, map[string]build.Options{"default": opts}, in.progress)
} }
@@ -214,6 +222,8 @@ func buildCmd(dockerCli command.Cli) *cobra.Command {
flags.StringVar(&options.target, "target", "", "Set the target build stage to build.") flags.StringVar(&options.target, "target", "", "Set the target build stage to build.")
flags.StringSliceVar(&options.allow, "allow", []string{}, "Allow extra privileged entitlement, e.g. network.host, security.insecure")
// not implemented // not implemented
flags.BoolVarP(&options.quiet, "quiet", "q", false, "Suppress the build output and print image ID on success") flags.BoolVarP(&options.quiet, "quiet", "q", false, "Suppress the build output and print image ID on success")
flags.StringVar(&options.networkMode, "network", "default", "Set the networking mode for the RUN instructions during build") flags.StringVar(&options.networkMode, "network", "default", "Set the networking mode for the RUN instructions during build")
@@ -282,12 +292,16 @@ func commonFlags(options *commonOptions, flags *pflag.FlagSet) {
flags.BoolVar(&options.pull, "pull", false, "Always attempt to pull a newer version of the image") flags.BoolVar(&options.pull, "pull", false, "Always attempt to pull a newer version of the image")
} }
func listToMap(values []string) map[string]string { func listToMap(values []string, defaultEnv bool) map[string]string {
result := make(map[string]string, len(values)) result := make(map[string]string, len(values))
for _, value := range values { for _, value := range values {
kv := strings.SplitN(value, "=", 2) kv := strings.SplitN(value, "=", 2)
if len(kv) == 1 { if len(kv) == 1 {
result[kv[0]] = "" if defaultEnv {
result[kv[0]] = os.Getenv(kv[0])
} else {
result[kv[0]] = ""
}
} else { } else {
result[kv[0]] = kv[1] result[kv[0]] = kv[1]
} }

View File

@@ -1,13 +1,16 @@
package commands package commands
import ( import (
"encoding/csv"
"fmt" "fmt"
"os" "os"
"strings"
"github.com/docker/buildx/driver" "github.com/docker/buildx/driver"
"github.com/docker/buildx/store" "github.com/docker/buildx/store"
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/google/shlex"
"github.com/moby/buildkit/util/appcontext" "github.com/moby/buildkit/util/appcontext"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@@ -22,6 +25,9 @@ type createOptions struct {
actionAppend bool actionAppend bool
actionLeave bool actionLeave bool
use bool use bool
flags string
configFile string
driverOpts []string
// upgrade bool // perform upgrade of the driver // upgrade bool // perform upgrade of the driver
} }
@@ -107,6 +113,14 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
ng.Driver = driverName ng.Driver = driverName
} }
var flags []string
if in.flags != "" {
flags, err = shlex.Split(in.flags)
if err != nil {
return errors.Wrap(err, "failed to parse buildkit flags")
}
}
var ep string var ep string
if in.actionLeave { if in.actionLeave {
if err := ng.Leave(in.nodeName); err != nil { if err := ng.Leave(in.nodeName); err != nil {
@@ -128,7 +142,11 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
return err return err
} }
} }
if err := ng.Update(in.nodeName, ep, in.platform, len(args) > 0, in.actionAppend); err != nil { m, err := csvToMap(in.driverOpts)
if err != nil {
return err
}
if err := ng.Update(in.nodeName, ep, in.platform, len(args) > 0, in.actionAppend, flags, in.configFile, m); err != nil {
return err return err
} }
} }
@@ -154,6 +172,11 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
func createCmd(dockerCli command.Cli) *cobra.Command { func createCmd(dockerCli command.Cli) *cobra.Command {
var options createOptions var options createOptions
var drivers []string
for s := range driver.GetFactories() {
drivers = append(drivers, s)
}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "create [OPTIONS] [CONTEXT|ENDPOINT]", Use: "create [OPTIONS] [CONTEXT|ENDPOINT]",
Short: "Create a new builder instance", Short: "Create a new builder instance",
@@ -166,9 +189,12 @@ func createCmd(dockerCli command.Cli) *cobra.Command {
flags := cmd.Flags() flags := cmd.Flags()
flags.StringVar(&options.name, "name", "", "Builder instance name") flags.StringVar(&options.name, "name", "", "Builder instance name")
flags.StringVar(&options.driver, "driver", "", "Driver to use (eg. docker-container)") flags.StringVar(&options.driver, "driver", "", fmt.Sprintf("Driver to use (available: %v)", drivers))
flags.StringVar(&options.nodeName, "node", "", "Create/modify node with given name") flags.StringVar(&options.nodeName, "node", "", "Create/modify node with given name")
flags.StringVar(&options.flags, "buildkitd-flags", "", "Flags for buildkitd daemon")
flags.StringVar(&options.configFile, "config", "", "BuildKit config file")
flags.StringArrayVar(&options.platform, "platform", []string{}, "Fixed platforms for current node") flags.StringArrayVar(&options.platform, "platform", []string{}, "Fixed platforms for current node")
flags.StringArrayVar(&options.driverOpts, "driver-opt", []string{}, "Options for the driver")
flags.BoolVar(&options.actionAppend, "append", false, "Append a node to builder instead of changing it") flags.BoolVar(&options.actionAppend, "append", false, "Append a node to builder instead of changing it")
flags.BoolVar(&options.actionLeave, "leave", false, "Remove a node from builder instead of changing it") flags.BoolVar(&options.actionLeave, "leave", false, "Remove a node from builder instead of changing it")
@@ -178,3 +204,22 @@ func createCmd(dockerCli command.Cli) *cobra.Command {
return cmd return cmd
} }
func csvToMap(in []string) (map[string]string, error) {
m := make(map[string]string, len(in))
for _, s := range in {
csvReader := csv.NewReader(strings.NewReader(s))
fields, err := csvReader.Read()
if err != nil {
return nil, err
}
for _, v := range fields {
p := strings.SplitN(v, "=", 2)
if len(p) != 2 {
return nil, errors.Errorf("invalid value %q, expecting k=v", v)
}
m[p[0]] = p[1]
}
}
return m, nil
}

View File

@@ -114,6 +114,9 @@ func runInspect(dockerCli command.Cli, in inspectOptions, args []string) error {
fmt.Fprintf(w, "Error:\t%s\n", err.Error()) fmt.Fprintf(w, "Error:\t%s\n", err.Error())
} else { } else {
fmt.Fprintf(w, "Status:\t%s\n", ngi.drivers[i].info.Status) fmt.Fprintf(w, "Status:\t%s\n", ngi.drivers[i].info.Status)
if len(n.Flags) > 0 {
fmt.Fprintf(w, "Flags:\t%s\n", strings.Join(n.Flags, " "))
}
fmt.Fprintf(w, "Platforms:\t%s\n", strings.Join(platformutil.Format(platformutil.Dedupe(append(n.Platforms, ngi.drivers[i].platforms...))), ", ")) fmt.Fprintf(w, "Platforms:\t%s\n", strings.Join(platformutil.Format(platformutil.Dedupe(append(n.Platforms, ngi.drivers[i].platforms...))), ", "))
} }
} }

View File

@@ -174,7 +174,7 @@ func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.N
// TODO: replace the following line with dockerclient.WithAPIVersionNegotiation option in clientForEndpoint // TODO: replace the following line with dockerclient.WithAPIVersionNegotiation option in clientForEndpoint
dockerapi.NegotiateAPIVersion(ctx) dockerapi.NegotiateAPIVersion(ctx)
d, err := driver.GetDriver(ctx, "buildx_buildkit_"+n.Name, f, dockerapi) d, err := driver.GetDriver(ctx, "buildx_buildkit_"+n.Name, f, dockerapi, n.Flags, n.ConfigFile, n.DriverOpts)
if err != nil { if err != nil {
di.Err = err di.Err = err
return nil return nil
@@ -251,7 +251,7 @@ func getDefaultDrivers(ctx context.Context, dockerCli command.Cli) ([]build.Driv
return driversForNodeGroup(ctx, dockerCli, ng) return driversForNodeGroup(ctx, dockerCli, ng)
} }
d, err := driver.GetDriver(ctx, "buildx_buildkit_default", nil, dockerCli.Client()) d, err := driver.GetDriver(ctx, "buildx_buildkit_default", nil, dockerCli.Client(), nil, "", nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +1,8 @@
package docker package docker
import ( import (
"archive/tar"
"bytes"
"context" "context"
"io" "io"
"io/ioutil" "io/ioutil"
@@ -20,11 +22,13 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
var buildkitImage = "moby/buildkit:master" // TODO: make this verified and configuratble var defaultBuildkitImage = "moby/buildkit:buildx-stable-1" // TODO: make this verified
type Driver struct { type Driver struct {
driver.InitConfig driver.InitConfig
factory driver.Factory factory driver.Factory
netMode string
image string
} }
func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error { func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
@@ -49,8 +53,12 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
} }
func (d *Driver) create(ctx context.Context, l progress.SubLogger) error { func (d *Driver) create(ctx context.Context, l progress.SubLogger) error {
if err := l.Wrap("pulling image "+buildkitImage, func() error { imageName := defaultBuildkitImage
rc, err := d.DockerAPI.ImageCreate(ctx, buildkitImage, types.ImageCreateOptions{}) if d.image != "" {
imageName = d.image
}
if err := l.Wrap("pulling image "+imageName, func() error {
rc, err := d.DockerAPI.ImageCreate(ctx, imageName, types.ImageCreateOptions{})
if err != nil { if err != nil {
return err return err
} }
@@ -59,15 +67,34 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error {
}); err != nil { }); err != nil {
return err return err
} }
cfg := &container.Config{
Image: imageName,
}
if d.InitConfig.BuildkitFlags != nil {
cfg.Cmd = d.InitConfig.BuildkitFlags
}
if err := l.Wrap("creating container "+d.Name, func() error { if err := l.Wrap("creating container "+d.Name, func() error {
_, err := d.DockerAPI.ContainerCreate(ctx, &container.Config{ hc := &container.HostConfig{
Image: buildkitImage,
}, &container.HostConfig{
Privileged: true, Privileged: true,
}, &network.NetworkingConfig{}, d.Name) }
if d.netMode != "" {
hc.NetworkMode = container.NetworkMode(d.netMode)
}
_, err := d.DockerAPI.ContainerCreate(ctx, cfg, hc, &network.NetworkingConfig{}, d.Name)
if err != nil { if err != nil {
return err return err
} }
if f := d.InitConfig.ConfigFile; f != "" {
buf, err := readFileToTar(f)
if err != nil {
return err
}
if err := d.DockerAPI.CopyToContainer(ctx, d.Name, "/", buf, dockertypes.CopyToContainerOptions{}); err != nil {
return err
}
}
if err := d.start(ctx, l); err != nil { if err := d.start(ctx, l); err != nil {
return err return err
} }
@@ -239,3 +266,26 @@ type demux struct {
func (d *demux) Read(dt []byte) (int, error) { func (d *demux) Read(dt []byte) (int, error) {
return d.Reader.Read(dt) return d.Reader.Read(dt)
} }
func readFileToTar(fn string) (*bytes.Buffer, error) {
buf := bytes.NewBuffer(nil)
tw := tar.NewWriter(buf)
dt, err := ioutil.ReadFile(fn)
if err != nil {
return nil, err
}
if err := tw.WriteHeader(&tar.Header{
Name: "/etc/buildkit/buildkitd.toml",
Size: int64(len(dt)),
Mode: 0644,
}); err != nil {
return nil, err
}
if _, err := tw.Write(dt); err != nil {
return nil, err
}
if err := tw.Close(); err != nil {
return nil, err
}
return buf, nil
}

View File

@@ -37,8 +37,22 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver
if cfg.DockerAPI == nil { if cfg.DockerAPI == nil {
return nil, errors.Errorf("%s driver requires docker API access", f.Name()) return nil, errors.Errorf("%s driver requires docker API access", f.Name())
} }
d := &Driver{factory: f, InitConfig: cfg}
for k, v := range cfg.DriverOpts {
switch k {
case "network":
d.netMode = v
if v == "host" {
d.InitConfig.BuildkitFlags = append(d.InitConfig.BuildkitFlags, "--allow-insecure-entitlement=network.host")
}
case "image":
d.image = v
default:
return nil, errors.Errorf("invalid driver option %s for docker-container driver", k)
}
}
return &Driver{factory: f, InitConfig: cfg}, nil return d, nil
} }
func (f *factory) AllowsInstances() bool { func (f *factory) AllowsInstances() bool {

View File

@@ -44,6 +44,9 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver
if cfg.DockerAPI == nil { if cfg.DockerAPI == nil {
return nil, errors.Errorf("docker driver requires docker API access") return nil, errors.Errorf("docker driver requires docker API access")
} }
if cfg.ConfigFile != "" {
return nil, errors.Errorf("setting config file is not supported for docker driver, use dockerd configuration file")
}
return &Driver{factory: f, InitConfig: cfg}, nil return &Driver{factory: f, InitConfig: cfg}, nil
} }

View File

@@ -23,10 +23,11 @@ type BuildkitConfig struct {
type InitConfig struct { type InitConfig struct {
// This object needs updates to be generic for different drivers // This object needs updates to be generic for different drivers
Name string Name string
DockerAPI dockerclient.APIClient DockerAPI dockerclient.APIClient
BuildkitConfig BuildkitConfig BuildkitFlags []string
Meta map[string]interface{} ConfigFile string
DriverOpts map[string]string
} }
var drivers map[string]Factory var drivers map[string]Factory
@@ -71,10 +72,13 @@ func GetFactory(name string, instanceRequired bool) Factory {
return nil return nil
} }
func GetDriver(ctx context.Context, name string, f Factory, api dockerclient.APIClient) (Driver, error) { func GetDriver(ctx context.Context, name string, f Factory, api dockerclient.APIClient, flags []string, config string, do map[string]string) (Driver, error) {
ic := InitConfig{ ic := InitConfig{
DockerAPI: api, DockerAPI: api,
Name: name, Name: name,
BuildkitFlags: flags,
ConfigFile: config,
DriverOpts: do,
} }
if f == nil { if f == nil {
var err error var err error
@@ -85,3 +89,7 @@ func GetDriver(ctx context.Context, name string, f Factory, api dockerclient.API
} }
return f.New(ctx, ic) return f.New(ctx, ic)
} }
func GetFactories() map[string]Factory {
return drivers
}

1
go.mod
View File

@@ -35,6 +35,7 @@ require (
github.com/gogo/protobuf v1.2.1 // indirect github.com/gogo/protobuf v1.2.1 // indirect
github.com/google/certificate-transparency-go v1.0.21 // indirect github.com/google/certificate-transparency-go v1.0.21 // indirect
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9
github.com/gorilla/mux v1.7.0 // indirect github.com/gorilla/mux v1.7.0 // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
github.com/hashicorp/go-version v1.1.0 // indirect github.com/hashicorp/go-version v1.1.0 // indirect

View File

@@ -16,9 +16,12 @@ type NodeGroup struct {
} }
type Node struct { type Node struct {
Name string Name string
Endpoint string Endpoint string
Platforms []specs.Platform Platforms []specs.Platform
Flags []string
ConfigFile string
DriverOpts map[string]string
} }
func (ng *NodeGroup) Leave(name string) error { func (ng *NodeGroup) Leave(name string) error {
@@ -33,7 +36,7 @@ func (ng *NodeGroup) Leave(name string) error {
return nil return nil
} }
func (ng *NodeGroup) Update(name, endpoint string, platforms []string, endpointsSet bool, actionAppend bool) error { func (ng *NodeGroup) Update(name, endpoint string, platforms []string, endpointsSet bool, actionAppend bool, flags []string, configFile string, do map[string]string) error {
i := ng.findNode(name) i := ng.findNode(name)
if i == -1 && !actionAppend { if i == -1 && !actionAppend {
if len(ng.Nodes) > 0 { if len(ng.Nodes) > 0 {
@@ -55,6 +58,9 @@ func (ng *NodeGroup) Update(name, endpoint string, platforms []string, endpoints
if len(platforms) > 0 { if len(platforms) > 0 {
n.Platforms = pp n.Platforms = pp
} }
if flags != nil {
n.Flags = flags
}
ng.Nodes[i] = n ng.Nodes[i] = n
if err := ng.validateDuplicates(endpoint, i); err != nil { if err := ng.validateDuplicates(endpoint, i); err != nil {
return err return err
@@ -72,9 +78,12 @@ func (ng *NodeGroup) Update(name, endpoint string, platforms []string, endpoints
} }
n := Node{ n := Node{
Name: name, Name: name,
Endpoint: endpoint, Endpoint: endpoint,
Platforms: pp, Platforms: pp,
ConfigFile: configFile,
Flags: flags,
DriverOpts: do,
} }
ng.Nodes = append(ng.Nodes, n) ng.Nodes = append(ng.Nodes, n)

View File

@@ -11,16 +11,16 @@ func TestNodeGroupUpdate(t *testing.T) {
t.Parallel() t.Parallel()
ng := &NodeGroup{} ng := &NodeGroup{}
err := ng.Update("foo", "foo0", []string{"linux/amd64"}, true, false) err := ng.Update("foo", "foo0", []string{"linux/amd64"}, true, false, []string{"--debug"}, "", nil)
require.NoError(t, err) require.NoError(t, err)
err = ng.Update("foo1", "foo1", []string{"linux/arm64", "linux/arm/v7"}, true, true) err = ng.Update("foo1", "foo1", []string{"linux/arm64", "linux/arm/v7"}, true, true, nil, "", nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, len(ng.Nodes), 2) require.Equal(t, len(ng.Nodes), 2)
// update // update
err = ng.Update("foo", "foo2", []string{"linux/amd64", "linux/arm"}, true, false) err = ng.Update("foo", "foo2", []string{"linux/amd64", "linux/arm"}, true, false, nil, "", nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, len(ng.Nodes), 2) require.Equal(t, len(ng.Nodes), 2)
@@ -28,9 +28,11 @@ func TestNodeGroupUpdate(t *testing.T) {
require.Equal(t, []string{"linux/arm64"}, platformutil.Format(ng.Nodes[1].Platforms)) require.Equal(t, []string{"linux/arm64"}, platformutil.Format(ng.Nodes[1].Platforms))
require.Equal(t, "foo2", ng.Nodes[0].Endpoint) require.Equal(t, "foo2", ng.Nodes[0].Endpoint)
require.Equal(t, []string{"--debug"}, ng.Nodes[0].Flags)
require.Equal(t, []string(nil), ng.Nodes[1].Flags)
// duplicate endpoint // duplicate endpoint
err = ng.Update("foo1", "foo2", nil, true, false) err = ng.Update("foo1", "foo2", nil, true, false, nil, "", nil)
require.Error(t, err) require.Error(t, err)
require.Contains(t, err.Error(), "duplicate endpoint") require.Contains(t, err.Error(), "duplicate endpoint")

12
vendor/modules.txt vendored
View File

@@ -36,6 +36,8 @@ github.com/containerd/containerd/remotes
github.com/containerd/containerd/remotes/docker github.com/containerd/containerd/remotes/docker
github.com/containerd/containerd/log github.com/containerd/containerd/log
github.com/containerd/containerd/content/local github.com/containerd/containerd/content/local
github.com/containerd/containerd/containers
github.com/containerd/containerd/oci
github.com/containerd/containerd/labels github.com/containerd/containerd/labels
github.com/containerd/containerd/reference github.com/containerd/containerd/reference
github.com/containerd/containerd/version github.com/containerd/containerd/version
@@ -44,12 +46,10 @@ github.com/containerd/containerd/sys
github.com/containerd/containerd/api/services/content/v1 github.com/containerd/containerd/api/services/content/v1
github.com/containerd/containerd/content/proxy github.com/containerd/containerd/content/proxy
github.com/containerd/containerd/services/content/contentserver github.com/containerd/containerd/services/content/contentserver
github.com/containerd/containerd/containers
github.com/containerd/containerd/oci
github.com/containerd/containerd
github.com/containerd/containerd/namespaces
github.com/containerd/containerd/mount github.com/containerd/containerd/mount
github.com/containerd/containerd/namespaces
github.com/containerd/containerd/snapshots github.com/containerd/containerd/snapshots
github.com/containerd/containerd
github.com/containerd/containerd/api/services/containers/v1 github.com/containerd/containerd/api/services/containers/v1
github.com/containerd/containerd/api/services/diff/v1 github.com/containerd/containerd/api/services/diff/v1
github.com/containerd/containerd/api/services/events/v1 github.com/containerd/containerd/api/services/events/v1
@@ -83,12 +83,12 @@ github.com/containerd/containerd/events/exchange
github.com/containerd/containerd/identifiers github.com/containerd/containerd/identifiers
# github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc # github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc
github.com/containerd/continuity github.com/containerd/continuity
github.com/containerd/continuity/fs
github.com/containerd/continuity/pathdriver github.com/containerd/continuity/pathdriver
github.com/containerd/continuity/devices github.com/containerd/continuity/devices
github.com/containerd/continuity/driver github.com/containerd/continuity/driver
github.com/containerd/continuity/proto github.com/containerd/continuity/proto
github.com/containerd/continuity/sysx github.com/containerd/continuity/sysx
github.com/containerd/continuity/fs
github.com/containerd/continuity/syscallx github.com/containerd/continuity/syscallx
# github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 # github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448
github.com/containerd/fifo github.com/containerd/fifo
@@ -266,6 +266,7 @@ github.com/moby/buildkit/session
github.com/moby/buildkit/session/secrets/secretsprovider github.com/moby/buildkit/session/secrets/secretsprovider
github.com/moby/buildkit/session/sshforward/sshprovider github.com/moby/buildkit/session/sshforward/sshprovider
github.com/moby/buildkit/session/upload/uploadprovider github.com/moby/buildkit/session/upload/uploadprovider
github.com/moby/buildkit/util/entitlements
github.com/moby/buildkit/util/appcontext github.com/moby/buildkit/util/appcontext
github.com/moby/buildkit/identity github.com/moby/buildkit/identity
github.com/moby/buildkit/util/progress/progressui github.com/moby/buildkit/util/progress/progressui
@@ -285,7 +286,6 @@ github.com/moby/buildkit/session/grpchijack
github.com/moby/buildkit/solver/pb github.com/moby/buildkit/solver/pb
github.com/moby/buildkit/util/apicaps github.com/moby/buildkit/util/apicaps
github.com/moby/buildkit/util/appdefaults github.com/moby/buildkit/util/appdefaults
github.com/moby/buildkit/util/entitlements
github.com/moby/buildkit/session/secrets github.com/moby/buildkit/session/secrets
github.com/moby/buildkit/session/sshforward github.com/moby/buildkit/session/sshforward
github.com/moby/buildkit/session/upload github.com/moby/buildkit/session/upload