mirror of
https://github.com/kreuzwerker/terraform-provider-docker.git
synced 2026-02-18 10:07:57 -05:00
fix: Implement buildx fixes for general buildkit support and platform handling (#734)
* fix: Implement buildx fixes for general buildkit support and platform handling * chore: Revert to having buildkit for non-buildx build attribute
This commit is contained in:
parent
da2a7967c8
commit
6f1d33f6ac
7 changed files with 78 additions and 13 deletions
|
|
@ -43,7 +43,7 @@ resource "docker_image" "ubuntu" {
|
|||
|
||||
### Build
|
||||
|
||||
You can also use the resource to build an image. By default the build block is using the old legacy docker build. In order to use a buildx builder, please read the section below
|
||||
You can also use the resource to build an image. If you want to use a buildx builder with all of its features, please read the section below.
|
||||
|
||||
-> **Note**: The default timeout for the building is 20 minutes. If you need to increase this, you can use [operation timeouts](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts).
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ resource "docker_image" "zoo" {
|
|||
|
||||
-> **Note**: The buildx feature is currently in preview and may have some quirks. Known issues: Setting `ulimits` will not work.
|
||||
|
||||
The `build` argument uses the legacy docker builder. If you want to use a buildx builder, you need to set the `builder` argument. For the default buildx builder, you can set the `builder` argument to `default`. For a custom buildx builder, you can set the `builder` argument to the name of the builder. You can find the name of the builder by running `docker buildx ls`.
|
||||
If you want to use a buildx builder, you need to set the `builder` argument. For the default buildx builder, you can set the `builder` argument to `default`. For a custom buildx builder, you can set the `builder` argument to the name of the builder. You can find the name of the builder by running `docker buildx ls`.
|
||||
|
||||
The single platform build result is automatically loaded to `docker images`.
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ Optional:
|
|||
- `build_args` (Map of String) Pairs for build-time variables in the form of `ENDPOINT : "https://example.com"`
|
||||
- `build_id` (String) BuildID is an optional identifier that can be passed together with the build request. The same identifier can be used to gracefully cancel the build with the cancel request.
|
||||
- `build_log_file` (String) Path to a file where the buildx log are written to. Only available when `builder` is set. If not set, no logs are available. The path is taken as is, so make sure to use a path that is available.
|
||||
- `builder` (String) Set the name of the buildx builder to use. If not set or empty, the legacy builder will be used.
|
||||
- `builder` (String) Set the name of the buildx builder to use. If not set, the legacy builder is used.
|
||||
- `cache_from` (List of String) Images to consider as cache sources
|
||||
- `cgroup_parent` (String) Optional parent cgroup for the container
|
||||
- `cpu_period` (Number) The length of a CPU period in microseconds
|
||||
|
|
@ -143,7 +143,7 @@ Optional:
|
|||
- `memory_swap` (Number) Total memory (memory + swap), -1 to enable unlimited swap
|
||||
- `network_mode` (String) Set the networking mode for the RUN instructions during build
|
||||
- `no_cache` (Boolean) Do not use the cache when building the image
|
||||
- `platform` (String) Set platform if server is multi-platform capable
|
||||
- `platform` (String) Set the target platform for the build. Defaults to `GOOS/GOARCH`. For more information see the [docker documentation](https://github.com/docker/buildx/blob/master/docs/reference/buildx.md#-set-the-target-platforms-for-the-build---platform)
|
||||
- `pull_parent` (Boolean) Attempt to pull the image even if an older image exists locally
|
||||
- `remote_context` (String) A Git repository URI or HTTP/HTTPS context URI. Will be ignored if `builder` is set.
|
||||
- `remove` (Boolean) Remove intermediate containers after a successful build. Defaults to `true`.
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ func mapBuildAttributesToBuildOptions(buildAttributes map[string]interface{}, im
|
|||
options.target = target
|
||||
}
|
||||
|
||||
if platform, ok := buildAttributes["platform"].(string); ok {
|
||||
if platform, ok := buildAttributes["platform"].(string); ok && len(platform) > 0 {
|
||||
options.platforms = append(options.platforms, platform)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ func resourceDockerImage() *schema.Resource {
|
|||
},
|
||||
"platform": {
|
||||
Type: schema.TypeString,
|
||||
Description: "Set platform if server is multi-platform capable",
|
||||
Description: "Set the target platform for the build. Defaults to `GOOS/GOARCH`. For more information see the [docker documentation](https://github.com/docker/buildx/blob/master/docs/reference/buildx.md#-set-the-target-platforms-for-the-build---platform)",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
|
@ -406,7 +406,7 @@ func resourceDockerImage() *schema.Resource {
|
|||
},
|
||||
"builder": {
|
||||
Type: schema.TypeString,
|
||||
Description: "Set the name of the buildx builder to use. If not set or empty, the legacy builder will be used.",
|
||||
Description: "Set the name of the buildx builder to use. If not set, the legacy builder is used.",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -16,12 +17,15 @@ import (
|
|||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/moby/buildkit/session"
|
||||
"github.com/moby/buildkit/session/secrets/secretsprovider"
|
||||
"github.com/moby/go-archive"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
|
@ -56,15 +60,17 @@ func resourceDockerImageCreate(ctx context.Context, d *schema.ResourceData, meta
|
|||
}
|
||||
buildLogFile := rawBuild["build_log_file"].(string)
|
||||
|
||||
log.Printf("[DEBUG] build options %#v", options)
|
||||
|
||||
err = runBuild(ctx, dockerCli, options, buildLogFile)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
return diag.Errorf("Error running buildx build: %v", err)
|
||||
}
|
||||
} else {
|
||||
|
||||
err := buildDockerImage(ctx, rawBuild, imageName, client)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
return diag.Errorf("Error running legacy build: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -356,6 +362,23 @@ func buildDockerImage(ctx context.Context, rawBuild map[string]interface{}, imag
|
|||
|
||||
buildContext := rawBuild["context"].(string)
|
||||
|
||||
buildKitSession := enableBuildKitIfSupported(ctx, client, &buildOptions)
|
||||
|
||||
// If Buildkit is enabled, try to parse and use secrets if present.
|
||||
if buildKitSession != nil {
|
||||
if secretsRaw, secretsDefined := rawBuild["secrets"]; secretsDefined {
|
||||
parsedSecrets := parseBuildSecrets(secretsRaw)
|
||||
|
||||
store, err := secretsprovider.NewStore(parsedSecrets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
provider := secretsprovider.NewSecretProvider(store)
|
||||
buildKitSession.Allow(provider)
|
||||
}
|
||||
}
|
||||
|
||||
buildCtx, relDockerfile, err := prepareBuildContext(buildContext, buildOptions.Dockerfile)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -377,6 +400,33 @@ func buildDockerImage(ctx context.Context, rawBuild map[string]interface{}, imag
|
|||
return nil
|
||||
}
|
||||
|
||||
const minBuildkitDockerVersion = "1.39"
|
||||
|
||||
func enableBuildKitIfSupported(
|
||||
ctx context.Context,
|
||||
client *client.Client,
|
||||
buildOptions *types.ImageBuildOptions,
|
||||
) *session.Session {
|
||||
dockerClientVersion := client.ClientVersion()
|
||||
log.Printf("[DEBUG] DockerClientVersion: %v, minBuildKitDockerVersion: %v\n", dockerClientVersion, minBuildkitDockerVersion)
|
||||
if versions.GreaterThanOrEqualTo(dockerClientVersion, minBuildkitDockerVersion) {
|
||||
log.Printf("[DEBUG] Enabling BuildKit")
|
||||
s, _ := session.NewSession(ctx, "docker-provider")
|
||||
dialSession := func(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) {
|
||||
return client.DialHijack(ctx, "/session", proto, meta)
|
||||
}
|
||||
//nolint
|
||||
go s.Run(ctx, dialSession)
|
||||
defer s.Close() //nolint:errcheck
|
||||
buildOptions.SessionID = s.ID()
|
||||
buildOptions.Version = types.BuilderBuildKit
|
||||
return s
|
||||
} else {
|
||||
buildOptions.Version = types.BuilderV1
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func prepareBuildContext(specifiedContext string, specifiedDockerfile string) (io.ReadCloser, string, error) {
|
||||
var (
|
||||
dockerfileCtx io.ReadCloser
|
||||
|
|
@ -465,3 +515,20 @@ func decodeBuildMessages(response types.ImageBuildResponse) (string, error) {
|
|||
|
||||
return buf.String(), buildErr
|
||||
}
|
||||
|
||||
func parseBuildSecrets(secretsRaw interface{}) []secretsprovider.Source {
|
||||
options := secretsRaw.([]interface{})
|
||||
|
||||
secrets := make([]secretsprovider.Source, len(options))
|
||||
for i, option := range options {
|
||||
secretRaw := option.(map[string]interface{})
|
||||
source := secretsprovider.Source{
|
||||
ID: secretRaw["id"].(string),
|
||||
FilePath: secretRaw["src"].(string),
|
||||
Env: secretRaw["env"].(string),
|
||||
}
|
||||
secrets[i] = source
|
||||
}
|
||||
|
||||
return secrets
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ you need to use it in combination with `docker_registry_image` as follows:
|
|||
|
||||
### Build
|
||||
|
||||
You can also use the resource to build an image. By default the build block is using the old legacy docker build. In order to use a buildx builder, please read the section below
|
||||
You can also use the resource to build an image. If you want to use a buildx builder with all of its features, please read the section below.
|
||||
|
||||
-> **Note**: The default timeout for the building is 20 minutes. If you need to increase this, you can use [operation timeouts](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts).
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ You can use the `triggers` argument to specify when the image should be rebuild.
|
|||
|
||||
-> **Note**: The buildx feature is currently in preview and may have some quirks. Known issues: Setting `ulimits` will not work.
|
||||
|
||||
The `build` argument uses the legacy docker builder. If you want to use a buildx builder, you need to set the `builder` argument. For the default buildx builder, you can set the `builder` argument to `default`. For a custom buildx builder, you can set the `builder` argument to the name of the builder. You can find the name of the builder by running `docker buildx ls`.
|
||||
If you want to use a buildx builder, you need to set the `builder` argument. For the default buildx builder, you can set the `builder` argument to `default`. For a custom buildx builder, you can set the `builder` argument to the name of the builder. You can find the name of the builder by running `docker buildx ls`.
|
||||
|
||||
The single platform build result is automatically loaded to `docker images`.
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ resource "docker_image" "test" {
|
|||
dockerfile = "Dockerfile"
|
||||
force_remove = true
|
||||
builder = "default"
|
||||
platform = "linux/amd64"
|
||||
|
||||
secrets {
|
||||
id = "TEST_SECRET_SRC"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ resource "docker_image" "test" {
|
|||
dockerfile = "Dockerfile"
|
||||
force_remove = true
|
||||
builder = "default"
|
||||
platform = "linux/amd64"
|
||||
|
||||
build_log_file = "%s"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue