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

Add docker builder option to provider #987

Merged
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
1 change: 1 addition & 0 deletions .github/workflows/e2e-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: E2E tests
on:
release:
types: [prereleased]
workflow_dispatch: {}
pull_request:
branches:
- main
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/e2e-win-full-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: E2E Win full tests
on:
release:
types: [prereleased]
workflow_dispatch: {}

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/go-licenses-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
paths:
- .github/workflows/go-licenses-check.yaml
- go.mod
workflow_dispatch:
workflow_dispatch: {}

concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
Expand Down
29 changes: 29 additions & 0 deletions pkg/docker/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"os"
Expand All @@ -17,6 +18,33 @@ import (
perrors "github.com/pkg/errors"
)

// DockerBuilder represents the Docker builder types.
type DockerBuilder int

// Enum values for DockerBuilder.
const (
DockerBuilderDefault DockerBuilder = iota
DockerBuilderBuildX
DockerBuilderBuildKit
)

func (db DockerBuilder) String() string {
return [...]string{"", "buildx", "buildkit"}[db]
}

func DockerBuilderFromString(s string) (DockerBuilder, error) {
switch s {
case "":
return DockerBuilderDefault, nil
case "buildkit":
return DockerBuilderBuildKit, nil
case "buildx":
return DockerBuilderBuildX, nil
default:
return DockerBuilderDefault, errors.New("invalid docker builder")
}
}

