Skip to content

Commit

Permalink
feat(cli): add docker builder option to provider
Browse files Browse the repository at this point in the history
  • Loading branch information
aacebedo committed Apr 20, 2024
1 parent 9fcb44e commit ec49f97
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 11 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/e2e-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ name: E2E tests
on:
release:
types: [prereleased]
workflow_dispatch:
inputs:
environment:
type: environment
pull_request:
branches:
- main
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{"buildkit", "buildx", ""}[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

0 comments on commit ec49f97

Please sign in to comment.