type DockerHelper struct {
DockerCommand string
// for a running container, we cannot pass down the container ID to the driver without introducing
Expand All @@ -25,6 +53,7 @@ type DockerHelper struct {
ContainerID string
// allow command to have a custom environment
Environment []string
Builder DockerBuilder
}

func (r *DockerHelper) GPUSupportEnabled() (bool, error) {
Expand Down
30 changes: 23 additions & 7 deletions pkg/driver/docker/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,34 @@ func (d *dockerDriver) BuildDevContainer(
if options.Platform != "" {
d.Log.Infof("Build for platform '%s'...", options.Platform)
}
if !options.ForceInternalBuildKit && d.buildxExists(ctx) {
d.Log.Info("Build with docker buildx...")
err := d.buildxBuild(ctx, writer, options.Platform, buildOptions)
if err != nil {
return nil, errors.Wrap(err, "buildx build")
}

builder := d.Docker.Builder
if (builder == docker.DockerBuilderDefault || builder == docker.
DockerBuilderBuildX) && d.buildxExists(ctx) && !options.ForceInternalBuildKit {
builder = docker.DockerBuilderBuildX
} else {
builder = docker.DockerBuilderBuildKit
}

switch builder {
case docker.DockerBuilderBuildX:
if d.buildxExists(ctx) {
d.Log.Info("Build with docker buildx...")
err := d.buildxBuild(ctx, writer, options.Platform, buildOptions)
if err != nil {
return nil, errors.Wrap(err, "buildx build")
}
} else {
return nil, fmt.Errorf("buildx is not available on your host. Use buildkit builder")
}
case docker.DockerBuilderBuildKit:
d.Log.Info("Build with internal buildkit...")
err := d.internalBuild(ctx, writer, options.Platform, buildOptions)
if err != nil {
return nil, errors.Wrap(err, "internal build")
}
case docker.DockerBuilderDefault:
return nil, fmt.Errorf("invalid docker builder: %s", builder)
}

// inspect image
Expand Down Expand Up @@ -221,7 +237,7 @@ func (d *dockerDriver) buildxExists(ctx context.Context) bool {
buf := &bytes.Buffer{}
err := d.Docker.Run(ctx, []string{"buildx", "version"}, nil, buf, buf)

return err == nil
return (err == nil) || d.Docker.IsPodman()
}

func (d *dockerDriver) internalBuild(ctx context.Context, writer io.Writer, platform string, options *build.BuildOptions) error {
Expand Down
12 changes: 10 additions & 2 deletions pkg/driver/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,29 @@ func makeEnvironment(env map[string]string, log log.Logger) []string {
return ret
}

func NewDockerDriver(workspaceInfo *provider2.AgentWorkspaceInfo, log log.Logger) driver.DockerDriver {
func NewDockerDriver(workspaceInfo *provider2.AgentWorkspaceInfo, log log.Logger) (driver.DockerDriver, error) {
dockerCommand := "docker"
if workspaceInfo.Agent.Docker.Path != "" {
dockerCommand = workspaceInfo.Agent.Docker.Path
}

var builder docker.DockerBuilder
var err error
builder, err = docker.DockerBuilderFromString(workspaceInfo.Agent.Docker.Builder)
if err != nil {
return nil, err
}

log.Debugf("Using docker command '%s'", dockerCommand)
return &dockerDriver{
Docker: &docker.DockerHelper{
DockerCommand: dockerCommand,
Environment: makeEnvironment(workspaceInfo.Agent.Docker.Env, log),
ContainerID: workspaceInfo.Workspace.Source.Container,
Builder: builder,
},
Log: log,
}
}, nil
}

type dockerDriver struct {
Expand Down
2 changes: 1 addition & 1 deletion pkg/driver/drivercreate/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
func NewDriver(workspaceInfo *provider2.AgentWorkspaceInfo, log log.Logger) (driver.Driver, error) {
driver := workspaceInfo.Agent.Driver
if driver == "" || driver == provider2.DockerDriver {
return docker.NewDockerDriver(workspaceInfo, log), nil
return docker.NewDockerDriver(workspaceInfo, log)
} else if driver == provider2.CustomDriver {
return custom.NewCustomDriver(workspaceInfo, log), nil
} else if driver == "kubernetes" {
Expand Down
1 change: 1 addition & 0 deletions pkg/options/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ func ResolveAgentConfig(devConfig *config.Config, provider *provider2.ProviderCo
agentConfig.Driver = resolver.ResolveDefaultValue(agentConfig.Driver, options)
agentConfig.Local = types.StrBool(resolver.ResolveDefaultValue(string(agentConfig.Local), options))
agentConfig.Docker.Path = resolver.ResolveDefaultValue(agentConfig.Docker.Path, options)
agentConfig.Docker.Builder = resolver.ResolveDefaultValue(agentConfig.Docker.Builder, options)
agentConfig.Docker.Install = types.StrBool(resolver.ResolveDefaultValue(string(agentConfig.Docker.Install), options))
agentConfig.Docker.Env = resolver.ResolveDefaultValues(agentConfig.Docker.Env, options)
agentConfig.DataPath = resolver.ResolveDefaultValue(agentConfig.DataPath, options)
Expand Down
3 changes: 3 additions & 0 deletions pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ type ProviderDockerDriverConfig struct {
// If false, DevPod will not try to install docker into the machine.
Install types.StrBool `json:"install,omitempty"`

// Builder to use with docker
Builder string `json:"builder,omitempty"`

// Environment variables to set when running docker commands
Env map[string]string `json:"env,omitempty"`
}
Expand Down
1 change: 0 additions & 1 deletion pkg/provider/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ type CLIOptions struct {
SkipPush bool `json:"skipPush,omitempty"`
Platform []string `json:"platform,omitempty"`

// TESTING
ForceBuild bool `json:"forceBuild,omitempty"`
ForceDockerless bool `json:"forceDockerless,omitempty"`
ForceInternalBuildKit bool `json:"forceInternalBuildKit,omitempty"`
Expand Down
5 changes: 5 additions & 0 deletions providers/docker/provider.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ optionGroups:
- DOCKER_PATH
- DOCKER_HOST
- INACTIVITY_TIMEOUT
- DOCKER_BUILDER
name: "Advanced Options"
options:
INACTIVITY_TIMEOUT:
Expand All @@ -19,11 +20,15 @@ options:
DOCKER_HOST:
global: true
description: The docker host to use.
DOCKER_BUILDER:
global: true
description: The docker builder to use.
agent:
containerInactivityTimeout: ${INACTIVITY_TIMEOUT}
local: true
docker:
path: ${DOCKER_PATH}
builder: ${DOCKER_BUILDER}
install: false
env:
DOCKER_HOST: ${DOCKER_HOST}
Expand Down
Loading