From ffa7803efda5ccb1611613a3bde7e5e0ef39f4c3 Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Thu, 15 Feb 2024 13:55:27 -0800
Subject: [PATCH 01/11] E2E examples

---
 examples/buildx/app/Dockerfile.buildArgs      |   5 +
 examples/buildx/app/Dockerfile.emptyContext   |   2 +
 examples/buildx/app/Dockerfile.generic        |   2 +
 examples/buildx/app/Dockerfile.multiPlatform  |   7 +
 examples/buildx/app/Dockerfile.namedContexts  |   5 +
 examples/buildx/app/Dockerfile.targets        |   8 +
 examples/buildx/csharp/.gitignore             | 353 ++++++++++++++++++
 examples/buildx/csharp/Program.cs             | 211 +++++++++++
 examples/buildx/csharp/Pulumi.yaml            |   3 +
 .../buildx/csharp/app/Dockerfile.buildArgs    |   5 +
 .../buildx/csharp/app/Dockerfile.emptyContext |   2 +
 examples/buildx/csharp/app/Dockerfile.generic |   2 +
 .../csharp/app/Dockerfile.multiPlatform       |   7 +
 .../csharp/app/Dockerfile.namedContexts       |   5 +
 examples/buildx/csharp/app/Dockerfile.targets |   8 +
 examples/buildx/csharp/buildx-examples.csproj |  14 +
 examples/buildx/go/Pulumi.yaml                |   3 +
 examples/buildx/go/app/Dockerfile.buildArgs   |   5 +
 .../buildx/go/app/Dockerfile.emptyContext     |   2 +
 examples/buildx/go/app/Dockerfile.generic     |   2 +
 .../buildx/go/app/Dockerfile.multiPlatform    |   7 +
 .../buildx/go/app/Dockerfile.namedContexts    |   5 +
 examples/buildx/go/app/Dockerfile.targets     |   8 +
 examples/buildx/go/go.mod                     |   8 +
 examples/buildx/go/main.go                    | 179 +++++++++
 examples/buildx/java/Pulumi.yaml              |   3 +
 examples/buildx/java/app/Dockerfile.buildArgs |   5 +
 .../buildx/java/app/Dockerfile.emptyContext   |   2 +
 examples/buildx/java/app/Dockerfile.generic   |   2 +
 .../buildx/java/app/Dockerfile.multiPlatform  |   7 +
 .../buildx/java/app/Dockerfile.namedContexts  |   5 +
 examples/buildx/java/app/Dockerfile.targets   |   8 +
 examples/buildx/java/pom.xml                  |  92 +++++
 .../src/main/java/generated_program/App.java  | 162 ++++++++
 examples/buildx/py/.gitignore                 |   2 +
 examples/buildx/py/Pulumi.yaml                |   3 +
 examples/buildx/py/__main__.py                | 120 ++++++
 examples/buildx/py/app/Dockerfile.buildArgs   |   5 +
 .../buildx/py/app/Dockerfile.emptyContext     |   2 +
 examples/buildx/py/app/Dockerfile.generic     |   2 +
 .../buildx/py/app/Dockerfile.multiPlatform    |   7 +
 .../buildx/py/app/Dockerfile.namedContexts    |   5 +
 examples/buildx/py/app/Dockerfile.targets     |   8 +
 examples/buildx/py/requirements.txt           |   2 +
 examples/buildx/ts/.gitignore                 |   2 +
 examples/buildx/ts/Pulumi.yaml                |   3 +
 examples/buildx/ts/app/Dockerfile.buildArgs   |   5 +
 .../buildx/ts/app/Dockerfile.emptyContext     |   2 +
 examples/buildx/ts/app/Dockerfile.generic     |   2 +
 .../buildx/ts/app/Dockerfile.multiPlatform    |   7 +
 .../buildx/ts/app/Dockerfile.namedContexts    |   5 +
 examples/buildx/ts/app/Dockerfile.targets     |   8 +
 examples/buildx/ts/index.ts                   | 129 +++++++
 examples/buildx/ts/package.json               |  10 +
 examples/buildx/ts/tsconfig.json              |  18 +
 examples/buildx/yaml/.dockerignore            |   2 +
 examples/buildx/yaml/Pulumi.yaml              | 144 +++++++
 examples/buildx/yaml/app/Dockerfile.buildArgs |   5 +
 .../buildx/yaml/app/Dockerfile.emptyContext   |   2 +
 examples/buildx/yaml/app/Dockerfile.generic   |   2 +
 .../buildx/yaml/app/Dockerfile.multiPlatform  |   7 +
 .../buildx/yaml/app/Dockerfile.namedContexts  |   5 +
 examples/buildx/yaml/app/Dockerfile.targets   |   8 +
 examples/examples_dotnet_test.go              |  12 +
 examples/examples_go_test.go                  |  15 +-
 examples/examples_java_test.go                |  56 +++
 examples/examples_nodejs_test.go              |  12 +
 examples/examples_py_test.go                  |  12 +
 examples/examples_yaml_test.go                |  18 +-
 examples/gen.go                               |  13 +
 70 files changed, 1799 insertions(+), 5 deletions(-)
 create mode 100644 examples/buildx/app/Dockerfile.buildArgs
 create mode 100644 examples/buildx/app/Dockerfile.emptyContext
 create mode 100644 examples/buildx/app/Dockerfile.generic
 create mode 100644 examples/buildx/app/Dockerfile.multiPlatform
 create mode 100644 examples/buildx/app/Dockerfile.namedContexts
 create mode 100644 examples/buildx/app/Dockerfile.targets
 create mode 100644 examples/buildx/csharp/.gitignore
 create mode 100644 examples/buildx/csharp/Program.cs
 create mode 100644 examples/buildx/csharp/Pulumi.yaml
 create mode 100644 examples/buildx/csharp/app/Dockerfile.buildArgs
 create mode 100644 examples/buildx/csharp/app/Dockerfile.emptyContext
 create mode 100644 examples/buildx/csharp/app/Dockerfile.generic
 create mode 100644 examples/buildx/csharp/app/Dockerfile.multiPlatform
 create mode 100644 examples/buildx/csharp/app/Dockerfile.namedContexts
 create mode 100644 examples/buildx/csharp/app/Dockerfile.targets
 create mode 100644 examples/buildx/csharp/buildx-examples.csproj
 create mode 100644 examples/buildx/go/Pulumi.yaml
 create mode 100644 examples/buildx/go/app/Dockerfile.buildArgs
 create mode 100644 examples/buildx/go/app/Dockerfile.emptyContext
 create mode 100644 examples/buildx/go/app/Dockerfile.generic
 create mode 100644 examples/buildx/go/app/Dockerfile.multiPlatform
 create mode 100644 examples/buildx/go/app/Dockerfile.namedContexts
 create mode 100644 examples/buildx/go/app/Dockerfile.targets
 create mode 100644 examples/buildx/go/go.mod
 create mode 100644 examples/buildx/go/main.go
 create mode 100644 examples/buildx/java/Pulumi.yaml
 create mode 100644 examples/buildx/java/app/Dockerfile.buildArgs
 create mode 100644 examples/buildx/java/app/Dockerfile.emptyContext
 create mode 100644 examples/buildx/java/app/Dockerfile.generic
 create mode 100644 examples/buildx/java/app/Dockerfile.multiPlatform
 create mode 100644 examples/buildx/java/app/Dockerfile.namedContexts
 create mode 100644 examples/buildx/java/app/Dockerfile.targets
 create mode 100644 examples/buildx/java/pom.xml
 create mode 100644 examples/buildx/java/src/main/java/generated_program/App.java
 create mode 100644 examples/buildx/py/.gitignore
 create mode 100644 examples/buildx/py/Pulumi.yaml
 create mode 100644 examples/buildx/py/__main__.py
 create mode 100644 examples/buildx/py/app/Dockerfile.buildArgs
 create mode 100644 examples/buildx/py/app/Dockerfile.emptyContext
 create mode 100644 examples/buildx/py/app/Dockerfile.generic
 create mode 100644 examples/buildx/py/app/Dockerfile.multiPlatform
 create mode 100644 examples/buildx/py/app/Dockerfile.namedContexts
 create mode 100644 examples/buildx/py/app/Dockerfile.targets
 create mode 100644 examples/buildx/py/requirements.txt
 create mode 100644 examples/buildx/ts/.gitignore
 create mode 100644 examples/buildx/ts/Pulumi.yaml
 create mode 100644 examples/buildx/ts/app/Dockerfile.buildArgs
 create mode 100644 examples/buildx/ts/app/Dockerfile.emptyContext
 create mode 100644 examples/buildx/ts/app/Dockerfile.generic
 create mode 100644 examples/buildx/ts/app/Dockerfile.multiPlatform
 create mode 100644 examples/buildx/ts/app/Dockerfile.namedContexts
 create mode 100644 examples/buildx/ts/app/Dockerfile.targets
 create mode 100644 examples/buildx/ts/index.ts
 create mode 100644 examples/buildx/ts/package.json
 create mode 100644 examples/buildx/ts/tsconfig.json
 create mode 100644 examples/buildx/yaml/.dockerignore
 create mode 100644 examples/buildx/yaml/Pulumi.yaml
 create mode 100644 examples/buildx/yaml/app/Dockerfile.buildArgs
 create mode 100644 examples/buildx/yaml/app/Dockerfile.emptyContext
 create mode 100644 examples/buildx/yaml/app/Dockerfile.generic
 create mode 100644 examples/buildx/yaml/app/Dockerfile.multiPlatform
 create mode 100644 examples/buildx/yaml/app/Dockerfile.namedContexts
 create mode 100644 examples/buildx/yaml/app/Dockerfile.targets
 create mode 100644 examples/examples_java_test.go
 create mode 100644 examples/gen.go

diff --git a/examples/buildx/app/Dockerfile.buildArgs b/examples/buildx/app/Dockerfile.buildArgs
new file mode 100644
index 00000000..438ee017
--- /dev/null
+++ b/examples/buildx/app/Dockerfile.buildArgs
@@ -0,0 +1,5 @@
+FROM alpine
+
+ARG SET_ME_TO_TRUE
+RUN [ "$SET_ME_TO_TRUE" = "true" ]
+RUN echo "That's the correct build arg, thanks! 👍"
diff --git a/examples/buildx/app/Dockerfile.emptyContext b/examples/buildx/app/Dockerfile.emptyContext
new file mode 100644
index 00000000..769593b2
--- /dev/null
+++ b/examples/buildx/app/Dockerfile.emptyContext
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo "This image doesn't use any local files, so it doesn't need a context parameter 👍"
diff --git a/examples/buildx/app/Dockerfile.generic b/examples/buildx/app/Dockerfile.generic
new file mode 100644
index 00000000..e17a80c7
--- /dev/null
+++ b/examples/buildx/app/Dockerfile.generic
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo 👍
diff --git a/examples/buildx/app/Dockerfile.multiPlatform b/examples/buildx/app/Dockerfile.multiPlatform
new file mode 100644
index 00000000..49d3c839
--- /dev/null
+++ b/examples/buildx/app/Dockerfile.multiPlatform
@@ -0,0 +1,7 @@
+FROM --platform=$BUILDPLATFORM alpine as build
+RUN echo ${BUILDPLATFORM} > buildplatform
+RUN echo ${TARGETPLATFORM} > targetplatform
+
+FROM build
+RUN cat buildplatform
+RUN cat targetplatform
diff --git a/examples/buildx/app/Dockerfile.namedContexts b/examples/buildx/app/Dockerfile.namedContexts
new file mode 100644
index 00000000..6e53dba1
--- /dev/null
+++ b/examples/buildx/app/Dockerfile.namedContexts
@@ -0,0 +1,5 @@
+# syntax=docker/dockerfile:1.4
+FROM golang:latest
+
+RUN version="$(go version)" && echo $version && [ "$version" = "go version go1.21.7 linux/amd64" ]
+RUN echo "This image uses named contexts to pin golang:latest to a specific SHA 👍"
diff --git a/examples/buildx/app/Dockerfile.targets b/examples/buildx/app/Dockerfile.targets
new file mode 100644
index 00000000..7cddec71
--- /dev/null
+++ b/examples/buildx/app/Dockerfile.targets
@@ -0,0 +1,8 @@
+FROM alpine as build-me
+RUN echo 👍
+
+FROM build-me as also-build-me
+RUN echo 🤙
+
+FROM build-me as dont-build-me
+RUN [ "true" = "false" ]
diff --git a/examples/buildx/csharp/.gitignore b/examples/buildx/csharp/.gitignore
new file mode 100644
index 00000000..e6452706
--- /dev/null
+++ b/examples/buildx/csharp/.gitignore
@@ -0,0 +1,353 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/examples/buildx/csharp/Program.cs b/examples/buildx/csharp/Program.cs
new file mode 100644
index 00000000..b8161f40
--- /dev/null
+++ b/examples/buildx/csharp/Program.cs
@@ -0,0 +1,211 @@
+using System.Collections.Generic;
+using System.Linq;
+using Pulumi;
+using Docker = Pulumi.Docker;
+
+return await Deployment.RunAsync(() => 
+{
+    var config = new Config();
+    var dockerHubPassword = config.Require("dockerHubPassword");
+    var multiPlatform = new Docker.Buildx.Image("multiPlatform", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.multiPlatform",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+        Platforms = new[]
+        {
+            Docker.Buildx.Platform.Plan9_amd64,
+            Docker.Buildx.Platform.Plan9_386,
+        },
+    });
+
+    var registryPush = new Docker.Buildx.Image("registryPush", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.generic",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+        Tags = new[]
+        {
+            "docker.io/pulumibot/buildkit-e2e:example",
+        },
+        Exports = new[]
+        {
+            new Docker.Buildx.Inputs.ExportEntryArgs
+            {
+                Registry = new Docker.Buildx.Inputs.ExportRegistryArgs
+                {
+                    OciMediaTypes = true,
+                    Push = false,
+                },
+            },
+        },
+        Registries = new[]
+        {
+            new Docker.Buildx.Inputs.RegistryAuthArgs
+            {
+                Address = "docker.io",
+                Username = "pulumibot",
+                Password = dockerHubPassword,
+            },
+        },
+    });
+
+    var cached = new Docker.Buildx.Image("cached", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.generic",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+        CacheTo = new[]
+        {
+            new Docker.Buildx.Inputs.CacheToEntryArgs
+            {
+                Local = new Docker.Buildx.Inputs.CacheToLocalArgs
+                {
+                    Dest = "tmp/cache",
+                    Mode = Docker.Buildx.CacheMode.Max,
+                },
+            },
+        },
+        CacheFrom = new[]
+        {
+            new Docker.Buildx.Inputs.CacheFromEntryArgs
+            {
+                Local = new Docker.Buildx.Inputs.CacheFromLocalArgs
+                {
+                    Src = "tmp/cache",
+                },
+            },
+        },
+    });
+
+    var buildArgs = new Docker.Buildx.Image("buildArgs", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.buildArgs",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+        BuildArgs = 
+        {
+            { "SET_ME_TO_TRUE", "true" },
+        },
+    });
+
+    var targets = new Docker.Buildx.Image("targets", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.targets",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+        Targets = new[]
+        {
+            "build-me",
+            "also-build-me",
+        },
+    });
+
+    var namedContexts = new Docker.Buildx.Image("namedContexts", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.namedContexts",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+            Named = 
+            {
+                { "golang:latest", new Docker.Buildx.Inputs.ContextArgs
+                {
+                    Location = "docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984",
+                } },
+            },
+        },
+    });
+
+    var remoteContext = new Docker.Buildx.Image("remoteContext", new()
+    {
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile",
+        },
+    });
+
+    var remoteContextWithInline = new Docker.Buildx.Image("remoteContextWithInline", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Inline = @"FROM busybox
+COPY hello.c ./
+",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "https://github.com/docker-library/hello-world.git",
+        },
+    });
+
+    var inline = new Docker.Buildx.Image("inline", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Inline = @"FROM alpine
+RUN echo ""This uses an inline Dockerfile! 👍""
+",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+    });
+
+    var dockerLoad = new Docker.Buildx.Image("dockerLoad", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.generic",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+        Exports = new[]
+        {
+            new Docker.Buildx.Inputs.ExportEntryArgs
+            {
+                Docker = new Docker.Buildx.Inputs.ExportDockerArgs
+                {
+                    Tar = true,
+                },
+            },
+        },
+    });
+
+    return new Dictionary<string, object?>
+    {
+        ["platforms"] = multiPlatform.Platforms,
+    };
+});
+
diff --git a/examples/buildx/csharp/Pulumi.yaml b/examples/buildx/csharp/Pulumi.yaml
new file mode 100644
index 00000000..a377f391
--- /dev/null
+++ b/examples/buildx/csharp/Pulumi.yaml
@@ -0,0 +1,3 @@
+name: buildx-examples
+runtime: dotnet
+description: Examples of buildx.Image
diff --git a/examples/buildx/csharp/app/Dockerfile.buildArgs b/examples/buildx/csharp/app/Dockerfile.buildArgs
new file mode 100644
index 00000000..438ee017
--- /dev/null
+++ b/examples/buildx/csharp/app/Dockerfile.buildArgs
@@ -0,0 +1,5 @@
+FROM alpine
+
+ARG SET_ME_TO_TRUE
+RUN [ "$SET_ME_TO_TRUE" = "true" ]
+RUN echo "That's the correct build arg, thanks! 👍"
diff --git a/examples/buildx/csharp/app/Dockerfile.emptyContext b/examples/buildx/csharp/app/Dockerfile.emptyContext
new file mode 100644
index 00000000..769593b2
--- /dev/null
+++ b/examples/buildx/csharp/app/Dockerfile.emptyContext
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo "This image doesn't use any local files, so it doesn't need a context parameter 👍"
diff --git a/examples/buildx/csharp/app/Dockerfile.generic b/examples/buildx/csharp/app/Dockerfile.generic
new file mode 100644
index 00000000..e17a80c7
--- /dev/null
+++ b/examples/buildx/csharp/app/Dockerfile.generic
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo 👍
diff --git a/examples/buildx/csharp/app/Dockerfile.multiPlatform b/examples/buildx/csharp/app/Dockerfile.multiPlatform
new file mode 100644
index 00000000..49d3c839
--- /dev/null
+++ b/examples/buildx/csharp/app/Dockerfile.multiPlatform
@@ -0,0 +1,7 @@
+FROM --platform=$BUILDPLATFORM alpine as build
+RUN echo ${BUILDPLATFORM} > buildplatform
+RUN echo ${TARGETPLATFORM} > targetplatform
+
+FROM build
+RUN cat buildplatform
+RUN cat targetplatform
diff --git a/examples/buildx/csharp/app/Dockerfile.namedContexts b/examples/buildx/csharp/app/Dockerfile.namedContexts
new file mode 100644
index 00000000..6e53dba1
--- /dev/null
+++ b/examples/buildx/csharp/app/Dockerfile.namedContexts
@@ -0,0 +1,5 @@
+# syntax=docker/dockerfile:1.4
+FROM golang:latest
+
+RUN version="$(go version)" && echo $version && [ "$version" = "go version go1.21.7 linux/amd64" ]
+RUN echo "This image uses named contexts to pin golang:latest to a specific SHA 👍"
diff --git a/examples/buildx/csharp/app/Dockerfile.targets b/examples/buildx/csharp/app/Dockerfile.targets
new file mode 100644
index 00000000..7cddec71
--- /dev/null
+++ b/examples/buildx/csharp/app/Dockerfile.targets
@@ -0,0 +1,8 @@
+FROM alpine as build-me
+RUN echo 👍
+
+FROM build-me as also-build-me
+RUN echo 🤙
+
+FROM build-me as dont-build-me
+RUN [ "true" = "false" ]
diff --git a/examples/buildx/csharp/buildx-examples.csproj b/examples/buildx/csharp/buildx-examples.csproj
new file mode 100644
index 00000000..2f2a3274
--- /dev/null
+++ b/examples/buildx/csharp/buildx-examples.csproj
@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+	<PropertyGroup>
+		<OutputType>Exe</OutputType>
+		<TargetFramework>net6.0</TargetFramework>
+		<Nullable>enable</Nullable>
+	</PropertyGroup>
+
+	<ItemGroup>
+		<PackageReference Include="Pulumi" Version="3.*" />
+		<PackageReference Include="Pulumi.Docker" Version="4.*" />
+	</ItemGroup>
+
+</Project>
diff --git a/examples/buildx/go/Pulumi.yaml b/examples/buildx/go/Pulumi.yaml
new file mode 100644
index 00000000..8d31364a
--- /dev/null
+++ b/examples/buildx/go/Pulumi.yaml
@@ -0,0 +1,3 @@
+name: buildx-examples
+runtime: go
+description: Examples of buildx.Image
diff --git a/examples/buildx/go/app/Dockerfile.buildArgs b/examples/buildx/go/app/Dockerfile.buildArgs
new file mode 100644
index 00000000..438ee017
--- /dev/null
+++ b/examples/buildx/go/app/Dockerfile.buildArgs
@@ -0,0 +1,5 @@
+FROM alpine
+
+ARG SET_ME_TO_TRUE
+RUN [ "$SET_ME_TO_TRUE" = "true" ]
+RUN echo "That's the correct build arg, thanks! 👍"
diff --git a/examples/buildx/go/app/Dockerfile.emptyContext b/examples/buildx/go/app/Dockerfile.emptyContext
new file mode 100644
index 00000000..769593b2
--- /dev/null
+++ b/examples/buildx/go/app/Dockerfile.emptyContext
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo "This image doesn't use any local files, so it doesn't need a context parameter 👍"
diff --git a/examples/buildx/go/app/Dockerfile.generic b/examples/buildx/go/app/Dockerfile.generic
new file mode 100644
index 00000000..e17a80c7
--- /dev/null
+++ b/examples/buildx/go/app/Dockerfile.generic
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo 👍
diff --git a/examples/buildx/go/app/Dockerfile.multiPlatform b/examples/buildx/go/app/Dockerfile.multiPlatform
new file mode 100644
index 00000000..49d3c839
--- /dev/null
+++ b/examples/buildx/go/app/Dockerfile.multiPlatform
@@ -0,0 +1,7 @@
+FROM --platform=$BUILDPLATFORM alpine as build
+RUN echo ${BUILDPLATFORM} > buildplatform
+RUN echo ${TARGETPLATFORM} > targetplatform
+
+FROM build
+RUN cat buildplatform
+RUN cat targetplatform
diff --git a/examples/buildx/go/app/Dockerfile.namedContexts b/examples/buildx/go/app/Dockerfile.namedContexts
new file mode 100644
index 00000000..6e53dba1
--- /dev/null
+++ b/examples/buildx/go/app/Dockerfile.namedContexts
@@ -0,0 +1,5 @@
+# syntax=docker/dockerfile:1.4
+FROM golang:latest
+
+RUN version="$(go version)" && echo $version && [ "$version" = "go version go1.21.7 linux/amd64" ]
+RUN echo "This image uses named contexts to pin golang:latest to a specific SHA 👍"
diff --git a/examples/buildx/go/app/Dockerfile.targets b/examples/buildx/go/app/Dockerfile.targets
new file mode 100644
index 00000000..7cddec71
--- /dev/null
+++ b/examples/buildx/go/app/Dockerfile.targets
@@ -0,0 +1,8 @@
+FROM alpine as build-me
+RUN echo 👍
+
+FROM build-me as also-build-me
+RUN echo 🤙
+
+FROM build-me as dont-build-me
+RUN [ "true" = "false" ]
diff --git a/examples/buildx/go/go.mod b/examples/buildx/go/go.mod
new file mode 100644
index 00000000..0019c974
--- /dev/null
+++ b/examples/buildx/go/go.mod
@@ -0,0 +1,8 @@
+module buildx-examples
+
+go 1.20
+
+require (
+	github.com/pulumi/pulumi/sdk/v3 v3.30.0
+	github.com/pulumi/pulumi-docker/sdk/v4 v4.6.0-alpha.1708450847+573e3670.dirty
+)
\ No newline at end of file
diff --git a/examples/buildx/go/main.go b/examples/buildx/go/main.go
new file mode 100644
index 00000000..b5dca9d7
--- /dev/null
+++ b/examples/buildx/go/main.go
@@ -0,0 +1,179 @@
+package main
+
+import (
+	"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx"
+	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
+	"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
+)
+
+func main() {
+	pulumi.Run(func(ctx *pulumi.Context) error {
+		cfg := config.New(ctx, "")
+		dockerHubPassword := cfg.Require("dockerHubPassword")
+		multiPlatform, err := buildx.NewImage(ctx, "multiPlatform", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.multiPlatform"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+			Platforms: buildx.PlatformArray{
+				buildx.Platform_Plan9_amd64,
+				buildx.Platform_Plan9_386,
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "registryPush", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.generic"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+			Tags: pulumi.StringArray{
+				pulumi.String("docker.io/pulumibot/buildkit-e2e:example"),
+			},
+			Exports: buildx.ExportEntryArray{
+				&buildx.ExportEntryArgs{
+					Registry: &buildx.ExportRegistryArgs{
+						OciMediaTypes: pulumi.Bool(true),
+						Push:          pulumi.Bool(false),
+					},
+				},
+			},
+			Registries: buildx.RegistryAuthArray{
+				&buildx.RegistryAuthArgs{
+					Address:  pulumi.String("docker.io"),
+					Username: pulumi.String("pulumibot"),
+					Password: pulumi.String(dockerHubPassword),
+				},
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "cached", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.generic"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+			CacheTo: buildx.CacheToEntryArray{
+				&buildx.CacheToEntryArgs{
+					Local: &buildx.CacheToLocalArgs{
+						Dest: pulumi.String("tmp/cache"),
+						Mode: buildx.CacheModeMax,
+					},
+				},
+			},
+			CacheFrom: buildx.CacheFromEntryArray{
+				&buildx.CacheFromEntryArgs{
+					Local: &buildx.CacheFromLocalArgs{
+						Src: pulumi.String("tmp/cache"),
+					},
+				},
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "buildArgs", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.buildArgs"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+			BuildArgs: pulumi.StringMap{
+				"SET_ME_TO_TRUE": pulumi.String("true"),
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "targets", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.targets"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+			Targets: pulumi.StringArray{
+				pulumi.String("build-me"),
+				pulumi.String("also-build-me"),
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "namedContexts", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.namedContexts"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+				Named: buildx.ContextMap{
+					"golang:latest": &buildx.ContextArgs{
+						Location: pulumi.String("docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984"),
+					},
+				},
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "remoteContext", &buildx.ImageArgs{
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile"),
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "remoteContextWithInline", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Inline: pulumi.String("FROM busybox\nCOPY hello.c ./\n"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("https://github.com/docker-library/hello-world.git"),
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "inline", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Inline: pulumi.String("FROM alpine\nRUN echo \"This uses an inline Dockerfile! 👍\"\n"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "dockerLoad", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.generic"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+			Exports: buildx.ExportEntryArray{
+				&buildx.ExportEntryArgs{
+					Docker: &buildx.ExportDockerArgs{
+						Tar: pulumi.Bool(true),
+					},
+				},
+			},
+		})
+		if err != nil {
+			return err
+		}
+		ctx.Export("platforms", multiPlatform.Platforms)
+		return nil
+	})
+}
diff --git a/examples/buildx/java/Pulumi.yaml b/examples/buildx/java/Pulumi.yaml
new file mode 100644
index 00000000..d9bb66cc
--- /dev/null
+++ b/examples/buildx/java/Pulumi.yaml
@@ -0,0 +1,3 @@
+name: buildx-examples
+runtime: java
+description: Examples of buildx.Image
diff --git a/examples/buildx/java/app/Dockerfile.buildArgs b/examples/buildx/java/app/Dockerfile.buildArgs
new file mode 100644
index 00000000..438ee017
--- /dev/null
+++ b/examples/buildx/java/app/Dockerfile.buildArgs
@@ -0,0 +1,5 @@
+FROM alpine
+
+ARG SET_ME_TO_TRUE
+RUN [ "$SET_ME_TO_TRUE" = "true" ]
+RUN echo "That's the correct build arg, thanks! 👍"
diff --git a/examples/buildx/java/app/Dockerfile.emptyContext b/examples/buildx/java/app/Dockerfile.emptyContext
new file mode 100644
index 00000000..769593b2
--- /dev/null
+++ b/examples/buildx/java/app/Dockerfile.emptyContext
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo "This image doesn't use any local files, so it doesn't need a context parameter 👍"
diff --git a/examples/buildx/java/app/Dockerfile.generic b/examples/buildx/java/app/Dockerfile.generic
new file mode 100644
index 00000000..e17a80c7
--- /dev/null
+++ b/examples/buildx/java/app/Dockerfile.generic
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo 👍
diff --git a/examples/buildx/java/app/Dockerfile.multiPlatform b/examples/buildx/java/app/Dockerfile.multiPlatform
new file mode 100644
index 00000000..49d3c839
--- /dev/null
+++ b/examples/buildx/java/app/Dockerfile.multiPlatform
@@ -0,0 +1,7 @@
+FROM --platform=$BUILDPLATFORM alpine as build
+RUN echo ${BUILDPLATFORM} > buildplatform
+RUN echo ${TARGETPLATFORM} > targetplatform
+
+FROM build
+RUN cat buildplatform
+RUN cat targetplatform
diff --git a/examples/buildx/java/app/Dockerfile.namedContexts b/examples/buildx/java/app/Dockerfile.namedContexts
new file mode 100644
index 00000000..6e53dba1
--- /dev/null
+++ b/examples/buildx/java/app/Dockerfile.namedContexts
@@ -0,0 +1,5 @@
+# syntax=docker/dockerfile:1.4
+FROM golang:latest
+
+RUN version="$(go version)" && echo $version && [ "$version" = "go version go1.21.7 linux/amd64" ]
+RUN echo "This image uses named contexts to pin golang:latest to a specific SHA 👍"
diff --git a/examples/buildx/java/app/Dockerfile.targets b/examples/buildx/java/app/Dockerfile.targets
new file mode 100644
index 00000000..7cddec71
--- /dev/null
+++ b/examples/buildx/java/app/Dockerfile.targets
@@ -0,0 +1,8 @@
+FROM alpine as build-me
+RUN echo 👍
+
+FROM build-me as also-build-me
+RUN echo 🤙
+
+FROM build-me as dont-build-me
+RUN [ "true" = "false" ]
diff --git a/examples/buildx/java/pom.xml b/examples/buildx/java/pom.xml
new file mode 100644
index 00000000..84d617e0
--- /dev/null
+++ b/examples/buildx/java/pom.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+		<project xmlns="http://maven.apache.org/POM/4.0.0"
+				 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+				 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+			<modelVersion>4.0.0</modelVersion>
+
+			<groupId>com.pulumi</groupId>
+			<artifactId>buildx-examples</artifactId>
+			<version>1.0-SNAPSHOT</version>
+
+			<properties>
+				<encoding>UTF-8</encoding>
+				<maven.compiler.source>11</maven.compiler.source>
+				<maven.compiler.target>11</maven.compiler.target>
+				<maven.compiler.release>11</maven.compiler.release>
+				<mainClass>generated_program.App</mainClass>
+				<mainArgs/>
+			</properties>
+
+			<dependencies>
+				<dependency>
+					<groupId>com.pulumi</groupId>
+					<artifactId>pulumi</artifactId>
+					<version>(,1.0]</version>
+				</dependency>
+				<dependency>
+            		<groupId>com.pulumi</groupId>
+            		<artifactId>docker</artifactId>
+                    <version>[0.0.0,)</version>
+        		</dependency>
+			</dependencies>
+
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>org.apache.maven.plugins</groupId>
+						<artifactId>maven-jar-plugin</artifactId>
+						<version>3.2.2</version>
+						<configuration>
+							<archive>
+								<manifest>
+									<addClasspath>true</addClasspath>
+									<mainClass>${mainClass}</mainClass>
+								</manifest>
+							</archive>
+						</configuration>
+					</plugin>
+					<plugin>
+						<groupId>org.apache.maven.plugins</groupId>
+						<artifactId>maven-assembly-plugin</artifactId>
+						<version>3.4.2</version>
+						<configuration>
+							<archive>
+								<manifest>
+									<addClasspath>true</addClasspath>
+									<mainClass>${mainClass}</mainClass>
+								</manifest>
+							</archive>
+							<descriptorRefs>
+								<descriptorRef>jar-with-dependencies</descriptorRef>
+							</descriptorRefs>
+						</configuration>
+						<executions>
+							<execution>
+								<id>make-my-jar-with-dependencies</id>
+								<phase>package</phase>
+								<goals>
+									<goal>single</goal>
+								</goals>
+							</execution>
+						</executions>
+					</plugin>
+					<plugin>
+						<groupId>org.codehaus.mojo</groupId>
+						<artifactId>exec-maven-plugin</artifactId>
+						<version>3.1.0</version>
+						<configuration>
+							<mainClass>${mainClass}</mainClass>
+							<commandlineArgs>${mainArgs}</commandlineArgs>
+						</configuration>
+					</plugin>
+					<plugin>
+						<groupId>org.apache.maven.plugins</groupId>
+						<artifactId>maven-wrapper-plugin</artifactId>
+						<version>3.1.1</version>
+						<configuration>
+							<mavenVersion>3.8.5</mavenVersion>
+						</configuration>
+					</plugin>
+				</plugins>
+			</build>
+		</project>
diff --git a/examples/buildx/java/src/main/java/generated_program/App.java b/examples/buildx/java/src/main/java/generated_program/App.java
new file mode 100644
index 00000000..8a5acb37
--- /dev/null
+++ b/examples/buildx/java/src/main/java/generated_program/App.java
@@ -0,0 +1,162 @@
+package generated_program;
+
+import com.pulumi.Context;
+import com.pulumi.Pulumi;
+import com.pulumi.core.Output;
+import com.pulumi.docker.buildx.Image;
+import com.pulumi.docker.buildx.ImageArgs;
+import com.pulumi.docker.buildx.DockerfileArgs;
+import com.pulumi.docker.buildx.BuildContextArgs;
+import com.pulumi.docker.buildx.ExportEntryArgs;
+import com.pulumi.docker.buildx.ExportRegistryArgs;
+import com.pulumi.docker.buildx.RegistryAuthArgs;
+import com.pulumi.docker.buildx.CacheToEntryArgs;
+import com.pulumi.docker.buildx.CacheToLocalArgs;
+import com.pulumi.docker.buildx.CacheFromEntryArgs;
+import com.pulumi.docker.buildx.CacheFromLocalArgs;
+import com.pulumi.docker.buildx.ExportDockerArgs;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+public class App {
+    public static void main(String[] args) {
+        Pulumi.run(App::stack);
+    }
+
+    public static void stack(Context ctx) {
+        final var config = ctx.config();
+        final var dockerHubPassword = config.get("dockerHubPassword");
+        var multiPlatform = new Image("multiPlatform", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.multiPlatform")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .platforms(            
+                "plan9/amd64",
+                "plan9/386")
+            .build());
+
+        var registryPush = new Image("registryPush", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.generic")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .tags("docker.io/pulumibot/buildkit-e2e:example")
+            .exports(ExportEntryArgs.builder()
+                .registry(ExportRegistryArgs.builder()
+                    .ociMediaTypes(true)
+                    .push(false)
+                    .build())
+                .build())
+            .registries(RegistryAuthArgs.builder()
+                .address("docker.io")
+                .username("pulumibot")
+                .password(dockerHubPassword)
+                .build())
+            .build());
+
+        var cached = new Image("cached", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.generic")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .cacheTo(CacheToEntryArgs.builder()
+                .local(CacheToLocalArgs.builder()
+                    .dest("tmp/cache")
+                    .mode("max")
+                    .build())
+                .build())
+            .cacheFrom(CacheFromEntryArgs.builder()
+                .local(CacheFromLocalArgs.builder()
+                    .src("tmp/cache")
+                    .build())
+                .build())
+            .build());
+
+        var buildArgs = new Image("buildArgs", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.buildArgs")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .buildArgs(Map.of("SET_ME_TO_TRUE", "true"))
+            .build());
+
+        var targets = new Image("targets", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.targets")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .targets(            
+                "build-me",
+                "also-build-me")
+            .build());
+
+        var namedContexts = new Image("namedContexts", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.namedContexts")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .named(Map.of("golang:latest", Map.of("location", "docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984")))
+                .build())
+            .build());
+
+        var remoteContext = new Image("remoteContext", ImageArgs.builder()        
+            .context(BuildContextArgs.builder()
+                .location("https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile")
+                .build())
+            .build());
+
+        var remoteContextWithInline = new Image("remoteContextWithInline", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .inline(
+                    "FROM busybox\n" +
+                    "COPY hello.c ./")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("https://github.com/docker-library/hello-world.git")
+                .build())
+            .build());
+
+        var inline = new Image("inline", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .inline(
+                    "FROM alpine\n" +
+                    "RUN echo 'This uses an inline Dockerfile! 👍'")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .build());
+
+        var dockerLoad = new Image("dockerLoad", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.generic")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .exports(ExportEntryArgs.builder()
+                .docker(ExportDockerArgs.builder()
+                    .tar(true)
+                    .build())
+                .build())
+            .build());
+
+        ctx.export("platforms", multiPlatform.platforms());
+    }
+}
diff --git a/examples/buildx/py/.gitignore b/examples/buildx/py/.gitignore
new file mode 100644
index 00000000..b664ab4e
--- /dev/null
+++ b/examples/buildx/py/.gitignore
@@ -0,0 +1,2 @@
+*.pyc
+venv/
\ No newline at end of file
diff --git a/examples/buildx/py/Pulumi.yaml b/examples/buildx/py/Pulumi.yaml
new file mode 100644
index 00000000..f790d69b
--- /dev/null
+++ b/examples/buildx/py/Pulumi.yaml
@@ -0,0 +1,3 @@
+name: buildx-examples
+runtime: python
+description: Examples of buildx.Image
diff --git a/examples/buildx/py/__main__.py b/examples/buildx/py/__main__.py
new file mode 100644
index 00000000..e73ef564
--- /dev/null
+++ b/examples/buildx/py/__main__.py
@@ -0,0 +1,120 @@
+import pulumi
+import pulumi_docker as docker
+
+config = pulumi.Config()
+docker_hub_password = config.require("dockerHubPassword")
+multi_platform = docker.buildx.Image("multiPlatform",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.multiPlatform",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ),
+    platforms=[
+        "plan9/amd64",
+        "plan9/386",
+    ])
+registry_push = docker.buildx.Image("registryPush",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.generic",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ),
+    tags=["docker.io/pulumibot/buildkit-e2e:example"],
+    exports=[docker.buildx.ExportEntryArgs(
+        registry=docker.buildx.ExportRegistryArgs(
+            oci_media_types=True,
+            push=False,
+        ),
+    )],
+    registries=[docker.buildx.RegistryAuthArgs(
+        address="docker.io",
+        username="pulumibot",
+        password=docker_hub_password,
+    )])
+cached = docker.buildx.Image("cached",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.generic",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ),
+    cache_to=[docker.buildx.CacheToEntryArgs(
+        local=docker.buildx.CacheToLocalArgs(
+            dest="tmp/cache",
+            mode="max",
+        ),
+    )],
+    cache_from=[docker.buildx.CacheFromEntryArgs(
+        local=docker.buildx.CacheFromLocalArgs(
+            src="tmp/cache",
+        ),
+    )])
+build_args = docker.buildx.Image("buildArgs",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.buildArgs",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ),
+    build_args={
+        "SET_ME_TO_TRUE": "true",
+    })
+targets = docker.buildx.Image("targets",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.targets",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ),
+    targets=[
+        "build-me",
+        "also-build-me",
+    ])
+named_contexts = docker.buildx.Image("namedContexts",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.namedContexts",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+        named={
+            "golang:latest": docker.buildx.ContextArgs(
+                location="docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984",
+            ),
+        },
+    ))
+remote_context = docker.buildx.Image("remoteContext", context=docker.buildx.BuildContextArgs(
+    location="https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile",
+))
+remote_context_with_inline = docker.buildx.Image("remoteContextWithInline",
+    dockerfile=docker.buildx.DockerfileArgs(
+        inline="""FROM busybox
+COPY hello.c ./
+""",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="https://github.com/docker-library/hello-world.git",
+    ))
+inline = docker.buildx.Image("inline",
+    dockerfile=docker.buildx.DockerfileArgs(
+        inline="""FROM alpine
+RUN echo "This uses an inline Dockerfile! 👍"
+""",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ))
+docker_load = docker.buildx.Image("dockerLoad",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.generic",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ),
+    exports=[docker.buildx.ExportEntryArgs(
+        docker=docker.buildx.ExportDockerArgs(
+            tar=True,
+        ),
+    )])
+pulumi.export("platforms", multi_platform.platforms)
diff --git a/examples/buildx/py/app/Dockerfile.buildArgs b/examples/buildx/py/app/Dockerfile.buildArgs
new file mode 100644
index 00000000..438ee017
--- /dev/null
+++ b/examples/buildx/py/app/Dockerfile.buildArgs
@@ -0,0 +1,5 @@
+FROM alpine
+
+ARG SET_ME_TO_TRUE
+RUN [ "$SET_ME_TO_TRUE" = "true" ]
+RUN echo "That's the correct build arg, thanks! 👍"
diff --git a/examples/buildx/py/app/Dockerfile.emptyContext b/examples/buildx/py/app/Dockerfile.emptyContext
new file mode 100644
index 00000000..769593b2
--- /dev/null
+++ b/examples/buildx/py/app/Dockerfile.emptyContext
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo "This image doesn't use any local files, so it doesn't need a context parameter 👍"
diff --git a/examples/buildx/py/app/Dockerfile.generic b/examples/buildx/py/app/Dockerfile.generic
new file mode 100644
index 00000000..e17a80c7
--- /dev/null
+++ b/examples/buildx/py/app/Dockerfile.generic
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo 👍
diff --git a/examples/buildx/py/app/Dockerfile.multiPlatform b/examples/buildx/py/app/Dockerfile.multiPlatform
new file mode 100644
index 00000000..49d3c839
--- /dev/null
+++ b/examples/buildx/py/app/Dockerfile.multiPlatform
@@ -0,0 +1,7 @@
+FROM --platform=$BUILDPLATFORM alpine as build
+RUN echo ${BUILDPLATFORM} > buildplatform
+RUN echo ${TARGETPLATFORM} > targetplatform
+
+FROM build
+RUN cat buildplatform
+RUN cat targetplatform
diff --git a/examples/buildx/py/app/Dockerfile.namedContexts b/examples/buildx/py/app/Dockerfile.namedContexts
new file mode 100644
index 00000000..6e53dba1
--- /dev/null
+++ b/examples/buildx/py/app/Dockerfile.namedContexts
@@ -0,0 +1,5 @@
+# syntax=docker/dockerfile:1.4
+FROM golang:latest
+
+RUN version="$(go version)" && echo $version && [ "$version" = "go version go1.21.7 linux/amd64" ]
+RUN echo "This image uses named contexts to pin golang:latest to a specific SHA 👍"
diff --git a/examples/buildx/py/app/Dockerfile.targets b/examples/buildx/py/app/Dockerfile.targets
new file mode 100644
index 00000000..7cddec71
--- /dev/null
+++ b/examples/buildx/py/app/Dockerfile.targets
@@ -0,0 +1,8 @@
+FROM alpine as build-me
+RUN echo 👍
+
+FROM build-me as also-build-me
+RUN echo 🤙
+
+FROM build-me as dont-build-me
+RUN [ "true" = "false" ]
diff --git a/examples/buildx/py/requirements.txt b/examples/buildx/py/requirements.txt
new file mode 100644
index 00000000..e0b6f666
--- /dev/null
+++ b/examples/buildx/py/requirements.txt
@@ -0,0 +1,2 @@
+pulumi>=3.0.0,<4.0.0
+pulumi-docker>=4.0.0
diff --git a/examples/buildx/ts/.gitignore b/examples/buildx/ts/.gitignore
new file mode 100644
index 00000000..dc902b57
--- /dev/null
+++ b/examples/buildx/ts/.gitignore
@@ -0,0 +1,2 @@
+/bin/
+/node_modules/
\ No newline at end of file
diff --git a/examples/buildx/ts/Pulumi.yaml b/examples/buildx/ts/Pulumi.yaml
new file mode 100644
index 00000000..7822abee
--- /dev/null
+++ b/examples/buildx/ts/Pulumi.yaml
@@ -0,0 +1,3 @@
+name: buildx-examples
+runtime: nodejs
+description: Examples of buildx.Image
diff --git a/examples/buildx/ts/app/Dockerfile.buildArgs b/examples/buildx/ts/app/Dockerfile.buildArgs
new file mode 100644
index 00000000..438ee017
--- /dev/null
+++ b/examples/buildx/ts/app/Dockerfile.buildArgs
@@ -0,0 +1,5 @@
+FROM alpine
+
+ARG SET_ME_TO_TRUE
+RUN [ "$SET_ME_TO_TRUE" = "true" ]
+RUN echo "That's the correct build arg, thanks! 👍"
diff --git a/examples/buildx/ts/app/Dockerfile.emptyContext b/examples/buildx/ts/app/Dockerfile.emptyContext
new file mode 100644
index 00000000..769593b2
--- /dev/null
+++ b/examples/buildx/ts/app/Dockerfile.emptyContext
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo "This image doesn't use any local files, so it doesn't need a context parameter 👍"
diff --git a/examples/buildx/ts/app/Dockerfile.generic b/examples/buildx/ts/app/Dockerfile.generic
new file mode 100644
index 00000000..e17a80c7
--- /dev/null
+++ b/examples/buildx/ts/app/Dockerfile.generic
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo 👍
diff --git a/examples/buildx/ts/app/Dockerfile.multiPlatform b/examples/buildx/ts/app/Dockerfile.multiPlatform
new file mode 100644
index 00000000..49d3c839
--- /dev/null
+++ b/examples/buildx/ts/app/Dockerfile.multiPlatform
@@ -0,0 +1,7 @@
+FROM --platform=$BUILDPLATFORM alpine as build
+RUN echo ${BUILDPLATFORM} > buildplatform
+RUN echo ${TARGETPLATFORM} > targetplatform
+
+FROM build
+RUN cat buildplatform
+RUN cat targetplatform
diff --git a/examples/buildx/ts/app/Dockerfile.namedContexts b/examples/buildx/ts/app/Dockerfile.namedContexts
new file mode 100644
index 00000000..6e53dba1
--- /dev/null
+++ b/examples/buildx/ts/app/Dockerfile.namedContexts
@@ -0,0 +1,5 @@
+# syntax=docker/dockerfile:1.4
+FROM golang:latest
+
+RUN version="$(go version)" && echo $version && [ "$version" = "go version go1.21.7 linux/amd64" ]
+RUN echo "This image uses named contexts to pin golang:latest to a specific SHA 👍"
diff --git a/examples/buildx/ts/app/Dockerfile.targets b/examples/buildx/ts/app/Dockerfile.targets
new file mode 100644
index 00000000..7cddec71
--- /dev/null
+++ b/examples/buildx/ts/app/Dockerfile.targets
@@ -0,0 +1,8 @@
+FROM alpine as build-me
+RUN echo 👍
+
+FROM build-me as also-build-me
+RUN echo 🤙
+
+FROM build-me as dont-build-me
+RUN [ "true" = "false" ]
diff --git a/examples/buildx/ts/index.ts b/examples/buildx/ts/index.ts
new file mode 100644
index 00000000..206bad99
--- /dev/null
+++ b/examples/buildx/ts/index.ts
@@ -0,0 +1,129 @@
+import * as pulumi from "@pulumi/pulumi";
+import * as docker from "@pulumi/docker";
+
+const config = new pulumi.Config();
+const dockerHubPassword = config.require("dockerHubPassword");
+const multiPlatform = new docker.buildx.Image("multiPlatform", {
+    dockerfile: {
+        location: "app/Dockerfile.multiPlatform",
+    },
+    context: {
+        location: "app",
+    },
+    platforms: [
+        "plan9/amd64",
+        "plan9/386",
+    ],
+});
+const registryPush = new docker.buildx.Image("registryPush", {
+    dockerfile: {
+        location: "app/Dockerfile.generic",
+    },
+    context: {
+        location: "app",
+    },
+    tags: ["docker.io/pulumibot/buildkit-e2e:example"],
+    exports: [{
+        registry: {
+            ociMediaTypes: true,
+            push: false,
+        },
+    }],
+    registries: [{
+        address: "docker.io",
+        username: "pulumibot",
+        password: dockerHubPassword,
+    }],
+});
+const cached = new docker.buildx.Image("cached", {
+    dockerfile: {
+        location: "app/Dockerfile.generic",
+    },
+    context: {
+        location: "app",
+    },
+    cacheTo: [{
+        local: {
+            dest: "tmp/cache",
+            mode: "max",
+        },
+    }],
+    cacheFrom: [{
+        local: {
+            src: "tmp/cache",
+        },
+    }],
+});
+const buildArgs = new docker.buildx.Image("buildArgs", {
+    dockerfile: {
+        location: "app/Dockerfile.buildArgs",
+    },
+    context: {
+        location: "app",
+    },
+    buildArgs: {
+        SET_ME_TO_TRUE: "true",
+    },
+});
+const targets = new docker.buildx.Image("targets", {
+    dockerfile: {
+        location: "app/Dockerfile.targets",
+    },
+    context: {
+        location: "app",
+    },
+    targets: [
+        "build-me",
+        "also-build-me",
+    ],
+});
+const namedContexts = new docker.buildx.Image("namedContexts", {
+    dockerfile: {
+        location: "app/Dockerfile.namedContexts",
+    },
+    context: {
+        location: "app",
+        named: {
+            "golang:latest": {
+                location: "docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984",
+            },
+        },
+    },
+});
+const remoteContext = new docker.buildx.Image("remoteContext", {context: {
+    location: "https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile",
+}});
+const remoteContextWithInline = new docker.buildx.Image("remoteContextWithInline", {
+    dockerfile: {
+        inline: `FROM busybox
+COPY hello.c ./
+`,
+    },
+    context: {
+        location: "https://github.com/docker-library/hello-world.git",
+    },
+});
+const inline = new docker.buildx.Image("inline", {
+    dockerfile: {
+        inline: `FROM alpine
+RUN echo "This uses an inline Dockerfile! 👍"
+`,
+    },
+    context: {
+        location: "app",
+    },
+});
+const dockerLoad = new docker.buildx.Image("dockerLoad", {
+    dockerfile: {
+        location: "app/Dockerfile.generic",
+    },
+    context: {
+        location: "app",
+    },
+    exports: [{
+        docker: {
+            tar: true,
+        },
+    }],
+});
+export const platforms = multiPlatform.platforms;
diff --git a/examples/buildx/ts/package.json b/examples/buildx/ts/package.json
new file mode 100644
index 00000000..214501ba
--- /dev/null
+++ b/examples/buildx/ts/package.json
@@ -0,0 +1,10 @@
+{
+	"name": "buildx-examples",
+	"devDependencies": {
+		"@types/node": "^14"
+	},
+	"dependencies": {
+		"typescript": "^4.0.0",
+		"@pulumi/pulumi": "^3.0.0"
+	}
+}
diff --git a/examples/buildx/ts/tsconfig.json b/examples/buildx/ts/tsconfig.json
new file mode 100644
index 00000000..11fc69af
--- /dev/null
+++ b/examples/buildx/ts/tsconfig.json
@@ -0,0 +1,18 @@
+{
+	"compilerOptions": {
+		"strict": true,
+		"outDir": "bin",
+		"target": "es2016",
+		"module": "commonjs",
+		"moduleResolution": "node",
+		"sourceMap": true,
+		"experimentalDecorators": true,
+		"pretty": true,
+		"noFallthroughCasesInSwitch": true,
+		"noImplicitReturns": true,
+		"forceConsistentCasingInFileNames": true
+	},
+	"files": [
+		"index.ts",
+	]
+}
\ No newline at end of file
diff --git a/examples/buildx/yaml/.dockerignore b/examples/buildx/yaml/.dockerignore
new file mode 100644
index 00000000..55418ecb
--- /dev/null
+++ b/examples/buildx/yaml/.dockerignore
@@ -0,0 +1,2 @@
+.dockerignore
+state
diff --git a/examples/buildx/yaml/Pulumi.yaml b/examples/buildx/yaml/Pulumi.yaml
new file mode 100644
index 00000000..3ce7ea04
--- /dev/null
+++ b/examples/buildx/yaml/Pulumi.yaml
@@ -0,0 +1,144 @@
+name: buildx-examples
+runtime: yaml
+description: Examples of buildx.Image
+
+resources:
+  # docker buildx build -f app/Dockerfile.multiPlatform --platform plan9/amd64,plan9/386 app
+  multiPlatform:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.multiPlatform"
+      context:
+        location: "app"
+      platforms:
+        - plan9/amd64
+        - plan9/386
+
+  # docker buildx build -f app/Dockerfile.generic --output=type=registry app
+  registryPush:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.generic"
+      context:
+        location: "app"
+      tags: ["docker.io/pulumibot/buildkit-e2e:example"]
+      exports:
+        - registry:
+            ociMediaTypes: true
+            push: false # Omit this to actually push images.
+      registries:
+        - address: docker.io
+          username: pulumibot
+          password: ${dockerHubPassword}
+
+  # docker buildx build -f app/Dockerfile.generic --cache-to=type=local,dest=tmp/cache,mode=max --cache-from=type=local,src=tmp/cache app
+  cached:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.generic"
+      context:
+        location: "app"
+      cacheTo:
+        - local:
+            dest: tmp/cache
+            mode: max
+      cacheFrom:
+        - local:
+            src: tmp/cache
+
+  # docker buildx build -f app/Dockerfile.buildArgs --build-arg SET_ME_TO_TRUE=true app
+  buildArgs:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.buildArgs"
+      context:
+        location: "app"
+      buildArgs:
+        SET_ME_TO_TRUE: "true"
+
+  # docker buildx build -f app/Dockerfile.targets --target build-me --target also-build-me app
+  targets:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.targets"
+      context:
+        location: "app"
+      targets:
+        - "build-me"
+        - "also-build-me"
+
+  # docker buildx build -f app/Dockerfile.namedContexts \
+  #   --build-context golang:latest=docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984 app
+  namedContexts:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.namedContexts"
+      context:
+        location: app
+        named:
+          "golang:latest":
+            location: "docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984"
+
+  # docker buildx build https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile
+  remoteContext:
+    type: docker:buildx/image:Image
+    properties:
+      context:
+        location: "https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile"
+
+  # docker buildx build -f - https://github.com/docker-library/hello-world.git <<EOF
+  #  FROM busybox
+  #  COPY hello.c ./
+  #  EOF
+  remoteContextWithInline:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        inline: |
+          FROM busybox
+          COPY hello.c ./
+      context:
+        location: "https://github.com/docker-library/hello-world.git"
+
+  # echo "FROM alpine" | docker buildx build -f - .
+  inline:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        inline: |
+          FROM alpine
+          RUN echo "This uses an inline Dockerfile! 👍"
+      context:
+        location: "app"
+
+  # docker buildx build -f app/Dockerfile.generic --load .
+  dockerLoad:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.generic"
+      context:
+        location: "app"
+      exports:
+        - docker:
+            tar: true
+
+  # docker buildx build - < app/Dockerfile.emptyContext
+  #emptyContext:
+  #  type: docker:buildx/image:Image
+  #  properties:
+  #    file: "app/Dockerfile.emptyContext"
+  #    context: "-"
+config:
+  dockerHubPassword:
+    type: string
+    secret: true
+
+outputs:
+  platforms: ${multiPlatform.platforms}
diff --git a/examples/buildx/yaml/app/Dockerfile.buildArgs b/examples/buildx/yaml/app/Dockerfile.buildArgs
new file mode 100644
index 00000000..438ee017
--- /dev/null
+++ b/examples/buildx/yaml/app/Dockerfile.buildArgs
@@ -0,0 +1,5 @@
+FROM alpine
+
+ARG SET_ME_TO_TRUE
+RUN [ "$SET_ME_TO_TRUE" = "true" ]
+RUN echo "That's the correct build arg, thanks! 👍"
diff --git a/examples/buildx/yaml/app/Dockerfile.emptyContext b/examples/buildx/yaml/app/Dockerfile.emptyContext
new file mode 100644
index 00000000..769593b2
--- /dev/null
+++ b/examples/buildx/yaml/app/Dockerfile.emptyContext
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo "This image doesn't use any local files, so it doesn't need a context parameter 👍"
diff --git a/examples/buildx/yaml/app/Dockerfile.generic b/examples/buildx/yaml/app/Dockerfile.generic
new file mode 100644
index 00000000..e17a80c7
--- /dev/null
+++ b/examples/buildx/yaml/app/Dockerfile.generic
@@ -0,0 +1,2 @@
+FROM alpine
+RUN echo 👍
diff --git a/examples/buildx/yaml/app/Dockerfile.multiPlatform b/examples/buildx/yaml/app/Dockerfile.multiPlatform
new file mode 100644
index 00000000..49d3c839
--- /dev/null
+++ b/examples/buildx/yaml/app/Dockerfile.multiPlatform
@@ -0,0 +1,7 @@
+FROM --platform=$BUILDPLATFORM alpine as build
+RUN echo ${BUILDPLATFORM} > buildplatform
+RUN echo ${TARGETPLATFORM} > targetplatform
+
+FROM build
+RUN cat buildplatform
+RUN cat targetplatform
diff --git a/examples/buildx/yaml/app/Dockerfile.namedContexts b/examples/buildx/yaml/app/Dockerfile.namedContexts
new file mode 100644
index 00000000..6e53dba1
--- /dev/null
+++ b/examples/buildx/yaml/app/Dockerfile.namedContexts
@@ -0,0 +1,5 @@
+# syntax=docker/dockerfile:1.4
+FROM golang:latest
+
+RUN version="$(go version)" && echo $version && [ "$version" = "go version go1.21.7 linux/amd64" ]
+RUN echo "This image uses named contexts to pin golang:latest to a specific SHA 👍"
diff --git a/examples/buildx/yaml/app/Dockerfile.targets b/examples/buildx/yaml/app/Dockerfile.targets
new file mode 100644
index 00000000..7cddec71
--- /dev/null
+++ b/examples/buildx/yaml/app/Dockerfile.targets
@@ -0,0 +1,8 @@
+FROM alpine as build-me
+RUN echo 👍
+
+FROM build-me as also-build-me
+RUN echo 🤙
+
+FROM build-me as dont-build-me
+RUN [ "true" = "false" ]
diff --git a/examples/examples_dotnet_test.go b/examples/examples_dotnet_test.go
index 1fe80d0b..f51db679 100644
--- a/examples/examples_dotnet_test.go
+++ b/examples/examples_dotnet_test.go
@@ -27,6 +27,18 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+func TestBuildxCs(t *testing.T) {
+	test := getCsharpBaseOptions(t).
+		With(integration.ProgramTestOptions{
+			Dir: path.Join(getCwd(t), "buildx", "csharp"),
+			Secrets: map[string]string{
+				"dockerHubPassword": os.Getenv("DOCKER_HUB_PASSWORD"),
+			},
+		})
+
+	integration.ProgramTest(t, &test)
+}
+
 func TestNginxCs(t *testing.T) {
 	test := getCsharpBaseOptions(t).
 		With(integration.ProgramTestOptions{
diff --git a/examples/examples_go_test.go b/examples/examples_go_test.go
index 2bb0a9cf..59ae6589 100644
--- a/examples/examples_go_test.go
+++ b/examples/examples_go_test.go
@@ -32,8 +32,21 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-func TestNginxGo(t *testing.T) {
+func TestBuildx(t *testing.T) {
+	test := base.With(integration.ProgramTestOptions{
+		Dependencies: []string{
+			"github.com/pulumi/pulumi-docker/sdk/v4=../sdk",
+		},
+		Dir: path.Join(getCwd(t), "buildx", "go"),
+		Secrets: map[string]string{
+			"dockerHubPassword": os.Getenv("DOCKER_HUB_PASSWORD"),
+		},
+	})
+
+	integration.ProgramTest(t, &test)
+}
 
+func TestNginxGo(t *testing.T) {
 	cwd, err := os.Getwd()
 	if !assert.NoError(t, err) {
 		t.FailNow()
diff --git a/examples/examples_java_test.go b/examples/examples_java_test.go
new file mode 100644
index 00000000..e2ee284e
--- /dev/null
+++ b/examples/examples_java_test.go
@@ -0,0 +1,56 @@
+// Copyright 2024, Pulumi Corporation.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//go:build java || all
+// +build java all
+
+package examples
+
+import (
+	"fmt"
+	"os"
+	"path"
+	"path/filepath"
+	"testing"
+
+	"github.com/pulumi/pulumi/pkg/v3/engine"
+	"github.com/pulumi/pulumi/pkg/v3/testing/integration"
+)
+
+func TestBuildxJava(t *testing.T) {
+	t.Skip("not working")
+
+	test := getJavaBase(t, path.Join("buildx", "java"), integration.ProgramTestOptions{
+		Secrets: map[string]string{
+			"dockerHubPassword": os.Getenv("DOCKER_HUB_PASSWORD"),
+		},
+	})
+
+	integration.ProgramTest(t, &test)
+}
+
+func getJavaBase(t *testing.T, dir string, testSpecificOptions integration.ProgramTestOptions) integration.ProgramTestOptions {
+	repoRoot, err := filepath.Abs(filepath.Join("..", ".."))
+	if err != nil {
+		panic(err)
+	}
+	opts := integration.ProgramTestOptions{
+		Dir: filepath.Join(getCwd(t), dir),
+		Env: []string{fmt.Sprintf("PULUMI_REPO_ROOT=%s", repoRoot)},
+		PrepareProject: func(*engine.Projinfo) error {
+			return nil // needed because defaultPrepareProject does not know about java
+		},
+	}
+	opts = opts.With(getBaseOptions()).With(testSpecificOptions)
+	return opts
+}
diff --git a/examples/examples_nodejs_test.go b/examples/examples_nodejs_test.go
index f0460f6c..e9c2fcf7 100644
--- a/examples/examples_nodejs_test.go
+++ b/examples/examples_nodejs_test.go
@@ -33,6 +33,18 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+func TestBuildxTs(t *testing.T) {
+	test := getJsOptions(t).
+		With(integration.ProgramTestOptions{
+			Dir: path.Join(getCwd(t), "buildx", "ts"),
+			Secrets: map[string]string{
+				"dockerHubPassword": os.Getenv("DOCKER_HUB_PASSWORD"),
+			},
+		})
+
+	integration.ProgramTest(t, &test)
+}
+
 func TestNginxTs(t *testing.T) {
 	test := getJsOptions(t).
 		With(integration.ProgramTestOptions{
diff --git a/examples/examples_py_test.go b/examples/examples_py_test.go
index fd59854d..8e75912e 100644
--- a/examples/examples_py_test.go
+++ b/examples/examples_py_test.go
@@ -24,6 +24,18 @@ import (
 	"github.com/pulumi/pulumi/pkg/v3/testing/integration"
 )
 
+func TestBuildxPy(t *testing.T) {
+	test := getPyOptions(t).
+		With(integration.ProgramTestOptions{
+			Dir: path.Join(getCwd(t), "buildx", "py"),
+			Secrets: map[string]string{
+				"dockerHubPassword": os.Getenv("DOCKER_HUB_PASSWORD"),
+			},
+		})
+
+	integration.ProgramTest(t, &test)
+}
+
 func TestAzureContainerRegistryPy(t *testing.T) {
 	location := os.Getenv("AZURE_LOCATION")
 	if location == "" {
diff --git a/examples/examples_yaml_test.go b/examples/examples_yaml_test.go
index 26825ce3..644d53d1 100644
--- a/examples/examples_yaml_test.go
+++ b/examples/examples_yaml_test.go
@@ -30,6 +30,15 @@ import (
 	"github.com/pulumi/pulumi/pkg/v3/testing/integration"
 )
 
+func TestBuildxYAML(t *testing.T) {
+	integration.ProgramTest(t, &integration.ProgramTestOptions{
+		Dir: path.Join(getCwd(t), "buildx", "yaml"),
+		Secrets: map[string]string{
+			"dockerHubPassword": os.Getenv("DOCKER_HUB_PASSWORD"),
+		},
+	})
+}
+
 func TestUnknownInputsYAML(t *testing.T) {
 	cwd, err := os.Getwd()
 	if !assert.NoError(t, err) {
@@ -86,9 +95,9 @@ func TestBuildOnPreviewYAML(t *testing.T) {
 	var outputBuf bytes.Buffer
 	integration.ProgramTest(t, &integration.ProgramTestOptions{
 		Dir:                      path.Join(cwd, "test-build-on-preview", "yaml"),
-		SkipUpdate:               true, //only run Preview
+		SkipUpdate:               true, // only run Preview
 		SkipExportImport:         true,
-		Verbose:                  true, //we need this to verify the build output logs
+		Verbose:                  true, // we need this to verify the build output logs
 		AllowEmptyPreviewChanges: true,
 		Stdout:                   &outputBuf,
 		ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {
@@ -97,6 +106,7 @@ func TestBuildOnPreviewYAML(t *testing.T) {
 		},
 	})
 }
+
 func TestDockerSwarmYAML(t *testing.T) {
 	cwd, err := os.Getwd()
 	if !assert.NoError(t, err) {
@@ -142,9 +152,9 @@ func TestUnknownsBuildOnPreviewWarnsYAML(t *testing.T) {
 	var outputBuf bytes.Buffer
 	integration.ProgramTest(t, &integration.ProgramTestOptions{
 		Dir:                      path.Join(cwd, "test-unknowns", "yaml-build-on-preview"),
-		SkipUpdate:               true, //only run Preview
+		SkipUpdate:               true, // only run Preview
 		SkipExportImport:         true,
-		Verbose:                  true, //we need this to verify the build output logs
+		Verbose:                  true, // we need this to verify the build output logs
 		AllowEmptyPreviewChanges: true,
 		Stderr:                   &outputBuf,
 		ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {
diff --git a/examples/gen.go b/examples/gen.go
new file mode 100644
index 00000000..7e6c3e8a
--- /dev/null
+++ b/examples/gen.go
@@ -0,0 +1,13 @@
+//go:generate /bin/sh -c "export PATH=\"$(realpath ../bin):$PATH\"; pulumi convert -C buildx/yaml --from yaml --language dotnet --out ../csharp --generate-only"
+//go:generate /bin/sh -c "export PATH=\"$(realpath ../bin):$PATH\"; pulumi convert -C buildx/yaml --from yaml --language go     --out ../go     --generate-only"
+//go:generate /bin/sh -c "export PATH=\"$(realpath ../bin):$PATH\"; pulumi convert -C buildx/yaml --from yaml --language nodejs --out ../ts     --generate-only"
+//go:generate /bin/sh -c "export PATH=\"$(realpath ../bin):$PATH\"; pulumi convert -C buildx/yaml --from yaml --language python --out ../py     --generate-only"
+//go:generate /bin/sh -c "export PATH=\"$(realpath ../bin):$PATH\"; pulumi convert -C buildx/yaml --from yaml --language java   --out ../java   --generate-only"
+//go:generate cp -r buildx/app buildx/yaml/.
+//go:generate cp -r buildx/app buildx/csharp/.
+//go:generate cp -r buildx/app buildx/go/.
+//go:generate cp -r buildx/app buildx/ts/.
+//go:generate cp -r buildx/app buildx/py/.
+//go:generate cp -r buildx/app buildx/java/.
+
+package examples

From afac0f296bfe6574f045681b12708b3794186933 Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Tue, 20 Feb 2024 15:33:26 -0800
Subject: [PATCH 02/11] Add examples for labels and secrets

---
 examples/buildx/app/Dockerfile.secrets        |  4 +++
 examples/buildx/csharp/Program.cs             | 32 +++++++++++++++++++
 examples/buildx/csharp/app/Dockerfile.secrets |  4 +++
 examples/buildx/go/app/Dockerfile.secrets     |  4 +++
 examples/buildx/go/main.go                    | 28 ++++++++++++++++
 examples/buildx/java/app/Dockerfile.secrets   |  4 +++
 .../src/main/java/generated_program/App.java  | 20 ++++++++++++
 examples/buildx/py/__main__.py                | 20 ++++++++++++
 examples/buildx/py/app/Dockerfile.secrets     |  4 +++
 examples/buildx/ts/app/Dockerfile.secrets     |  4 +++
 examples/buildx/ts/index.ts                   | 22 +++++++++++++
 examples/buildx/yaml/Pulumi.yaml              | 22 +++++++++++++
 examples/buildx/yaml/app/Dockerfile.secrets   |  4 +++
 13 files changed, 172 insertions(+)
 create mode 100644 examples/buildx/app/Dockerfile.secrets
 create mode 100644 examples/buildx/csharp/app/Dockerfile.secrets
 create mode 100644 examples/buildx/go/app/Dockerfile.secrets
 create mode 100644 examples/buildx/java/app/Dockerfile.secrets
 create mode 100644 examples/buildx/py/app/Dockerfile.secrets
 create mode 100644 examples/buildx/ts/app/Dockerfile.secrets
 create mode 100644 examples/buildx/yaml/app/Dockerfile.secrets

diff --git a/examples/buildx/app/Dockerfile.secrets b/examples/buildx/app/Dockerfile.secrets
new file mode 100644
index 00000000..513bbd26
--- /dev/null
+++ b/examples/buildx/app/Dockerfile.secrets
@@ -0,0 +1,4 @@
+FROM alpine
+
+RUN --mount=type=secret,id=password [ "$(cat /run/secrets/password)" = "hunter2" ]
+
diff --git a/examples/buildx/csharp/Program.cs b/examples/buildx/csharp/Program.cs
index b8161f40..5ce055ea 100644
--- a/examples/buildx/csharp/Program.cs
+++ b/examples/buildx/csharp/Program.cs
@@ -109,6 +109,38 @@
         },
     });
 
+    var secrets = new Docker.Buildx.Image("secrets", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.secrets",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+        Secrets = 
+        {
+            { "password", "hunter2" },
+        },
+    });
+
+    var labels = new Docker.Buildx.Image("labels", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.generic",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+        Labels = 
+        {
+            { "description", "This image will get a descriptive label 👍" },
+        },
+    });
+
     var targets = new Docker.Buildx.Image("targets", new()
     {
         Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
diff --git a/examples/buildx/csharp/app/Dockerfile.secrets b/examples/buildx/csharp/app/Dockerfile.secrets
new file mode 100644
index 00000000..513bbd26
--- /dev/null
+++ b/examples/buildx/csharp/app/Dockerfile.secrets
@@ -0,0 +1,4 @@
+FROM alpine
+
+RUN --mount=type=secret,id=password [ "$(cat /run/secrets/password)" = "hunter2" ]
+
diff --git a/examples/buildx/go/app/Dockerfile.secrets b/examples/buildx/go/app/Dockerfile.secrets
new file mode 100644
index 00000000..513bbd26
--- /dev/null
+++ b/examples/buildx/go/app/Dockerfile.secrets
@@ -0,0 +1,4 @@
+FROM alpine
+
+RUN --mount=type=secret,id=password [ "$(cat /run/secrets/password)" = "hunter2" ]
+
diff --git a/examples/buildx/go/main.go b/examples/buildx/go/main.go
index b5dca9d7..3fec288c 100644
--- a/examples/buildx/go/main.go
+++ b/examples/buildx/go/main.go
@@ -94,6 +94,34 @@ func main() {
 		if err != nil {
 			return err
 		}
+		_, err = buildx.NewImage(ctx, "secrets", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.secrets"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+			Secrets: pulumi.StringMap{
+				"password": pulumi.String("hunter2"),
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "labels", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.generic"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+			Labels: pulumi.StringMap{
+				"description": pulumi.String("This image will get a descriptive label 👍"),
+			},
+		})
+		if err != nil {
+			return err
+		}
 		_, err = buildx.NewImage(ctx, "targets", &buildx.ImageArgs{
 			Dockerfile: &buildx.DockerfileArgs{
 				Location: pulumi.String("app/Dockerfile.targets"),
diff --git a/examples/buildx/java/app/Dockerfile.secrets b/examples/buildx/java/app/Dockerfile.secrets
new file mode 100644
index 00000000..513bbd26
--- /dev/null
+++ b/examples/buildx/java/app/Dockerfile.secrets
@@ -0,0 +1,4 @@
+FROM alpine
+
+RUN --mount=type=secret,id=password [ "$(cat /run/secrets/password)" = "hunter2" ]
+
diff --git a/examples/buildx/java/src/main/java/generated_program/App.java b/examples/buildx/java/src/main/java/generated_program/App.java
index 8a5acb37..10b2b344 100644
--- a/examples/buildx/java/src/main/java/generated_program/App.java
+++ b/examples/buildx/java/src/main/java/generated_program/App.java
@@ -93,6 +93,26 @@ public static void stack(Context ctx) {
             .buildArgs(Map.of("SET_ME_TO_TRUE", "true"))
             .build());
 
+        var secrets = new Image("secrets", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.secrets")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .secrets(Map.of("password", "hunter2"))
+            .build());
+
+        var labels = new Image("labels", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.generic")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .labels(Map.of("description", "This image will get a descriptive label 👍"))
+            .build());
+
         var targets = new Image("targets", ImageArgs.builder()        
             .dockerfile(DockerfileArgs.builder()
                 .location("app/Dockerfile.targets")
diff --git a/examples/buildx/py/__main__.py b/examples/buildx/py/__main__.py
index e73ef564..e0dd935f 100644
--- a/examples/buildx/py/__main__.py
+++ b/examples/buildx/py/__main__.py
@@ -61,6 +61,26 @@
     build_args={
         "SET_ME_TO_TRUE": "true",
     })
+secrets = docker.buildx.Image("secrets",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.secrets",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ),
+    secrets={
+        "password": "hunter2",
+    })
+labels = docker.buildx.Image("labels",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.generic",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ),
+    labels={
+        "description": "This image will get a descriptive label 👍",
+    })
 targets = docker.buildx.Image("targets",
     dockerfile=docker.buildx.DockerfileArgs(
         location="app/Dockerfile.targets",
diff --git a/examples/buildx/py/app/Dockerfile.secrets b/examples/buildx/py/app/Dockerfile.secrets
new file mode 100644
index 00000000..513bbd26
--- /dev/null
+++ b/examples/buildx/py/app/Dockerfile.secrets
@@ -0,0 +1,4 @@
+FROM alpine
+
+RUN --mount=type=secret,id=password [ "$(cat /run/secrets/password)" = "hunter2" ]
+
diff --git a/examples/buildx/ts/app/Dockerfile.secrets b/examples/buildx/ts/app/Dockerfile.secrets
new file mode 100644
index 00000000..513bbd26
--- /dev/null
+++ b/examples/buildx/ts/app/Dockerfile.secrets
@@ -0,0 +1,4 @@
+FROM alpine
+
+RUN --mount=type=secret,id=password [ "$(cat /run/secrets/password)" = "hunter2" ]
+
diff --git a/examples/buildx/ts/index.ts b/examples/buildx/ts/index.ts
index 206bad99..6a11af7d 100644
--- a/examples/buildx/ts/index.ts
+++ b/examples/buildx/ts/index.ts
@@ -65,6 +65,28 @@ const buildArgs = new docker.buildx.Image("buildArgs", {
         SET_ME_TO_TRUE: "true",
     },
 });
+const secrets = new docker.buildx.Image("secrets", {
+    dockerfile: {
+        location: "app/Dockerfile.secrets",
+    },
+    context: {
+        location: "app",
+    },
+    secrets: {
+        password: "hunter2",
+    },
+});
+const labels = new docker.buildx.Image("labels", {
+    dockerfile: {
+        location: "app/Dockerfile.generic",
+    },
+    context: {
+        location: "app",
+    },
+    labels: {
+        description: "This image will get a descriptive label 👍",
+    },
+});
 const targets = new docker.buildx.Image("targets", {
     dockerfile: {
         location: "app/Dockerfile.targets",
diff --git a/examples/buildx/yaml/Pulumi.yaml b/examples/buildx/yaml/Pulumi.yaml
index 3ce7ea04..62a5fcdd 100644
--- a/examples/buildx/yaml/Pulumi.yaml
+++ b/examples/buildx/yaml/Pulumi.yaml
@@ -60,6 +60,28 @@ resources:
       buildArgs:
         SET_ME_TO_TRUE: "true"
 
+  # PASSWORD=hunter2 docker buildx build -f app/Dockerfile.secrets --secret id=password,env=PASSWORD app
+  secrets:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.secrets"
+      context:
+        location: "app"
+      secrets:
+        password: hunter2
+
+  # docker buildx build -f app/Dockerfile.generic --label "description=This image will get a descriptive label 👍" app
+  labels:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.generic"
+      context:
+        location: "app"
+      labels:
+        description: "This image will get a descriptive label 👍"
+
   # docker buildx build -f app/Dockerfile.targets --target build-me --target also-build-me app
   targets:
     type: docker:buildx/image:Image
diff --git a/examples/buildx/yaml/app/Dockerfile.secrets b/examples/buildx/yaml/app/Dockerfile.secrets
new file mode 100644
index 00000000..513bbd26
--- /dev/null
+++ b/examples/buildx/yaml/app/Dockerfile.secrets
@@ -0,0 +1,4 @@
+FROM alpine
+
+RUN --mount=type=secret,id=password [ "$(cat /run/secrets/password)" = "hunter2" ]
+

From b3cb450d62fad17d510ff509b2c492d1b5a612d7 Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Wed, 21 Feb 2024 15:26:20 -0800
Subject: [PATCH 03/11] not sure why ci-mgmt didn't pick this up...

---
 .github/workflows/master.yml               | 2 ++
 .github/workflows/prerelease.yml           | 2 ++
 .github/workflows/release.yml              | 2 ++
 .github/workflows/run-acceptance-tests.yml | 2 ++
 4 files changed, 8 insertions(+)

diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml
index c38d6a00..b61e800e 100644
--- a/.github/workflows/master.yml
+++ b/.github/workflows/master.yml
@@ -506,6 +506,8 @@ jobs:
       uses: webfactory/ssh-agent@v0.7.0
       with:
         ssh-private-key: ${{ secrets.PRIVATE_SSH_KEY_FOR_DIGITALOCEAN }}
+    - name: Expose GitHub Actions runtime
+      uses: crazy-max/ghaction-github-runtime@v3
     - name: Run tests
       run: cd examples && go test -v -json -count=1 -cover -timeout 2h -tags=${{
         matrix.language }} -parallel 4 . 2>&1 | tee /tmp/gotest.log | gotestfmt
diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml
index 7b701bd6..1f9f51d0 100644
--- a/.github/workflows/prerelease.yml
+++ b/.github/workflows/prerelease.yml
@@ -426,6 +426,8 @@ jobs:
       uses: webfactory/ssh-agent@v0.7.0
       with:
         ssh-private-key: ${{ secrets.PRIVATE_SSH_KEY_FOR_DIGITALOCEAN }}
+    - name: Expose GitHub Actions runtime
+      uses: crazy-max/ghaction-github-runtime@v3
     - name: Run tests
       run: cd examples && go test -v -json -count=1 -cover -timeout 2h -tags=${{
         matrix.language }} -parallel 4 . 2>&1 | tee /tmp/gotest.log | gotestfmt
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 2f77a33a..cc0e6fee 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -474,6 +474,8 @@ jobs:
       uses: webfactory/ssh-agent@v0.7.0
       with:
         ssh-private-key: ${{ secrets.PRIVATE_SSH_KEY_FOR_DIGITALOCEAN }}
+    - name: Expose GitHub Actions runtime
+      uses: crazy-max/ghaction-github-runtime@v3
     - name: Run tests
       run: cd examples && go test -v -json -count=1 -cover -timeout 2h -tags=${{
         matrix.language }} -parallel 4 . 2>&1 | tee /tmp/gotest.log | gotestfmt
diff --git a/.github/workflows/run-acceptance-tests.yml b/.github/workflows/run-acceptance-tests.yml
index f01d8c75..88deefe4 100644
--- a/.github/workflows/run-acceptance-tests.yml
+++ b/.github/workflows/run-acceptance-tests.yml
@@ -423,6 +423,8 @@ jobs:
       uses: webfactory/ssh-agent@v0.7.0
       with:
         ssh-private-key: ${{ secrets.PRIVATE_SSH_KEY_FOR_DIGITALOCEAN }}
+    - name: Expose GitHub Actions runtime
+      uses: crazy-max/ghaction-github-runtime@v3
     - name: Run tests
       if: matrix.testTarget == 'local'
       run: cd examples && go test -v -json -count=1 -cover -timeout 2h -tags=${{

From 29a6f4f998b66929d2bf642ba28d7e19c66fcdaf Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Thu, 29 Feb 2024 21:08:02 -0800
Subject: [PATCH 04/11] Add examples for --ssh and --add-host

---
 examples/buildx/app/Dockerfile.extraHosts     |  3 ++
 examples/buildx/app/Dockerfile.sshMount       |  5 +++
 examples/buildx/csharp/Program.cs             | 35 +++++++++++++++++++
 .../buildx/csharp/app/Dockerfile.extraHosts   |  3 ++
 .../buildx/csharp/app/Dockerfile.sshMount     |  5 +++
 examples/buildx/go/app/Dockerfile.extraHosts  |  3 ++
 examples/buildx/go/app/Dockerfile.sshMount    |  5 +++
 examples/buildx/go/main.go                    | 30 ++++++++++++++++
 .../buildx/java/app/Dockerfile.extraHosts     |  3 ++
 examples/buildx/java/app/Dockerfile.sshMount  |  5 +++
 .../src/main/java/generated_program/App.java  | 22 ++++++++++++
 examples/buildx/py/__main__.py                | 18 ++++++++++
 examples/buildx/py/app/Dockerfile.extraHosts  |  3 ++
 examples/buildx/py/app/Dockerfile.sshMount    |  5 +++
 examples/buildx/ts/app/Dockerfile.extraHosts  |  3 ++
 examples/buildx/ts/app/Dockerfile.sshMount    |  5 +++
 examples/buildx/ts/index.ts                   | 20 +++++++++++
 examples/buildx/yaml/Pulumi.yaml              | 22 ++++++++++++
 .../buildx/yaml/app/Dockerfile.extraHosts     |  3 ++
 examples/buildx/yaml/app/Dockerfile.sshMount  |  5 +++
 20 files changed, 203 insertions(+)
 create mode 100644 examples/buildx/app/Dockerfile.extraHosts
 create mode 100644 examples/buildx/app/Dockerfile.sshMount
 create mode 100644 examples/buildx/csharp/app/Dockerfile.extraHosts
 create mode 100644 examples/buildx/csharp/app/Dockerfile.sshMount
 create mode 100644 examples/buildx/go/app/Dockerfile.extraHosts
 create mode 100644 examples/buildx/go/app/Dockerfile.sshMount
 create mode 100644 examples/buildx/java/app/Dockerfile.extraHosts
 create mode 100644 examples/buildx/java/app/Dockerfile.sshMount
 create mode 100644 examples/buildx/py/app/Dockerfile.extraHosts
 create mode 100644 examples/buildx/py/app/Dockerfile.sshMount
 create mode 100644 examples/buildx/ts/app/Dockerfile.extraHosts
 create mode 100644 examples/buildx/ts/app/Dockerfile.sshMount
 create mode 100644 examples/buildx/yaml/app/Dockerfile.extraHosts
 create mode 100644 examples/buildx/yaml/app/Dockerfile.sshMount

diff --git a/examples/buildx/app/Dockerfile.extraHosts b/examples/buildx/app/Dockerfile.extraHosts
new file mode 100644
index 00000000..35b15f4e
--- /dev/null
+++ b/examples/buildx/app/Dockerfile.extraHosts
@@ -0,0 +1,3 @@
+FROM bash AS base
+
+RUN getent hosts metadata.google.internal
diff --git a/examples/buildx/app/Dockerfile.sshMount b/examples/buildx/app/Dockerfile.sshMount
new file mode 100644
index 00000000..055cb780
--- /dev/null
+++ b/examples/buildx/app/Dockerfile.sshMount
@@ -0,0 +1,5 @@
+FROM alpine
+
+RUN apk add openssh-client
+
+RUN --mount=type=ssh ssh-add -l
diff --git a/examples/buildx/csharp/Program.cs b/examples/buildx/csharp/Program.cs
index 5ce055ea..4bdd5e8e 100644
--- a/examples/buildx/csharp/Program.cs
+++ b/examples/buildx/csharp/Program.cs
@@ -109,6 +109,41 @@
         },
     });
 
+    var extraHosts = new Docker.Buildx.Image("extraHosts", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.extraHosts",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+        AddHosts = new[]
+        {
+            "metadata.google.internal:169.254.169.254",
+        },
+    });
+
+    var sshMount = new Docker.Buildx.Image("sshMount", new()
+    {
+        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
+        {
+            Location = "app/Dockerfile.sshMount",
+        },
+        Context = new Docker.Buildx.Inputs.BuildContextArgs
+        {
+            Location = "app",
+        },
+        Ssh = new[]
+        {
+            new Docker.Buildx.Inputs.SSHArgs
+            {
+                Id = "default",
+            },
+        },
+    });
+
     var secrets = new Docker.Buildx.Image("secrets", new()
     {
         Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
diff --git a/examples/buildx/csharp/app/Dockerfile.extraHosts b/examples/buildx/csharp/app/Dockerfile.extraHosts
new file mode 100644
index 00000000..35b15f4e
--- /dev/null
+++ b/examples/buildx/csharp/app/Dockerfile.extraHosts
@@ -0,0 +1,3 @@
+FROM bash AS base
+
+RUN getent hosts metadata.google.internal
diff --git a/examples/buildx/csharp/app/Dockerfile.sshMount b/examples/buildx/csharp/app/Dockerfile.sshMount
new file mode 100644
index 00000000..055cb780
--- /dev/null
+++ b/examples/buildx/csharp/app/Dockerfile.sshMount
@@ -0,0 +1,5 @@
+FROM alpine
+
+RUN apk add openssh-client
+
+RUN --mount=type=ssh ssh-add -l
diff --git a/examples/buildx/go/app/Dockerfile.extraHosts b/examples/buildx/go/app/Dockerfile.extraHosts
new file mode 100644
index 00000000..35b15f4e
--- /dev/null
+++ b/examples/buildx/go/app/Dockerfile.extraHosts
@@ -0,0 +1,3 @@
+FROM bash AS base
+
+RUN getent hosts metadata.google.internal
diff --git a/examples/buildx/go/app/Dockerfile.sshMount b/examples/buildx/go/app/Dockerfile.sshMount
new file mode 100644
index 00000000..055cb780
--- /dev/null
+++ b/examples/buildx/go/app/Dockerfile.sshMount
@@ -0,0 +1,5 @@
+FROM alpine
+
+RUN apk add openssh-client
+
+RUN --mount=type=ssh ssh-add -l
diff --git a/examples/buildx/go/main.go b/examples/buildx/go/main.go
index 3fec288c..db609854 100644
--- a/examples/buildx/go/main.go
+++ b/examples/buildx/go/main.go
@@ -94,6 +94,36 @@ func main() {
 		if err != nil {
 			return err
 		}
+		_, err = buildx.NewImage(ctx, "extraHosts", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.extraHosts"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+			AddHosts: pulumi.StringArray{
+				pulumi.String("metadata.google.internal:169.254.169.254"),
+			},
+		})
+		if err != nil {
+			return err
+		}
+		_, err = buildx.NewImage(ctx, "sshMount", &buildx.ImageArgs{
+			Dockerfile: &buildx.DockerfileArgs{
+				Location: pulumi.String("app/Dockerfile.sshMount"),
+			},
+			Context: &buildx.BuildContextArgs{
+				Location: pulumi.String("app"),
+			},
+			Ssh: buildx.SSHArray{
+				&buildx.SSHArgs{
+					Id: pulumi.String("default"),
+				},
+			},
+		})
+		if err != nil {
+			return err
+		}
 		_, err = buildx.NewImage(ctx, "secrets", &buildx.ImageArgs{
 			Dockerfile: &buildx.DockerfileArgs{
 				Location: pulumi.String("app/Dockerfile.secrets"),
diff --git a/examples/buildx/java/app/Dockerfile.extraHosts b/examples/buildx/java/app/Dockerfile.extraHosts
new file mode 100644
index 00000000..35b15f4e
--- /dev/null
+++ b/examples/buildx/java/app/Dockerfile.extraHosts
@@ -0,0 +1,3 @@
+FROM bash AS base
+
+RUN getent hosts metadata.google.internal
diff --git a/examples/buildx/java/app/Dockerfile.sshMount b/examples/buildx/java/app/Dockerfile.sshMount
new file mode 100644
index 00000000..055cb780
--- /dev/null
+++ b/examples/buildx/java/app/Dockerfile.sshMount
@@ -0,0 +1,5 @@
+FROM alpine
+
+RUN apk add openssh-client
+
+RUN --mount=type=ssh ssh-add -l
diff --git a/examples/buildx/java/src/main/java/generated_program/App.java b/examples/buildx/java/src/main/java/generated_program/App.java
index 10b2b344..9c9bfe16 100644
--- a/examples/buildx/java/src/main/java/generated_program/App.java
+++ b/examples/buildx/java/src/main/java/generated_program/App.java
@@ -93,6 +93,28 @@ public static void stack(Context ctx) {
             .buildArgs(Map.of("SET_ME_TO_TRUE", "true"))
             .build());
 
+        var extraHosts = new Image("extraHosts", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.extraHosts")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .addHosts("metadata.google.internal:169.254.169.254")
+            .build());
+
+        var sshMount = new Image("sshMount", ImageArgs.builder()        
+            .dockerfile(DockerfileArgs.builder()
+                .location("app/Dockerfile.sshMount")
+                .build())
+            .context(BuildContextArgs.builder()
+                .location("app")
+                .build())
+            .ssh(SSHArgs.builder()
+                .id("default")
+                .build())
+            .build());
+
         var secrets = new Image("secrets", ImageArgs.builder()        
             .dockerfile(DockerfileArgs.builder()
                 .location("app/Dockerfile.secrets")
diff --git a/examples/buildx/py/__main__.py b/examples/buildx/py/__main__.py
index e0dd935f..e7049156 100644
--- a/examples/buildx/py/__main__.py
+++ b/examples/buildx/py/__main__.py
@@ -61,6 +61,24 @@
     build_args={
         "SET_ME_TO_TRUE": "true",
     })
+extra_hosts = docker.buildx.Image("extraHosts",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.extraHosts",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ),
+    add_hosts=["metadata.google.internal:169.254.169.254"])
+ssh_mount = docker.buildx.Image("sshMount",
+    dockerfile=docker.buildx.DockerfileArgs(
+        location="app/Dockerfile.sshMount",
+    ),
+    context=docker.buildx.BuildContextArgs(
+        location="app",
+    ),
+    ssh=[docker.buildx.SSHArgs(
+        id="default",
+    )])
 secrets = docker.buildx.Image("secrets",
     dockerfile=docker.buildx.DockerfileArgs(
         location="app/Dockerfile.secrets",
diff --git a/examples/buildx/py/app/Dockerfile.extraHosts b/examples/buildx/py/app/Dockerfile.extraHosts
new file mode 100644
index 00000000..35b15f4e
--- /dev/null
+++ b/examples/buildx/py/app/Dockerfile.extraHosts
@@ -0,0 +1,3 @@
+FROM bash AS base
+
+RUN getent hosts metadata.google.internal
diff --git a/examples/buildx/py/app/Dockerfile.sshMount b/examples/buildx/py/app/Dockerfile.sshMount
new file mode 100644
index 00000000..055cb780
--- /dev/null
+++ b/examples/buildx/py/app/Dockerfile.sshMount
@@ -0,0 +1,5 @@
+FROM alpine
+
+RUN apk add openssh-client
+
+RUN --mount=type=ssh ssh-add -l
diff --git a/examples/buildx/ts/app/Dockerfile.extraHosts b/examples/buildx/ts/app/Dockerfile.extraHosts
new file mode 100644
index 00000000..35b15f4e
--- /dev/null
+++ b/examples/buildx/ts/app/Dockerfile.extraHosts
@@ -0,0 +1,3 @@
+FROM bash AS base
+
+RUN getent hosts metadata.google.internal
diff --git a/examples/buildx/ts/app/Dockerfile.sshMount b/examples/buildx/ts/app/Dockerfile.sshMount
new file mode 100644
index 00000000..055cb780
--- /dev/null
+++ b/examples/buildx/ts/app/Dockerfile.sshMount
@@ -0,0 +1,5 @@
+FROM alpine
+
+RUN apk add openssh-client
+
+RUN --mount=type=ssh ssh-add -l
diff --git a/examples/buildx/ts/index.ts b/examples/buildx/ts/index.ts
index 6a11af7d..0674b8af 100644
--- a/examples/buildx/ts/index.ts
+++ b/examples/buildx/ts/index.ts
@@ -65,6 +65,26 @@ const buildArgs = new docker.buildx.Image("buildArgs", {
         SET_ME_TO_TRUE: "true",
     },
 });
+const extraHosts = new docker.buildx.Image("extraHosts", {
+    dockerfile: {
+        location: "app/Dockerfile.extraHosts",
+    },
+    context: {
+        location: "app",
+    },
+    addHosts: ["metadata.google.internal:169.254.169.254"],
+});
+const sshMount = new docker.buildx.Image("sshMount", {
+    dockerfile: {
+        location: "app/Dockerfile.sshMount",
+    },
+    context: {
+        location: "app",
+    },
+    ssh: [{
+        id: "default",
+    }],
+});
 const secrets = new docker.buildx.Image("secrets", {
     dockerfile: {
         location: "app/Dockerfile.secrets",
diff --git a/examples/buildx/yaml/Pulumi.yaml b/examples/buildx/yaml/Pulumi.yaml
index 62a5fcdd..cb4a69af 100644
--- a/examples/buildx/yaml/Pulumi.yaml
+++ b/examples/buildx/yaml/Pulumi.yaml
@@ -60,6 +60,28 @@ resources:
       buildArgs:
         SET_ME_TO_TRUE: "true"
 
+  # docker buildx build -f app/Dockerfile.extraHosts --add-host metadata.google.internal:169.254.169.254 app
+  extraHosts:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.extraHosts"
+      context:
+        location: "app"
+      addHosts:
+        - "metadata.google.internal:169.254.169.254"
+
+  # docker buildx build -f app/Dockerfile.sshMount --ssh default app
+  sshMount:
+    type: docker:buildx/image:Image
+    properties:
+      dockerfile:
+        location: "app/Dockerfile.sshMount"
+      context:
+        location: "app"
+      ssh:
+        - id: default
+
   # PASSWORD=hunter2 docker buildx build -f app/Dockerfile.secrets --secret id=password,env=PASSWORD app
   secrets:
     type: docker:buildx/image:Image
diff --git a/examples/buildx/yaml/app/Dockerfile.extraHosts b/examples/buildx/yaml/app/Dockerfile.extraHosts
new file mode 100644
index 00000000..35b15f4e
--- /dev/null
+++ b/examples/buildx/yaml/app/Dockerfile.extraHosts
@@ -0,0 +1,3 @@
+FROM bash AS base
+
+RUN getent hosts metadata.google.internal
diff --git a/examples/buildx/yaml/app/Dockerfile.sshMount b/examples/buildx/yaml/app/Dockerfile.sshMount
new file mode 100644
index 00000000..055cb780
--- /dev/null
+++ b/examples/buildx/yaml/app/Dockerfile.sshMount
@@ -0,0 +1,5 @@
+FROM alpine
+
+RUN apk add openssh-client
+
+RUN --mount=type=ssh ssh-add -l

From 1f77247f255cebad437857e61e42ab8271101dca Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Thu, 29 Feb 2024 21:15:40 -0800
Subject: [PATCH 05/11] Expose --ssh, --no-cache, and --add-host

---
 provider/internal/client.go     | 27 +++++++-----
 provider/internal/image.go      | 76 ++++++++++++++++++++++++++++-----
 provider/internal/image_test.go | 65 +++++++++++++++++++++++++++-
 provider/internal/ssh.go        | 45 +++++++++++++++++++
 4 files changed, 191 insertions(+), 22 deletions(-)
 create mode 100644 provider/internal/ssh.go

diff --git a/provider/internal/client.go b/provider/internal/client.go
index b92e5ec1..edbd4261 100644
--- a/provider/internal/client.go
+++ b/provider/internal/client.go
@@ -238,6 +238,11 @@ func (d *docker) Build(
 		namedContexts[name] = buildx.NamedContext{Path: v}
 	}
 
+	ssh, err := controllerapi.CreateSSH(opts.SSH)
+	if err != nil {
+		return nil, err
+	}
+
 	payload := map[string]buildx.Options{}
 	for _, target := range build.Targets() {
 		targetName := target
@@ -252,18 +257,20 @@ func (d *docker) Build(
 				NamedContexts:    namedContexts,
 				InStream:         strings.NewReader(""),
 			},
-			BuildArgs: opts.BuildArgs,
-			CacheFrom: cacheFrom,
-			CacheTo:   cacheTo,
-			Exports:   exports,
-			NoCache:   opts.NoCache,
-			Labels:    opts.Labels,
-			Platforms: platforms,
-			Pull:      opts.Pull,
-			Tags:      opts.Tags,
-			Target:    target,
+			BuildArgs:  opts.BuildArgs,
+			CacheFrom:  cacheFrom,
+			CacheTo:    cacheTo,
+			Exports:    exports,
+			ExtraHosts: opts.ExtraHosts,
+			NoCache:    opts.NoCache,
+			Labels:     opts.Labels,
+			Platforms:  platforms,
+			Pull:       opts.Pull,
+			Tags:       opts.Tags,
+			Target:     target,
 
 			Session: []session.Attachable{
+				ssh,
 				authprovider.NewDockerAuthProvider(&configfile.ConfigFile{AuthConfigs: auths}, nil),
 				build.Secrets(),
 			},
diff --git a/provider/internal/image.go b/provider/internal/image.go
index 7977c2ce..3998548f 100644
--- a/provider/internal/image.go
+++ b/provider/internal/image.go
@@ -83,6 +83,7 @@ func (i *Image) Annotate(a infer.Annotator) {
 
 // ImageArgs instantiates a new Image.
 type ImageArgs struct {
+	AddHosts       []string          `pulumi:"addHosts,optional"`
 	BuildArgs      map[string]string `pulumi:"buildArgs,optional"`
 	BuildOnPreview bool              `pulumi:"buildOnPreview,optional"`
 	Builder        BuilderConfig     `pulumi:"builder,optional"`
@@ -92,16 +93,23 @@ type ImageArgs struct {
 	Dockerfile     Dockerfile        `pulumi:"dockerfile,optional"`
 	Exports        []ExportEntry     `pulumi:"exports,optional"`
 	Labels         map[string]string `pulumi:"labels,optional"`
+	NoCache        bool              `pulumi:"noCache,optional"`
 	Platforms      []Platform        `pulumi:"platforms,optional"`
 	Pull           bool              `pulumi:"pull,optional"`
 	Registries     []RegistryAuth    `pulumi:"registries,optional"`
-	Secrets        map[string]string `pulumi:"secrets,optional"        provider:"secret"`
+	Secrets        map[string]string `pulumi:"secrets,optional"`
+	SSH            []SSH             `pulumi:"ssh,optional"`
 	Tags           []string          `pulumi:"tags,optional"`
 	Targets        []string          `pulumi:"targets,optional"`
 }
 
 // Annotate describes inputs to the Image resource.
 func (ia *ImageArgs) Annotate(a infer.Annotator) {
+	a.Describe(&ia.AddHosts, dedent(`
+		Custom "host:ip" mappings to use during the build.
+
+		Equivalent to Docker's "--add-host" flag.
+	`))
 	a.Describe(&ia.BuildArgs, dedent(`
 		"ARG" names and values to set during the build.
 		
@@ -153,6 +161,11 @@ func (ia *ImageArgs) Annotate(a infer.Annotator) {
 
 		Equivalent to Docker's "--label" flag.
 	`))
+	a.Describe(&ia.NoCache, dedent(`
+		Do not import cache manifests when building the image.
+
+		Equivalent to Docker's "--no-cache" flag.
+	`))
 	a.Describe(&ia.Platforms, dedent(`
 		Set target platform(s) for the build. Defaults to the host's platform.
 		
@@ -174,6 +187,11 @@ func (ia *ImageArgs) Annotate(a infer.Annotator) {
 
 		Similar to Docker's "--secret" flag.
 	`))
+	a.Describe(&ia.SSH, dedent(`
+		SSH agent socket or keys to expose to the build.
+
+		Equivalent to Docker's "--ssh" flag.
+	`))
 	a.Describe(&ia.Tags, dedent(`
 		Name and optionally a tag (format: "name:tag").
 
@@ -283,18 +301,21 @@ func newCheckFailure(property string, err error) checkFailure {
 
 func (ia *ImageArgs) withoutUnknowns(preview bool) ImageArgs {
 	filtered := ImageArgs{
+		AddHosts:       filter(stringKeeper{preview}, ia.AddHosts...),
 		BuildArgs:      mapKeeper{preview}.keep(ia.BuildArgs),
-		Builder:        ia.Builder,
 		BuildOnPreview: ia.BuildOnPreview,
+		Builder:        ia.Builder,
 		CacheFrom:      filter(stringerKeeper[CacheFromEntry]{preview}, ia.CacheFrom...),
 		CacheTo:        filter(stringerKeeper[CacheToEntry]{preview}, ia.CacheTo...),
 		Context:        contextKeeper{preview}.keep(ia.Context),
 		Dockerfile:     ia.Dockerfile,
 		Exports:        filter(stringerKeeper[ExportEntry]{preview}, ia.Exports...),
 		Labels:         mapKeeper{preview}.keep(ia.Labels),
+		NoCache:        ia.NoCache,
 		Platforms:      filter(stringerKeeper[Platform]{preview}, ia.Platforms...),
 		Pull:           ia.Pull,
 		Registries:     filter(registryKeeper{preview}, ia.Registries...),
+		SSH:            filter(stringerKeeper[SSH]{preview}, ia.SSH...),
 		Secrets:        mapKeeper{preview}.keep(ia.Secrets),
 		Tags:           filter(stringKeeper{preview}, ia.Tags...),
 		Targets:        filter(stringKeeper{preview}, ia.Targets...),
@@ -615,6 +636,19 @@ func (ia *ImageArgs) toBuildOptions(preview bool) (controllerapi.BuildOptions, e
 		cacheTo = append(cacheTo, parsed[0])
 	}
 
+	ssh := []*controllerapi.SSH{}
+	for _, s := range filtered.SSH {
+		parsed, err := buildflags.ParseSSHSpecs([]string{s.String()})
+		if err != nil {
+			multierr = errors.Join(multierr, newCheckFailure("ssh", err))
+			continue
+		}
+		if len(parsed) == 0 {
+			continue
+		}
+		ssh = append(ssh, parsed[0])
+	}
+
 	if filtered.Dockerfile.Location != "" && filtered.Dockerfile.Inline != "" {
 		multierr = errors.Join(
 			multierr,
@@ -639,12 +673,14 @@ func (ia *ImageArgs) toBuildOptions(preview bool) (controllerapi.BuildOptions, e
 		ContextPath:    filtered.Context.Location,
 		DockerfileName: filtered.Dockerfile.Location,
 		Exports:        exports,
+		ExtraHosts:     filtered.AddHosts,
 		Labels:         filtered.Labels,
+		NoCache:        filtered.NoCache,
 		NamedContexts:  filtered.Context.Named.Map(),
 		Platforms:      platforms,
 		Pull:           filtered.Pull,
+		SSH:            ssh,
 		Tags:           filtered.Tags,
-		// Target:         filtered.Targets,
 	}
 
 	return opts, multierr
@@ -846,9 +882,15 @@ func (*Image) Diff(
 	diff := map[string]provider.PropertyDiff{}
 	update := provider.PropertyDiff{Kind: provider.Update}
 
+	if !reflect.DeepEqual(olds.AddHosts, news.AddHosts) {
+		diff["addHosts"] = update
+	}
 	if !reflect.DeepEqual(olds.BuildArgs, news.BuildArgs) {
 		diff["buildArgs"] = update
 	}
+	if olds.BuildOnPreview != news.BuildOnPreview {
+		diff["buildOnPreview"] = update
+	}
 	if !reflect.DeepEqual(olds.Builder, news.Builder) {
 		diff["builder"] = update
 	}
@@ -859,11 +901,10 @@ func (*Image) Diff(
 		diff["cacheTo"] = update
 	}
 	if olds.Context.Location != news.Context.Location {
-		diff["context"] = update
+		diff["context.location"] = update
 	}
-	// Use string comparison to ignore any manifests attached to the export.
-	if fmt.Sprint(olds.Exports) != fmt.Sprint(news.Exports) {
-		diff["exports"] = update
+	if !reflect.DeepEqual(olds.Context.Named, news.Context.Named) {
+		diff["context.named"] = update
 	}
 	if olds.Dockerfile.Location != news.Dockerfile.Location {
 		diff["dockerfile.location"] = update
@@ -871,8 +912,15 @@ func (*Image) Diff(
 	if olds.Dockerfile.Inline != news.Dockerfile.Inline {
 		diff["dockerfile.inline"] = update
 	}
-	if !reflect.DeepEqual(olds.Context.Named, news.Context.Named) {
-		diff["context.named"] = update
+	// Use string comparison to ignore any manifests attached to the export.
+	if fmt.Sprint(olds.Exports) != fmt.Sprint(news.Exports) {
+		diff["exports"] = update
+	}
+	if !reflect.DeepEqual(olds.Labels, news.Labels) {
+		diff["labels"] = update
+	}
+	if !reflect.DeepEqual(olds.NoCache, news.NoCache) {
+		diff["noCache"] = update
 	}
 	if !reflect.DeepEqual(olds.Platforms, news.Platforms) {
 		diff["platforms"] = update
@@ -880,6 +928,12 @@ func (*Image) Diff(
 	if olds.Pull != news.Pull {
 		diff["pull"] = update
 	}
+	if !reflect.DeepEqual(olds.Secrets, news.Secrets) {
+		diff["secrets"] = update
+	}
+	if !reflect.DeepEqual(olds.SSH, news.SSH) {
+		diff["ssh"] = update
+	}
 	if !reflect.DeepEqual(olds.Tags, news.Tags) {
 		diff["tags"] = update
 	}
@@ -890,7 +944,7 @@ func (*Image) Diff(
 	// pull=true indicates that we want to keep base layers up-to-date. In this
 	// case we'll always perform the build.
 	if news.Pull && len(news.Exports) > 0 {
-		diff["exports"] = update
+		diff["contextHash"] = update
 	}
 
 	// Check if anything has changed in our build context.
@@ -915,7 +969,7 @@ func (*Image) Diff(
 			if (oldr.Username == newr.Username) && (oldr.Address == newr.Address) {
 				continue
 			}
-			diff["registries"] = update
+			diff[fmt.Sprintf("registries[%d]", idx)] = update
 			break
 		}
 	}
diff --git a/provider/internal/image_test.go b/provider/internal/image_test.go
index b13eb63f..6fc9f03d 100644
--- a/provider/internal/image_test.go
+++ b/provider/internal/image_test.go
@@ -476,7 +476,16 @@ func TestDiff(t *testing.T) {
 			wantChanges: true,
 		},
 		{
-			name: "diff if file changes",
+			name: "diff if named context changes",
+			olds: func(*testing.T, ImageState) ImageState { return baseState },
+			news: func(_ *testing.T, a ImageArgs) ImageArgs {
+				a.Context.Named = NamedContexts{"foo": Context{Location: "bar"}}
+				return a
+			},
+			wantChanges: true,
+		},
+		{
+			name: "diff if dockerfile location changes",
 			olds: func(*testing.T, ImageState) ImageState { return baseState },
 			news: func(_ *testing.T, a ImageArgs) ImageArgs {
 				a.Dockerfile.Location = "testdata/ignores/basedir/Dockerfile"
@@ -484,6 +493,15 @@ func TestDiff(t *testing.T) {
 			},
 			wantChanges: true,
 		},
+		{
+			name: "diff if dockerfile inline changes",
+			olds: func(*testing.T, ImageState) ImageState { return baseState },
+			news: func(_ *testing.T, a ImageArgs) ImageArgs {
+				a.Dockerfile.Inline = "FROM scratch"
+				return a
+			},
+			wantChanges: true,
+		},
 		{
 			name: "diff if platforms change",
 			olds: func(*testing.T, ImageState) ImageState { return baseState },
@@ -529,6 +547,51 @@ func TestDiff(t *testing.T) {
 			},
 			wantChanges: true,
 		},
+		{
+			name: "diff if targets change",
+			olds: func(*testing.T, ImageState) ImageState { return baseState },
+			news: func(_ *testing.T, a ImageArgs) ImageArgs {
+				a.Targets = []string{"foo"}
+				return a
+			},
+			wantChanges: true,
+		},
+		{
+			name: "diff if pulling",
+			olds: func(*testing.T, ImageState) ImageState { return baseState },
+			news: func(_ *testing.T, a ImageArgs) ImageArgs {
+				a.Pull = true
+				return a
+			},
+			wantChanges: true,
+		},
+		{
+			name: "diff if noCache changes",
+			olds: func(*testing.T, ImageState) ImageState { return baseState },
+			news: func(_ *testing.T, a ImageArgs) ImageArgs {
+				a.NoCache = true
+				return a
+			},
+			wantChanges: true,
+		},
+		{
+			name: "diff if labels change",
+			olds: func(*testing.T, ImageState) ImageState { return baseState },
+			news: func(_ *testing.T, a ImageArgs) ImageArgs {
+				a.Labels = map[string]string{"foo": "bar"}
+				return a
+			},
+			wantChanges: true,
+		},
+		{
+			name: "diff if secrets change",
+			olds: func(*testing.T, ImageState) ImageState { return baseState },
+			news: func(_ *testing.T, a ImageArgs) ImageArgs {
+				a.Secrets = map[string]string{"foo": "bar"}
+				return a
+			},
+			wantChanges: true,
+		},
 	}
 
 	s := newServer(nil)
diff --git a/provider/internal/ssh.go b/provider/internal/ssh.go
new file mode 100644
index 00000000..81b3d5b3
--- /dev/null
+++ b/provider/internal/ssh.go
@@ -0,0 +1,45 @@
+package internal
+
+import (
+	"strings"
+
+	"github.com/pulumi/pulumi-go-provider/infer"
+)
+
+type SSH struct {
+	ID    string   `pulumi:"id"`
+	Paths []string `pulumi:"paths,optional"`
+}
+
+func (s *SSH) Annotate(a infer.Annotator) {
+	a.Describe(&s.ID, dedent(`
+		Useful for distinguishing different servers that are part of the same
+		build.
+
+		A value of "default" is appropriate if only dealing with a single host.
+	`))
+	a.Describe(&s.Paths, dedent(`
+		SSH agent socket or private keys to expose to the build under the given
+		identifier.
+
+		Defaults to "[$SSH_AUTH_SOCK]".
+
+		Note that your keys are **not** automatically added when using an
+		agent. Run "ssh-add -l" locally to confirm which public keys are
+		visible to the agent; these will be exposed to your build.
+	`))
+}
+
+func (s SSH) String() string {
+	if s.ID == "" {
+		return ""
+	}
+
+	r := s.ID
+
+	if len(s.Paths) > 0 {
+		r += "=" + strings.Join(s.Paths, ",")
+	}
+
+	return r
+}

From b7494b410439ba731b399c22da4c36826ca80c3b Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Fri, 1 Mar 2024 10:43:27 -0800
Subject: [PATCH 06/11] Use default Dockerfile location for some examples

---
 .../app/{Dockerfile.generic => Dockerfile}       |  0
 examples/buildx/csharp/Program.cs                | 16 ----------------
 .../app/{Dockerfile.generic => Dockerfile}       |  0
 .../go/app/{Dockerfile.generic => Dockerfile}    |  0
 examples/buildx/go/main.go                       | 12 ------------
 .../java/app/{Dockerfile.generic => Dockerfile}  |  0
 .../src/main/java/generated_program/App.java     | 12 ------------
 examples/buildx/py/__main__.py                   | 12 ------------
 .../py/app/{Dockerfile.generic => Dockerfile}    |  0
 .../ts/app/{Dockerfile.generic => Dockerfile}    |  0
 examples/buildx/ts/index.ts                      | 12 ------------
 examples/buildx/yaml/Pulumi.yaml                 | 16 ++++------------
 .../yaml/app/{Dockerfile.generic => Dockerfile}  |  0
 examples/gen.go                                  |  1 +
 14 files changed, 5 insertions(+), 76 deletions(-)
 rename examples/buildx/app/{Dockerfile.generic => Dockerfile} (100%)
 rename examples/buildx/csharp/app/{Dockerfile.generic => Dockerfile} (100%)
 rename examples/buildx/go/app/{Dockerfile.generic => Dockerfile} (100%)
 rename examples/buildx/java/app/{Dockerfile.generic => Dockerfile} (100%)
 rename examples/buildx/py/app/{Dockerfile.generic => Dockerfile} (100%)
 rename examples/buildx/ts/app/{Dockerfile.generic => Dockerfile} (100%)
 rename examples/buildx/yaml/app/{Dockerfile.generic => Dockerfile} (100%)

diff --git a/examples/buildx/app/Dockerfile.generic b/examples/buildx/app/Dockerfile
similarity index 100%
rename from examples/buildx/app/Dockerfile.generic
rename to examples/buildx/app/Dockerfile
diff --git a/examples/buildx/csharp/Program.cs b/examples/buildx/csharp/Program.cs
index 4bdd5e8e..20204856 100644
--- a/examples/buildx/csharp/Program.cs
+++ b/examples/buildx/csharp/Program.cs
@@ -26,10 +26,6 @@
 
     var registryPush = new Docker.Buildx.Image("registryPush", new()
     {
-        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
-        {
-            Location = "app/Dockerfile.generic",
-        },
         Context = new Docker.Buildx.Inputs.BuildContextArgs
         {
             Location = "app",
@@ -62,10 +58,6 @@
 
     var cached = new Docker.Buildx.Image("cached", new()
     {
-        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
-        {
-            Location = "app/Dockerfile.generic",
-        },
         Context = new Docker.Buildx.Inputs.BuildContextArgs
         {
             Location = "app",
@@ -162,10 +154,6 @@
 
     var labels = new Docker.Buildx.Image("labels", new()
     {
-        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
-        {
-            Location = "app/Dockerfile.generic",
-        },
         Context = new Docker.Buildx.Inputs.BuildContextArgs
         {
             Location = "app",
@@ -250,10 +238,6 @@ RUN echo ""This uses an inline Dockerfile! 👍""
 
     var dockerLoad = new Docker.Buildx.Image("dockerLoad", new()
     {
-        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs
-        {
-            Location = "app/Dockerfile.generic",
-        },
         Context = new Docker.Buildx.Inputs.BuildContextArgs
         {
             Location = "app",
diff --git a/examples/buildx/csharp/app/Dockerfile.generic b/examples/buildx/csharp/app/Dockerfile
similarity index 100%
rename from examples/buildx/csharp/app/Dockerfile.generic
rename to examples/buildx/csharp/app/Dockerfile
diff --git a/examples/buildx/go/app/Dockerfile.generic b/examples/buildx/go/app/Dockerfile
similarity index 100%
rename from examples/buildx/go/app/Dockerfile.generic
rename to examples/buildx/go/app/Dockerfile
diff --git a/examples/buildx/go/main.go b/examples/buildx/go/main.go
index db609854..92baf8a9 100644
--- a/examples/buildx/go/main.go
+++ b/examples/buildx/go/main.go
@@ -26,9 +26,6 @@ func main() {
 			return err
 		}
 		_, err = buildx.NewImage(ctx, "registryPush", &buildx.ImageArgs{
-			Dockerfile: &buildx.DockerfileArgs{
-				Location: pulumi.String("app/Dockerfile.generic"),
-			},
 			Context: &buildx.BuildContextArgs{
 				Location: pulumi.String("app"),
 			},
@@ -55,9 +52,6 @@ func main() {
 			return err
 		}
 		_, err = buildx.NewImage(ctx, "cached", &buildx.ImageArgs{
-			Dockerfile: &buildx.DockerfileArgs{
-				Location: pulumi.String("app/Dockerfile.generic"),
-			},
 			Context: &buildx.BuildContextArgs{
 				Location: pulumi.String("app"),
 			},
@@ -139,9 +133,6 @@ func main() {
 			return err
 		}
 		_, err = buildx.NewImage(ctx, "labels", &buildx.ImageArgs{
-			Dockerfile: &buildx.DockerfileArgs{
-				Location: pulumi.String("app/Dockerfile.generic"),
-			},
 			Context: &buildx.BuildContextArgs{
 				Location: pulumi.String("app"),
 			},
@@ -214,9 +205,6 @@ func main() {
 			return err
 		}
 		_, err = buildx.NewImage(ctx, "dockerLoad", &buildx.ImageArgs{
-			Dockerfile: &buildx.DockerfileArgs{
-				Location: pulumi.String("app/Dockerfile.generic"),
-			},
 			Context: &buildx.BuildContextArgs{
 				Location: pulumi.String("app"),
 			},
diff --git a/examples/buildx/java/app/Dockerfile.generic b/examples/buildx/java/app/Dockerfile
similarity index 100%
rename from examples/buildx/java/app/Dockerfile.generic
rename to examples/buildx/java/app/Dockerfile
diff --git a/examples/buildx/java/src/main/java/generated_program/App.java b/examples/buildx/java/src/main/java/generated_program/App.java
index 9c9bfe16..ffe80bd7 100644
--- a/examples/buildx/java/src/main/java/generated_program/App.java
+++ b/examples/buildx/java/src/main/java/generated_program/App.java
@@ -43,9 +43,6 @@ public static void stack(Context ctx) {
             .build());
 
         var registryPush = new Image("registryPush", ImageArgs.builder()        
-            .dockerfile(DockerfileArgs.builder()
-                .location("app/Dockerfile.generic")
-                .build())
             .context(BuildContextArgs.builder()
                 .location("app")
                 .build())
@@ -64,9 +61,6 @@ public static void stack(Context ctx) {
             .build());
 
         var cached = new Image("cached", ImageArgs.builder()        
-            .dockerfile(DockerfileArgs.builder()
-                .location("app/Dockerfile.generic")
-                .build())
             .context(BuildContextArgs.builder()
                 .location("app")
                 .build())
@@ -126,9 +120,6 @@ public static void stack(Context ctx) {
             .build());
 
         var labels = new Image("labels", ImageArgs.builder()        
-            .dockerfile(DockerfileArgs.builder()
-                .location("app/Dockerfile.generic")
-                .build())
             .context(BuildContextArgs.builder()
                 .location("app")
                 .build())
@@ -186,9 +177,6 @@ public static void stack(Context ctx) {
             .build());
 
         var dockerLoad = new Image("dockerLoad", ImageArgs.builder()        
-            .dockerfile(DockerfileArgs.builder()
-                .location("app/Dockerfile.generic")
-                .build())
             .context(BuildContextArgs.builder()
                 .location("app")
                 .build())
diff --git a/examples/buildx/py/__main__.py b/examples/buildx/py/__main__.py
index e7049156..f5ef5d3c 100644
--- a/examples/buildx/py/__main__.py
+++ b/examples/buildx/py/__main__.py
@@ -15,9 +15,6 @@
         "plan9/386",
     ])
 registry_push = docker.buildx.Image("registryPush",
-    dockerfile=docker.buildx.DockerfileArgs(
-        location="app/Dockerfile.generic",
-    ),
     context=docker.buildx.BuildContextArgs(
         location="app",
     ),
@@ -34,9 +31,6 @@
         password=docker_hub_password,
     )])
 cached = docker.buildx.Image("cached",
-    dockerfile=docker.buildx.DockerfileArgs(
-        location="app/Dockerfile.generic",
-    ),
     context=docker.buildx.BuildContextArgs(
         location="app",
     ),
@@ -90,9 +84,6 @@
         "password": "hunter2",
     })
 labels = docker.buildx.Image("labels",
-    dockerfile=docker.buildx.DockerfileArgs(
-        location="app/Dockerfile.generic",
-    ),
     context=docker.buildx.BuildContextArgs(
         location="app",
     ),
@@ -144,9 +135,6 @@
         location="app",
     ))
 docker_load = docker.buildx.Image("dockerLoad",
-    dockerfile=docker.buildx.DockerfileArgs(
-        location="app/Dockerfile.generic",
-    ),
     context=docker.buildx.BuildContextArgs(
         location="app",
     ),
diff --git a/examples/buildx/py/app/Dockerfile.generic b/examples/buildx/py/app/Dockerfile
similarity index 100%
rename from examples/buildx/py/app/Dockerfile.generic
rename to examples/buildx/py/app/Dockerfile
diff --git a/examples/buildx/ts/app/Dockerfile.generic b/examples/buildx/ts/app/Dockerfile
similarity index 100%
rename from examples/buildx/ts/app/Dockerfile.generic
rename to examples/buildx/ts/app/Dockerfile
diff --git a/examples/buildx/ts/index.ts b/examples/buildx/ts/index.ts
index 0674b8af..3f965d68 100644
--- a/examples/buildx/ts/index.ts
+++ b/examples/buildx/ts/index.ts
@@ -16,9 +16,6 @@ const multiPlatform = new docker.buildx.Image("multiPlatform", {
     ],
 });
 const registryPush = new docker.buildx.Image("registryPush", {
-    dockerfile: {
-        location: "app/Dockerfile.generic",
-    },
     context: {
         location: "app",
     },
@@ -36,9 +33,6 @@ const registryPush = new docker.buildx.Image("registryPush", {
     }],
 });
 const cached = new docker.buildx.Image("cached", {
-    dockerfile: {
-        location: "app/Dockerfile.generic",
-    },
     context: {
         location: "app",
     },
@@ -97,9 +91,6 @@ const secrets = new docker.buildx.Image("secrets", {
     },
 });
 const labels = new docker.buildx.Image("labels", {
-    dockerfile: {
-        location: "app/Dockerfile.generic",
-    },
     context: {
         location: "app",
     },
@@ -156,9 +147,6 @@ RUN echo "This uses an inline Dockerfile! 👍"
     },
 });
 const dockerLoad = new docker.buildx.Image("dockerLoad", {
-    dockerfile: {
-        location: "app/Dockerfile.generic",
-    },
     context: {
         location: "app",
     },
diff --git a/examples/buildx/yaml/Pulumi.yaml b/examples/buildx/yaml/Pulumi.yaml
index cb4a69af..aa638137 100644
--- a/examples/buildx/yaml/Pulumi.yaml
+++ b/examples/buildx/yaml/Pulumi.yaml
@@ -15,12 +15,10 @@ resources:
         - plan9/amd64
         - plan9/386
 
-  # docker buildx build -f app/Dockerfile.generic --output=type=registry app
+  # docker buildx build --output=type=registry app
   registryPush:
     type: docker:buildx/image:Image
     properties:
-      dockerfile:
-        location: "app/Dockerfile.generic"
       context:
         location: "app"
       tags: ["docker.io/pulumibot/buildkit-e2e:example"]
@@ -33,12 +31,10 @@ resources:
           username: pulumibot
           password: ${dockerHubPassword}
 
-  # docker buildx build -f app/Dockerfile.generic --cache-to=type=local,dest=tmp/cache,mode=max --cache-from=type=local,src=tmp/cache app
+  # docker buildx build --cache-to=type=local,dest=tmp/cache,mode=max --cache-from=type=local,src=tmp/cache app
   cached:
     type: docker:buildx/image:Image
     properties:
-      dockerfile:
-        location: "app/Dockerfile.generic"
       context:
         location: "app"
       cacheTo:
@@ -93,12 +89,10 @@ resources:
       secrets:
         password: hunter2
 
-  # docker buildx build -f app/Dockerfile.generic --label "description=This image will get a descriptive label 👍" app
+  # docker buildx build --label "description=This image will get a descriptive label 👍" app
   labels:
     type: docker:buildx/image:Image
     properties:
-      dockerfile:
-        location: "app/Dockerfile.generic"
       context:
         location: "app"
       labels:
@@ -161,12 +155,10 @@ resources:
       context:
         location: "app"
 
-  # docker buildx build -f app/Dockerfile.generic --load .
+  # docker buildx build --load .
   dockerLoad:
     type: docker:buildx/image:Image
     properties:
-      dockerfile:
-        location: "app/Dockerfile.generic"
       context:
         location: "app"
       exports:
diff --git a/examples/buildx/yaml/app/Dockerfile.generic b/examples/buildx/yaml/app/Dockerfile
similarity index 100%
rename from examples/buildx/yaml/app/Dockerfile.generic
rename to examples/buildx/yaml/app/Dockerfile
diff --git a/examples/gen.go b/examples/gen.go
index 7e6c3e8a..336bbb11 100644
--- a/examples/gen.go
+++ b/examples/gen.go
@@ -3,6 +3,7 @@
 //go:generate /bin/sh -c "export PATH=\"$(realpath ../bin):$PATH\"; pulumi convert -C buildx/yaml --from yaml --language nodejs --out ../ts     --generate-only"
 //go:generate /bin/sh -c "export PATH=\"$(realpath ../bin):$PATH\"; pulumi convert -C buildx/yaml --from yaml --language python --out ../py     --generate-only"
 //go:generate /bin/sh -c "export PATH=\"$(realpath ../bin):$PATH\"; pulumi convert -C buildx/yaml --from yaml --language java   --out ../java   --generate-only"
+//go:generate rm -rf buildx/*/app
 //go:generate cp -r buildx/app buildx/yaml/.
 //go:generate cp -r buildx/app buildx/csharp/.
 //go:generate cp -r buildx/app buildx/go/.

From b0b33a8b41353e0f71e6a3b9f75f927660b5db37 Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Fri, 1 Mar 2024 12:58:24 -0800
Subject: [PATCH 07/11] Expose load and push

---
 provider/internal/image.go      | 54 ++++++++++++++++++++++++++++++---
 provider/internal/image_test.go |  9 ++++--
 2 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/provider/internal/image.go b/provider/internal/image.go
index 3998548f..80db7f11 100644
--- a/provider/internal/image.go
+++ b/provider/internal/image.go
@@ -93,9 +93,11 @@ type ImageArgs struct {
 	Dockerfile     Dockerfile        `pulumi:"dockerfile,optional"`
 	Exports        []ExportEntry     `pulumi:"exports,optional"`
 	Labels         map[string]string `pulumi:"labels,optional"`
+	Load           bool              `pulumi:"load,optional"`
 	NoCache        bool              `pulumi:"noCache,optional"`
 	Platforms      []Platform        `pulumi:"platforms,optional"`
 	Pull           bool              `pulumi:"pull,optional"`
+	Push           bool              `pulumi:"push,optional"`
 	Registries     []RegistryAuth    `pulumi:"registries,optional"`
 	Secrets        map[string]string `pulumi:"secrets,optional"`
 	SSH            []SSH             `pulumi:"ssh,optional"`
@@ -161,6 +163,13 @@ func (ia *ImageArgs) Annotate(a infer.Annotator) {
 
 		Equivalent to Docker's "--label" flag.
 	`))
+	a.Describe(&ia.Load, dedent(`
+		When "true" the build will automatically include a "docker" export.
+
+		Defaults to "false".
+
+		Equivalent to Docker's "--load" flag.
+	`))
 	a.Describe(&ia.NoCache, dedent(`
 		Do not import cache manifests when building the image.
 
@@ -176,6 +185,13 @@ func (ia *ImageArgs) Annotate(a infer.Annotator) {
 
 		Equivalent to Docker's "--pull" flag.
 	`))
+	a.Describe(&ia.Push, dedent(`
+		When "true" the build will automatically include a "registry" export.
+
+		Defaults to "false".
+
+		Equivalent to Docker's "--push" flag.
+	`))
 	a.Describe(&ia.Secrets, dedent(`
 		A mapping of secret names to their corresponding values.
 
@@ -311,9 +327,11 @@ func (ia *ImageArgs) withoutUnknowns(preview bool) ImageArgs {
 		Dockerfile:     ia.Dockerfile,
 		Exports:        filter(stringerKeeper[ExportEntry]{preview}, ia.Exports...),
 		Labels:         mapKeeper{preview}.keep(ia.Labels),
+		Load:           ia.Load,
 		NoCache:        ia.NoCache,
 		Platforms:      filter(stringerKeeper[Platform]{preview}, ia.Platforms...),
 		Pull:           ia.Pull,
+		Push:           ia.Push,
 		Registries:     filter(registryKeeper{preview}, ia.Registries...),
 		SSH:            filter(stringerKeeper[SSH]{preview}, ia.SSH...),
 		Secrets:        mapKeeper{preview}.keep(ia.Secrets),
@@ -370,6 +388,13 @@ func (ia ImageArgs) toBuilds(
 		targets = []string{""}
 	}
 
+	if len(opts.Exports) == 0 {
+		ctx.Log(diag.Warning,
+			"No exports were specified so the build will only remain in the local build cache. "+
+				"Use `push` to upload the image to a registry.",
+		)
+	}
+
 	// Check if we need a workaround for multi-platform caching (https://github.com/docker/buildx/issues/1044).
 	if len(ia.Platforms) <= 1 || len(ia.CacheTo) == 0 {
 		return []Build{
@@ -498,11 +523,20 @@ func (ia *ImageArgs) toBuildOptions(preview bool) (controllerapi.BuildOptions, e
 	var multierr error
 
 	if len(ia.Exports) > 1 {
-		multierr = errors.Join(
-			multierr,
+		multierr = errors.Join(multierr,
 			newCheckFailure("exports", fmt.Errorf("multiple exports are currently unsupported")),
 		)
 	}
+	if ia.Push && ia.Load {
+		multierr = errors.Join(multierr,
+			newCheckFailure("push", fmt.Errorf("push and load may not be set together at the moment")),
+		)
+	}
+	if len(ia.Exports) > 0 && (ia.Push || ia.Load) {
+		multierr = errors.Join(multierr,
+			newCheckFailure("exports", fmt.Errorf("exports can't be provided with push or load")),
+		)
+	}
 
 	if ia.Context.Location != "" {
 		abs, err := filepath.Abs(ia.Context.Location)
@@ -541,6 +575,12 @@ func (ia *ImageArgs) toBuildOptions(preview bool) (controllerapi.BuildOptions, e
 	filtered := ia.withoutUnknowns(preview)
 
 	exports := []*controllerapi.ExportEntry{}
+	if filtered.Push {
+		filtered.Exports = append(filtered.Exports, ExportEntry{Raw: "type=registry"})
+	}
+	if filtered.Load {
+		filtered.Exports = append(filtered.Exports, ExportEntry{Raw: "type=docker"})
+	}
 	for _, e := range filtered.Exports {
 		if strings.Count(e.String(), "type=") > 1 {
 			multierr = errors.Join(
@@ -569,8 +609,8 @@ func (ia *ImageArgs) toBuildOptions(preview bool) (controllerapi.BuildOptions, e
 			continue
 		}
 		exports = append(exports, exp)
-
 	}
+
 	if preview {
 		// Don't perform registry pushes during previews.
 		for _, e := range exports {
@@ -919,6 +959,9 @@ func (*Image) Diff(
 	if !reflect.DeepEqual(olds.Labels, news.Labels) {
 		diff["labels"] = update
 	}
+	if olds.Load != news.Load {
+		diff["load"] = update
+	}
 	if !reflect.DeepEqual(olds.NoCache, news.NoCache) {
 		diff["noCache"] = update
 	}
@@ -928,6 +971,9 @@ func (*Image) Diff(
 	if olds.Pull != news.Pull {
 		diff["pull"] = update
 	}
+	if olds.Push != news.Push {
+		diff["push"] = update
+	}
 	if !reflect.DeepEqual(olds.Secrets, news.Secrets) {
 		diff["secrets"] = update
 	}
@@ -943,7 +989,7 @@ func (*Image) Diff(
 
 	// pull=true indicates that we want to keep base layers up-to-date. In this
 	// case we'll always perform the build.
-	if news.Pull && len(news.Exports) > 0 {
+	if news.Pull && (len(news.Exports) > 0 || news.Push || news.Load) {
 		diff["contextHash"] = update
 	}
 
diff --git a/provider/internal/image_test.go b/provider/internal/image_test.go
index 6fc9f03d..c7ae0693 100644
--- a/provider/internal/image_test.go
+++ b/provider/internal/image_test.go
@@ -798,6 +798,10 @@ func TestBuildable(t *testing.T) {
 }
 
 func TestToBuilds(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	pctx := NewMockProviderContext(ctrl)
+	pctx.EXPECT().Log(gomock.Any(), gomock.Any()).AnyTimes()
+
 	t.Run("single-platform caching", func(t *testing.T) {
 		ia := ImageArgs{
 			Tags:      []string{"foo", "bar"},
@@ -821,7 +825,8 @@ func TestToBuilds(t *testing.T) {
 				{Registry: &CacheFromRegistry{Ref: "docker.io/foo/bar:baz"}},
 			},
 		}
-		builds, err := ia.toBuilds(nil, false)
+
+		builds, err := ia.toBuilds(pctx, false)
 		assert.NoError(t, err)
 		assert.Len(t, builds, 1)
 	})
@@ -853,7 +858,7 @@ func TestToBuilds(t *testing.T) {
 			},
 		}
 
-		builds, err := ia.toBuilds(nil, false)
+		builds, err := ia.toBuilds(pctx, false)
 		assert.NoError(t, err)
 
 		assert.Len(t, builds, 3)

From dce588e0f6baf49167ef1f2bec2ec02de61544c8 Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Fri, 1 Mar 2024 14:07:11 -0800
Subject: [PATCH 08/11] CI-aware buildOnPreview behavior

---
 provider/go.mod                 |  3 +-
 provider/go.sum                 | 31 +++++++++++++++--
 provider/internal/image.go      | 28 ++++++++++++---
 provider/internal/image_test.go | 62 +++++++++++++++------------------
 4 files changed, 83 insertions(+), 41 deletions(-)

diff --git a/provider/go.mod b/provider/go.mod
index 8a83e03d..49b708d5 100644
--- a/provider/go.mod
+++ b/provider/go.mod
@@ -22,7 +22,9 @@ require (
 	github.com/pulumi/pulumi-go-provider/integration v0.10.0
 	github.com/pulumi/pulumi-terraform-bridge/v3 v3.76.0
 	github.com/pulumi/pulumi/pkg/v3 v3.107.0
+	github.com/pulumi/pulumi/sdk v1.14.1
 	github.com/pulumi/pulumi/sdk/v3 v3.107.0
+	github.com/sirupsen/logrus v1.9.3
 	github.com/spf13/afero v1.9.5
 	github.com/stretchr/testify v1.8.4
 	github.com/terraform-providers/terraform-provider-docker v0.0.0
@@ -266,7 +268,6 @@ require (
 	github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 // indirect
 	github.com/shibumi/go-pathspec v1.3.0 // indirect
 	github.com/shopspring/decimal v1.3.1 // indirect
-	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/skeema/knownhosts v1.2.1 // indirect
 	github.com/spf13/cast v1.5.0 // indirect
 	github.com/spf13/cobra v1.8.0 // indirect
diff --git a/provider/go.sum b/provider/go.sum
index e501ab43..c24279c2 100644
--- a/provider/go.sum
+++ b/provider/go.sum
@@ -749,6 +749,7 @@ github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm
 github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
 github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
 github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
+github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -760,6 +761,7 @@ github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY
 github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
 github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
 github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
@@ -945,6 +947,7 @@ github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNW
 github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
 github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
 github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
+github.com/cheggaaa/pb v1.0.18/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
 github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
 github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo=
 github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30=
@@ -1162,6 +1165,7 @@ github.com/digitalocean/godo v1.78.0/go.mod h1:GBmu8MkjZmNARE7IXRPmkbbnocNN8+uBm
 github.com/digitalocean/godo v1.88.0/go.mod h1:NRpFznZFvhHjBoqZAaOD3khVzsJ3EibzKqFL4R60dmA=
 github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
 github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
+github.com/djherbis/times v1.2.0/go.mod h1:CGMZlo255K5r4Yw0b9RRfFQpM2y7uOmxg4jm9HsaVf8=
 github.com/djherbis/times v1.5.0 h1:79myA211VwPhFTqUk8xehWrsEO+zcIZj0zT8mXPVARU=
 github.com/djherbis/times v1.5.0/go.mod h1:5q7FDLvbNg1L/KaBmPcWlVR9NmoKo3+ucqUA3ijQhA0=
 github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
@@ -1224,6 +1228,7 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT
 github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
 github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ=
 github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
 github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
 github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
 github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
@@ -1266,6 +1271,7 @@ github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
 github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
@@ -1297,6 +1303,7 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
 github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
 github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
+github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
 github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
 github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
 github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
@@ -1434,6 +1441,7 @@ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6
 github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
 github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
 github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
 github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
@@ -1923,6 +1931,7 @@ github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E
 github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
 github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
+github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
 github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
 github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
 github.com/keybase/go-crypto v0.0.0-20161004153544-93f5b35093ba/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
@@ -2022,6 +2031,7 @@ github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2J
 github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
 github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
 github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
@@ -2254,6 +2264,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
 github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
 github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
+github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
 github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
@@ -2375,8 +2386,6 @@ github.com/pulumi/esc v0.6.2 h1:+z+l8cuwIauLSwXQS0uoI3rqB+YG4SzsZYtHfNoXBvw=
 github.com/pulumi/esc v0.6.2/go.mod h1:jNnYNjzsOgVTjCp0LL24NsCk8ZJxq4IoLQdCT0X7l8k=
 github.com/pulumi/providertest v0.0.10 h1:bx77G0JYPO2Alf/SHRP05XpAYMrboKJkMIVkbFclVhI=
 github.com/pulumi/providertest v0.0.10/go.mod h1:HsxjVsytcMIuNj19w1lT2W0QXY0oReXl1+h6eD2JXP8=
-github.com/pulumi/pulumi-go-provider v0.14.1-0.20240215003739-1759a7d2465b h1:HqGl6ZTRBAR3C/nUAZS6Fq5/NriAm/nrl9UkpUAOojY=
-github.com/pulumi/pulumi-go-provider v0.14.1-0.20240215003739-1759a7d2465b/go.mod h1:Jb4jciqN/Ayi0eiTjbQkhZh/JMvdz8t60Zz7NtJTwN8=
 github.com/pulumi/pulumi-go-provider v0.14.1-0.20240301190400-aeddefa8dc54 h1:ajfW0p4tM1BLYoZRuy+CJoEcT3US6KXmAfCNNzi1Has=
 github.com/pulumi/pulumi-go-provider v0.14.1-0.20240301190400-aeddefa8dc54/go.mod h1:fpmTbPgwdzd4OtUcgE0wYRNzqEY5r88T/c3J1UM/lpA=
 github.com/pulumi/pulumi-go-provider/integration v0.10.0 h1:GHesnrrvkboSjkZpC+qRwjkXBp5d+fSXqlIO92zQxvc=
@@ -2391,6 +2400,8 @@ github.com/pulumi/pulumi-yaml v1.5.0 h1:HfXu+WSFNpycref9CK935cViYJzXwSgHGWM/Repy
 github.com/pulumi/pulumi-yaml v1.5.0/go.mod h1:AvKSmEQv2EkPbpvAQroR1eP1LkJGC8z5NDM34rVWOtg=
 github.com/pulumi/pulumi/pkg/v3 v3.107.0 h1:HRyIl1c9ur0PVQW+GuFL1APBEuGa/fQQMp3F+WluxW8=
 github.com/pulumi/pulumi/pkg/v3 v3.107.0/go.mod h1:7edfZu4FlrXdIn4339tJ+SQX5VKGqbFntmpc8cai0Zg=
+github.com/pulumi/pulumi/sdk v1.14.1 h1:FnUPMgO2AgqvKzSBOy3F2X4nJ8n/SaXCOP2eYSNkAxk=
+github.com/pulumi/pulumi/sdk v1.14.1/go.mod h1:7HttsBa/x9udp5/sO8r/ibSpoQ7/zFo7a16zHWHktZ4=
 github.com/pulumi/pulumi/sdk/v3 v3.107.0 h1:bef+ayh9+4KkAqXih4EjlHfQXRY24NWPwWBIQhBxTjg=
 github.com/pulumi/pulumi/sdk/v3 v3.107.0/go.mod h1:Ml3rpGfyZlI4zQCG7LN2XDSmH4XUNYdyBwJ3yEr/OpI=
 github.com/pulumi/schema-tools v0.1.2 h1:Fd9xvUjgck4NA+7/jSk7InqCUT4Kj940+EcnbQKpfZo=
@@ -2506,6 +2517,7 @@ github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155
 github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
 github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
 github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
 github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
@@ -2527,6 +2539,7 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y
 github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
 github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU=
 github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
+github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
 github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
 github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
 github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
@@ -2561,6 +2574,7 @@ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG
 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
 github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0=
+github.com/texttheater/golang-levenshtein v0.0.0-20191208221605-eb6844b05fc6/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g=
 github.com/texttheater/golang-levenshtein v1.0.1 h1:+cRNoVrfiwufQPhoMzB6N0Yf/Mqajr6t1lOv8GyGE2U=
 github.com/texttheater/golang-levenshtein v1.0.1/go.mod h1:PYAKrbF5sAiq9wd+H82hs7gNaen0CplQ9uvm6+enD/8=
 github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c=
@@ -2579,8 +2593,10 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri
 github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
 github.com/tweekmonster/luser v0.0.0-20161003172636-3fa38070dbd7 h1:X9dsIWPuuEJlPX//UmRKophhOKCGXc46RVIGuttks68=
 github.com/tweekmonster/luser v0.0.0-20161003172636-3fa38070dbd7/go.mod h1:UxoP3EypF8JfGEjAII8jx1q8rQyDnX8qdTCs/UQBVIE=
+github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
 github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
 github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
+github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
 github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
 github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
@@ -2615,6 +2631,7 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV
 github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
 github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
 github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
+github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
 github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
 github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
@@ -2807,6 +2824,7 @@ golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnf
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
@@ -2820,6 +2838,7 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -2939,6 +2958,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -3070,6 +3090,7 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -3118,6 +3139,7 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -3303,6 +3325,7 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw
 golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
+golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
 golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -3682,6 +3705,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
 gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
+gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
@@ -3703,6 +3727,9 @@ gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76
 gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
 gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
+gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
+gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
 gopkg.in/telebot.v3 v3.0.0/go.mod h1:7rExV8/0mDDNu9epSrDm/8j22KLaActH1Tbee6YjzWg=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
diff --git a/provider/internal/image.go b/provider/internal/image.go
index 80db7f11..68f4c0c1 100644
--- a/provider/internal/image.go
+++ b/provider/internal/image.go
@@ -32,6 +32,7 @@ import (
 
 	provider "github.com/pulumi/pulumi-go-provider"
 	"github.com/pulumi/pulumi-go-provider/infer"
+	"github.com/pulumi/pulumi/sdk/go/common/util/ciutil"
 	"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
 	"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
 )
@@ -85,7 +86,7 @@ func (i *Image) Annotate(a infer.Annotator) {
 type ImageArgs struct {
 	AddHosts       []string          `pulumi:"addHosts,optional"`
 	BuildArgs      map[string]string `pulumi:"buildArgs,optional"`
-	BuildOnPreview bool              `pulumi:"buildOnPreview,optional"`
+	BuildOnPreview *bool             `pulumi:"buildOnPreview,optional"`
 	Builder        BuilderConfig     `pulumi:"builder,optional"`
 	CacheFrom      []CacheFromEntry  `pulumi:"cacheFrom,optional"`
 	CacheTo        []CacheToEntry    `pulumi:"cacheTo,optional"`
@@ -124,8 +125,20 @@ func (ia *ImageArgs) Annotate(a infer.Annotator) {
 		Equivalent to Docker's "--build-arg" flag.
 	`))
 	a.Describe(&ia.BuildOnPreview, dedent(`
-		When "true", attempt to build the image during previews. The image will
-		not be pushed to registries, however caches will still be populated.
+		By default, preview behavior depends on the execution environment. If
+		Pulumi detects the operation is running on a CI system (GitHub Actions,
+		Travis CI, Azure Pipelines, etc.) then it will build images during
+		previews as a safeguard. Otherwise, if not running on CI, previews will
+		not build images.
+
+		Setting this to "false" forces previews to never perform builds, and
+		setting it to "true" will always build the image during previews.
+
+		Images built during previews are never exported to registries, however
+		cache manifests are still exported.
+
+		On-disk Dockerfiles are always validated for syntactic correctness
+		regardless of this setting.
 	`))
 	a.Describe(&ia.Builder, dedent(`
 		Builder configuration.
@@ -348,6 +361,13 @@ func (ia *ImageArgs) buildable() bool {
 	return reflect.DeepEqual(ia, &filtered)
 }
 
+func (ia *ImageArgs) shouldBuildOnPreview() bool {
+	if ia.BuildOnPreview != nil {
+		return *ia.BuildOnPreview
+	}
+	return ciutil.IsCI()
+}
+
 type build struct {
 	opts    controllerapi.BuildOptions
 	targets []string
@@ -761,7 +781,7 @@ func (i *Image) Update(
 	}
 	state.ContextHash = hash
 
-	if preview && !input.BuildOnPreview {
+	if preview && !input.shouldBuildOnPreview() {
 		return state, nil
 	}
 	if preview && !input.buildable() {
diff --git a/provider/internal/image_test.go b/provider/internal/image_test.go
index c7ae0693..8eef384d 100644
--- a/provider/internal/image_test.go
+++ b/provider/internal/image_test.go
@@ -51,29 +51,26 @@ func TestLifecycle(t *testing.T) {
 				ctrl := gomock.NewController(t)
 				c := NewMockClient(ctrl)
 				c.EXPECT().Auth(gomock.Any(), "test", gomock.Any()).Return(nil).AnyTimes()
-				gomock.InOrder(
-					c.EXPECT().BuildKitEnabled().Return(true, nil), // Preview.
-					c.EXPECT().BuildKitEnabled().Return(true, nil), // Create.
-					c.EXPECT().Build(gomock.Any(), "test", gomock.AssignableToTypeOf(build{})).DoAndReturn(
-						func(_ provider.Context, name string, b Build) (map[string]*client.SolveResponse, error) {
-							assert.Equal(t, "../testdata/Dockerfile", b.BuildOptions().DockerfileName)
-							return map[string]*client.SolveResponse{
-								b.Targets()[0]: {ExporterResponse: map[string]string{"containerimage.digest": "SHA256:digest"}},
-							}, nil
+				c.EXPECT().BuildKitEnabled().Return(true, nil).AnyTimes()
+				c.EXPECT().Build(gomock.Any(), "test", gomock.AssignableToTypeOf(build{})).DoAndReturn(
+					func(_ provider.Context, name string, b Build) (map[string]*client.SolveResponse, error) {
+						assert.Equal(t, "../testdata/Dockerfile", b.BuildOptions().DockerfileName)
+						return map[string]*client.SolveResponse{
+							b.Targets()[0]: {ExporterResponse: map[string]string{"containerimage.digest": "SHA256:digest"}},
+						}, nil
+					},
+				).AnyTimes()
+				c.EXPECT().Inspect(gomock.Any(), "test", "docker.io/pulumibot/buildkit-e2e").Return(
+					[]manifesttypes.ImageManifest{
+						{
+							Ref:        &manifesttypes.SerializableNamed{Named: digestRef},
+							Descriptor: v1.Descriptor{Platform: &v1.Platform{OS: "linux", Architecture: "arm64"}},
 						},
-					),
-					c.EXPECT().Inspect(gomock.Any(), "test", "docker.io/pulumibot/buildkit-e2e").Return(
-						[]manifesttypes.ImageManifest{
-							{
-								Ref:        &manifesttypes.SerializableNamed{Named: digestRef},
-								Descriptor: v1.Descriptor{Platform: &v1.Platform{OS: "linux", Architecture: "arm64"}},
-							},
-						}, nil,
-					),
-					c.EXPECT().Inspect(gomock.Any(), "test", "docker.io/pulumibot/buildkit-e2e:main"),
-					c.EXPECT().Delete(gomock.Any(), digestRef.String()).Return(
-						[]image.DeleteResponse{{Deleted: "deleted"}, {Untagged: "untagged"}}, nil),
-				)
+					}, nil,
+				).AnyTimes()
+				c.EXPECT().Inspect(gomock.Any(), "test", "docker.io/pulumibot/buildkit-e2e:main").AnyTimes()
+				c.EXPECT().Delete(gomock.Any(), digestRef.String()).Return(
+					[]image.DeleteResponse{{Deleted: "deleted"}, {Untagged: "untagged"}}, nil)
 				return c
 			},
 			op: func(t *testing.T) integration.Operation {
@@ -220,18 +217,15 @@ func TestLifecycle(t *testing.T) {
 			client: func(t *testing.T) Client {
 				ctrl := gomock.NewController(t)
 				c := NewMockClient(ctrl)
-				gomock.InOrder(
-					c.EXPECT().BuildKitEnabled().Return(true, nil), // Preview.
-					c.EXPECT().BuildKitEnabled().Return(true, nil), // Create.
-					c.EXPECT().Build(gomock.Any(), "test", gomock.AssignableToTypeOf(build{})).DoAndReturn(
-						func(_ provider.Context, name string, b Build) (map[string]*client.SolveResponse, error) {
-							assert.Equal(t, "../testdata/Dockerfile", b.BuildOptions().DockerfileName)
-							return map[string]*client.SolveResponse{
-								b.Targets()[0]: {ExporterResponse: map[string]string{"image.name": "test:latest"}},
-							}, nil
-						},
-					),
-				)
+				c.EXPECT().BuildKitEnabled().Return(true, nil).AnyTimes()
+				c.EXPECT().Build(gomock.Any(), "test", gomock.AssignableToTypeOf(build{})).DoAndReturn(
+					func(_ provider.Context, name string, b Build) (map[string]*client.SolveResponse, error) {
+						assert.Equal(t, "../testdata/Dockerfile", b.BuildOptions().DockerfileName)
+						return map[string]*client.SolveResponse{
+							b.Targets()[0]: {ExporterResponse: map[string]string{"image.name": "test:latest"}},
+						}, nil
+					},
+				).AnyTimes()
 				return c
 			},
 			op: func(t *testing.T) integration.Operation {

From f88bfb363254e7fbdcd795e9e73fd5495c619ff2 Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Fri, 1 Mar 2024 15:36:57 -0800
Subject: [PATCH 09/11] Expose network mode

---
 provider/internal/client.go  | 23 ++++++++++++-----------
 provider/internal/image.go   | 15 +++++++++++++++
 provider/internal/network.go | 30 ++++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+), 11 deletions(-)
 create mode 100644 provider/internal/network.go

diff --git a/provider/internal/client.go b/provider/internal/client.go
index edbd4261..d74d538e 100644
--- a/provider/internal/client.go
+++ b/provider/internal/client.go
@@ -257,17 +257,18 @@ func (d *docker) Build(
 				NamedContexts:    namedContexts,
 				InStream:         strings.NewReader(""),
 			},
-			BuildArgs:  opts.BuildArgs,
-			CacheFrom:  cacheFrom,
-			CacheTo:    cacheTo,
-			Exports:    exports,
-			ExtraHosts: opts.ExtraHosts,
-			NoCache:    opts.NoCache,
-			Labels:     opts.Labels,
-			Platforms:  platforms,
-			Pull:       opts.Pull,
-			Tags:       opts.Tags,
-			Target:     target,
+			BuildArgs:   opts.BuildArgs,
+			CacheFrom:   cacheFrom,
+			CacheTo:     cacheTo,
+			Exports:     exports,
+			ExtraHosts:  opts.ExtraHosts,
+			NetworkMode: opts.NetworkMode,
+			NoCache:     opts.NoCache,
+			Labels:      opts.Labels,
+			Platforms:   platforms,
+			Pull:        opts.Pull,
+			Tags:        opts.Tags,
+			Target:      target,
 
 			Session: []session.Attachable{
 				ssh,
diff --git a/provider/internal/image.go b/provider/internal/image.go
index 68f4c0c1..969b52b6 100644
--- a/provider/internal/image.go
+++ b/provider/internal/image.go
@@ -95,6 +95,7 @@ type ImageArgs struct {
 	Exports        []ExportEntry     `pulumi:"exports,optional"`
 	Labels         map[string]string `pulumi:"labels,optional"`
 	Load           bool              `pulumi:"load,optional"`
+	Network        NetworkMode       `pulumi:"network,optional"`
 	NoCache        bool              `pulumi:"noCache,optional"`
 	Platforms      []Platform        `pulumi:"platforms,optional"`
 	Pull           bool              `pulumi:"pull,optional"`
@@ -183,6 +184,13 @@ func (ia *ImageArgs) Annotate(a infer.Annotator) {
 
 		Equivalent to Docker's "--load" flag.
 	`))
+	a.Describe(&ia.Network, dedent(`
+		Set the network mode for "RUN" instructions. Defaults to "default".
+
+		For custom networks, configure your builder with "--driver-opt network=...".
+
+		Equivalent to Docker's "--network" flag.
+	`))
 	a.Describe(&ia.NoCache, dedent(`
 		Do not import cache manifests when building the image.
 
@@ -245,6 +253,8 @@ func (ia *ImageArgs) Annotate(a infer.Annotator) {
 
 		Similar to "docker login".
 	`))
+
+	a.SetDefault(&ia.Network, NetworkModeDefault)
 }
 
 // ImageState is serialized to the program's state file.
@@ -341,6 +351,7 @@ func (ia *ImageArgs) withoutUnknowns(preview bool) ImageArgs {
 		Exports:        filter(stringerKeeper[ExportEntry]{preview}, ia.Exports...),
 		Labels:         mapKeeper{preview}.keep(ia.Labels),
 		Load:           ia.Load,
+		Network:        ia.Network,
 		NoCache:        ia.NoCache,
 		Platforms:      filter(stringerKeeper[Platform]{preview}, ia.Platforms...),
 		Pull:           ia.Pull,
@@ -735,6 +746,7 @@ func (ia *ImageArgs) toBuildOptions(preview bool) (controllerapi.BuildOptions, e
 		Exports:        exports,
 		ExtraHosts:     filtered.AddHosts,
 		Labels:         filtered.Labels,
+		NetworkMode:    string(filtered.Network),
 		NoCache:        filtered.NoCache,
 		NamedContexts:  filtered.Context.Named.Map(),
 		Platforms:      platforms,
@@ -982,6 +994,9 @@ func (*Image) Diff(
 	if olds.Load != news.Load {
 		diff["load"] = update
 	}
+	if olds.Network != news.Network {
+		diff["network"] = update
+	}
 	if !reflect.DeepEqual(olds.NoCache, news.NoCache) {
 		diff["noCache"] = update
 	}
diff --git a/provider/internal/network.go b/provider/internal/network.go
new file mode 100644
index 00000000..0e7902b0
--- /dev/null
+++ b/provider/internal/network.go
@@ -0,0 +1,30 @@
+package internal
+
+import "github.com/pulumi/pulumi-go-provider/infer"
+
+var _ = (infer.Enum[NetworkMode])((*NetworkMode)(nil))
+
+type NetworkMode string
+
+const (
+	NetworkModeDefault NetworkMode = "default"
+	NetworkModeHost    NetworkMode = "host"
+	NetworkModeNone    NetworkMode = "none"
+)
+
+func (NetworkMode) Values() []infer.EnumValue[NetworkMode] {
+	return []infer.EnumValue[NetworkMode]{
+		{
+			Value:       NetworkModeDefault,
+			Description: "The default sandbox network mode.",
+		},
+		{
+			Value:       NetworkModeHost,
+			Description: "Host network mode.",
+		},
+		{
+			Value:       NetworkModeNone,
+			Description: "Disable network access.",
+		},
+	}
+}

From cb5da0cbaf2a963df9f61834e72dd87c042dbbbd Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Tue, 5 Mar 2024 10:47:55 -0800
Subject: [PATCH 10/11] revert manifests on exports

---
 provider/internal/export.go     |   6 --
 provider/internal/image.go      | 184 ++++++++++++++++++++++----------
 provider/internal/image_test.go |  71 ++++++------
 3 files changed, 167 insertions(+), 94 deletions(-)

diff --git a/provider/internal/export.go b/provider/internal/export.go
index 500c44dc..e6595fda 100644
--- a/provider/internal/export.go
+++ b/provider/internal/export.go
@@ -42,8 +42,6 @@ type ExportEntry struct {
 	Raw      Raw             `pulumi:"raw,optional"`
 
 	Disabled bool `pulumi:"disabled,optional"`
-
-	Manifests []Manifest `pulumi:"manifests,optional" provider:"output"`
 }
 
 func (e *ExportEntry) Annotate(a infer.Annotator) {
@@ -73,10 +71,6 @@ func (e *ExportEntry) Annotate(a infer.Annotator) {
 	a.Describe(&e.Disabled, dedent(`
 		When "true" this entry will be excluded. Defaults to "false".
 	`))
-	a.Describe(&e.Manifests, dedent(`
-		An output property populated for exporters that pushed image
-		manifest(s) to a registry.
-	`))
 }
 
 func (e ExportEntry) String() string {
diff --git a/provider/internal/image.go b/provider/internal/image.go
index 969b52b6..f36067de 100644
--- a/provider/internal/image.go
+++ b/provider/internal/image.go
@@ -24,10 +24,12 @@ import (
 	"github.com/docker/buildx/util/buildflags"
 	"github.com/docker/buildx/util/platformutil"
 	"github.com/docker/docker/errdefs"
+	"github.com/moby/buildkit/exporter/containerimage/exptypes"
 	"github.com/moby/buildkit/frontend/dockerfile/instructions"
 	"github.com/moby/buildkit/frontend/dockerfile/parser"
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/session/secrets/secretsprovider"
+	"github.com/opencontainers/go-digest"
 	"github.com/spf13/afero"
 
 	provider "github.com/pulumi/pulumi-go-provider"
@@ -261,8 +263,9 @@ func (ia *ImageArgs) Annotate(a infer.Annotator) {
 type ImageState struct {
 	ImageArgs
 
-	Digests     map[Platform][]string `pulumi:"digests,optional"     provider:"output"`
-	ContextHash string                `pulumi:"contextHash,optional" provider:"internal,output"`
+	Digests     map[string]string `pulumi:"digests"     provider:"output"`
+	ContextHash string            `pulumi:"contextHash" provider:"output"`
+	Ref         string            `pulumi:"ref" provider:"output"`
 }
 
 // Annotate describes outputs of the Image resource.
@@ -270,13 +273,29 @@ func (is *ImageState) Annotate(a infer.Annotator) {
 	is.ImageArgs.Annotate(a)
 
 	a.Describe(&is.Digests, dedent(`
-		A mapping of platform type to refs which were pushed to registries.`,
+		A mapping of target names to the SHA256 digest of their pushed manifest.
+
+		If no target was specified 'default' is used as the target name.
+
+		Pushed manifests can be referenced as "<tag>@<digest>".
+		`,
 	))
 	a.Describe(&is.ContextHash, dedent(`
 		A preliminary hash of the image's build context.
 
 		Pulumi uses this to determine if an image _may_ need to be re-built.
 	`))
+	a.Describe(&is.Ref, dedent(`
+		If the image was pushed to any registries then this will contain a
+		single fully-qualified tag including the build's digest.
+
+		This is only for convenience and may not be appropriate for situations
+		where multiple tags or registries are involved. In those cases this
+		output is not guaranteed to be stable.
+
+		For more control over tags consumed by downstream resources you should
+		use the "Digests" output.
+	`))
 }
 
 // Check validates ImageArgs, sets defaults, and ensures our client is
@@ -372,6 +391,19 @@ func (ia *ImageArgs) buildable() bool {
 	return reflect.DeepEqual(ia, &filtered)
 }
 
+// isExported returns true if the args include a registry export.
+func (ia *ImageArgs) isExported() bool {
+	if ia.Push {
+		return true
+	}
+	for _, e := range ia.Exports {
+		if e.pushed() {
+			return true
+		}
+	}
+	return false
+}
+
 func (ia *ImageArgs) shouldBuildOnPreview() bool {
 	if ia.BuildOnPreview != nil {
 		return *ia.BuildOnPreview
@@ -801,16 +833,42 @@ func (i *Image) Update(
 		return state, nil
 	}
 
-	for _, b := range builds {
+	result, err := cfg.client.Build(ctx, name, builds[0])
+	if err != nil {
+		return state, err
+	}
+	// Run any remaining cache builds.
+	for idx := 1; idx < len(builds); idx++ {
+		b := builds[idx]
 		_, err = cfg.client.Build(ctx, name, b)
 		if err != nil {
 			return state, err
 		}
 	}
 
-	_, _, state, err = i.Read(ctx, name, input, state)
+	var dgst digest.Digest
+	state.Digests = map[string]string{}
+	for target, resp := range result {
+		if d, ok := resp.ExporterResponse[exptypes.ExporterImageDigestKey]; ok {
 
-	return state, err
+			dgst = digest.Digest(d)
+			state.Digests[target] = d
+		}
+	}
+
+	// Take the first registry tag we find and add a digest to it. That becomes
+	// our simplified "ref" output.
+	for _, tag := range state.Tags {
+		ref, ok := addDigest(tag, dgst.String())
+		if !ok {
+			continue
+		}
+
+		state.Ref = ref
+		break
+	}
+
+	return state, nil
 }
 
 // Create initializes a new resource and performs an Update on it.
@@ -845,20 +903,29 @@ func (*Image) Read(
 		}
 	}
 
-	// Do a lookup on all of the tags we expected to push and update our export
-	// with the manifest we pushed.
-	digests := map[Platform][]string{}
-	for idx, export := range state.Exports {
-		// We only care about exports that could have pushed tags.
-		if !export.pushed() {
-			continue
-		}
+	if !state.isExported() {
+		// Nothing was pushed -- all done.
+		return name, input, state, nil
+	}
+
+	tagsToKeep := []string{}
+
+	// Do a lookup on all of the tags at the digests we expect to see.
+	for _, tag := range state.Tags {
+		for _, d := range state.Digests {
+			digest := digest.Digest(d)
 
-		state.Exports[idx].Manifests = []Manifest{}
-		for _, tag := range state.Tags {
-			// Does the tag still exist?
-			infos, err := cfg.client.Inspect(ctx, name, tag)
+			ref, ok := addDigest(tag, digest.String())
+			if !ok {
+				// Not a pushed tag.
+				tagsToKeep = append(tagsToKeep, tag)
+				break
+			}
+
+			// Does a tag with this digest exist?
+			infos, err := cfg.client.Inspect(ctx, name, ref)
 			if err != nil {
+				ctx.Log(diag.Warning, err.Error())
 				continue
 			}
 
@@ -872,38 +939,20 @@ func (*Image) Read(
 					continue
 				}
 
-				os, arch := m.Descriptor.Platform.OS, m.Descriptor.Platform.Architecture
-				platform := Platform(fmt.Sprintf("%s/%s", os, arch))
-
-				if _, ok := digests[platform]; !ok {
-					digests[platform] = []string{}
-				}
-
-				digests[platform] = slices.Compact(append(digests[platform], m.Ref.String()))
-
-				state.Exports[idx].Manifests = append(
-					state.Exports[idx].Manifests,
-					Manifest{
-						Digest: m.Descriptor.Digest.String(),
-						Platform: ManifestPlatform{
-							OS:           m.Descriptor.Platform.OS,
-							Architecture: m.Descriptor.Platform.Architecture,
-						},
-						Ref:  m.Ref.String(),
-						Size: m.Descriptor.Size,
-					},
-				)
+				tagsToKeep = append(tagsToKeep, tag)
+				break
 			}
 		}
 	}
-	state.Digests = digests
 
 	// If we couldn't find the tags we expected then return an empty ID to
 	// delete the resource.
-	if len(input.Tags) > 0 && len(digests) == 0 {
+	if len(input.Tags) > 0 && len(tagsToKeep) == 0 {
 		return "", input, state, nil
 	}
 
+	state.Tags = tagsToKeep
+
 	return name, input, state, nil
 }
 
@@ -919,21 +968,23 @@ func (*Image) Delete(
 
 	var multierr error
 
-	for _, refs := range state.Digests {
-		for _, ref := range refs {
-			deletions, err := cfg.client.Delete(context.Context(ctx), ref)
-			if errdefs.IsNotFound(err) {
-				continue // Nothing to do.
-			}
-			multierr = errors.Join(multierr, err)
+	for _, tag := range state.Tags {
+		ref, err := reference.ParseNamed(tag)
+		if err != nil {
+			continue
+		}
+		deletions, err := cfg.client.Delete(context.Context(ctx), ref.String())
+		if errdefs.IsNotFound(err) {
+			continue // Nothing to do.
+		}
+		multierr = errors.Join(multierr, err)
 
-			for _, d := range deletions {
-				if d.Deleted != "" {
-					ctx.Log(diag.Info, d.Deleted)
-				}
-				if d.Untagged != "" {
-					ctx.Log(diag.Info, d.Untagged)
-				}
+		for _, d := range deletions {
+			if d.Deleted != "" {
+				ctx.Log(diag.Info, d.Deleted)
+			}
+			if d.Untagged != "" {
+				ctx.Log(diag.Info, d.Untagged)
 			}
 		}
 	}
@@ -1073,3 +1124,26 @@ func parseDockerfile(r io.Reader) error {
 	}
 	return nil
 }
+
+// addDigest constructs a tagged ref with an "@<digest>" suffix.
+//
+// Returns false if the given ref was not fully qualified.
+func addDigest(ref, digest string) (string, bool) {
+	named, err := reference.ParseNamed(ref)
+	if err != nil {
+		return "", false
+	}
+	tag := "latest"
+	if tagged, ok := named.(reference.Tagged); ok {
+		tag = tagged.Tag()
+	}
+
+	full, err := reference.Parse(
+		fmt.Sprintf("%s:%s@%s", named.Name(), tag, digest),
+	)
+	if err != nil {
+		return "", false
+	}
+
+	return full.String(), true
+}
diff --git a/provider/internal/image_test.go b/provider/internal/image_test.go
index 8eef384d..bc8acd5e 100644
--- a/provider/internal/image_test.go
+++ b/provider/internal/image_test.go
@@ -2,6 +2,7 @@ package internal
 
 import (
 	"errors"
+	"fmt"
 	"os"
 	"path/filepath"
 	"testing"
@@ -13,6 +14,7 @@ import (
 	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types/image"
 	"github.com/moby/buildkit/client"
+	"github.com/moby/buildkit/exporter/containerimage/exptypes"
 	v1 "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -34,9 +36,7 @@ func TestLifecycle(t *testing.T) {
 		return NewMockClient(ctrl)
 	}
 
-	ref, err := reference.ParseNamed("docker.io/pulumibot/buildkit-e2e")
-	require.NoError(t, err)
-	digestRef, err := reference.WithDigest(ref, "sha256:7f9fc9830dbb80a7fd23b9903d587b6433a9e87969de4868e551bc2959e63dd9")
+	_, err := reference.ParseNamed("docker.io/pulumibot/buildkit-e2e")
 	require.NoError(t, err)
 
 	tests := []struct {
@@ -56,20 +56,17 @@ func TestLifecycle(t *testing.T) {
 					func(_ provider.Context, name string, b Build) (map[string]*client.SolveResponse, error) {
 						assert.Equal(t, "../testdata/Dockerfile", b.BuildOptions().DockerfileName)
 						return map[string]*client.SolveResponse{
-							b.Targets()[0]: {ExporterResponse: map[string]string{"containerimage.digest": "SHA256:digest"}},
+							b.Targets()[0]: {
+								ExporterResponse: map[string]string{
+									exptypes.ExporterImageDigestKey: "sha256:98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4",
+								},
+							},
 						}, nil
 					},
 				).AnyTimes()
-				c.EXPECT().Inspect(gomock.Any(), "test", "docker.io/pulumibot/buildkit-e2e").Return(
-					[]manifesttypes.ImageManifest{
-						{
-							Ref:        &manifesttypes.SerializableNamed{Named: digestRef},
-							Descriptor: v1.Descriptor{Platform: &v1.Platform{OS: "linux", Architecture: "arm64"}},
-						},
-					}, nil,
-				).AnyTimes()
-				c.EXPECT().Inspect(gomock.Any(), "test", "docker.io/pulumibot/buildkit-e2e:main").AnyTimes()
-				c.EXPECT().Delete(gomock.Any(), digestRef.String()).Return(
+				c.EXPECT().Delete(gomock.Any(), "docker.io/pulumibot/buildkit-e2e").Return(
+					[]image.DeleteResponse{{Deleted: "deleted"}, {Untagged: "untagged"}}, nil)
+				c.EXPECT().Delete(gomock.Any(), "docker.io/pulumibot/buildkit-e2e:main").Return(
 					[]image.DeleteResponse{{Deleted: "deleted"}, {Untagged: "untagged"}}, nil)
 				return c
 			},
@@ -278,8 +275,7 @@ func TestDelete(t *testing.T) {
 	t.Run("image was already deleted", func(t *testing.T) {
 		ctrl := gomock.NewController(t)
 		client := NewMockClient(ctrl)
-		client.EXPECT().Delete(gomock.Any(), "foo").Return(nil, errNotFound{})
-		client.EXPECT().Delete(gomock.Any(), "bar").Return(nil, errNotFound{})
+		client.EXPECT().Delete(gomock.Any(), "docker.io/pulumi/test:foo").Return(nil, errNotFound{})
 
 		s := newServer(client)
 		err := s.Configure(provider.ConfigureRequest{})
@@ -289,12 +285,15 @@ func TestDelete(t *testing.T) {
 			ID:  "foo,bar",
 			Urn: _fakeURN,
 			Properties: resource.PropertyMap{
+				"tags": resource.NewArrayProperty([]resource.PropertyValue{
+					resource.NewStringProperty("docker.io/pulumi/test:foo"),
+				}),
+				"push": resource.NewBoolProperty(true),
 				"digests": resource.NewObjectProperty(resource.PropertyMap{
-					"digests": resource.NewArrayProperty([]resource.PropertyValue{
-						resource.NewStringProperty("foo"),
-						resource.NewStringProperty("bar"),
-					}),
+					"default": resource.NewStringProperty("sha256:foo"),
 				}),
+				"contextHash": resource.NewStringProperty(""),
+				"ref":         resource.NewStringProperty(""),
 			},
 		})
 		assert.NoError(t, err)
@@ -303,24 +302,26 @@ func TestDelete(t *testing.T) {
 
 func TestRead(t *testing.T) {
 	tag := "docker.io/pulumi/pulumitest"
+	digest := "sha256:3be99cafdcd80a8e620da56bdc215acab6213bb608d3d492c0ba1807128786a1"
 	ref, err := reference.ParseNamed(tag)
 	require.NoError(t, err)
 
 	ctrl := gomock.NewController(t)
 	client := NewMockClient(ctrl)
-	client.EXPECT().Inspect(gomock.Any(), "my-image", tag).Return([]manifesttypes.ImageManifest{
-		{
-			Descriptor: v1.Descriptor{Platform: &v1.Platform{Architecture: "arm64"}},
-			Ref:        &manifesttypes.SerializableNamed{Named: ref},
-		},
-		{
-			Descriptor: v1.Descriptor{Platform: &v1.Platform{Architecture: "unknown"}},
-			Ref:        &manifesttypes.SerializableNamed{Named: ref},
-		},
-		{
-			Descriptor: v1.Descriptor{},
-		},
-	}, nil)
+	client.EXPECT().Inspect(gomock.Any(), "my-image", fmt.Sprintf("%s:latest@%s", tag, digest)).Return(
+		[]manifesttypes.ImageManifest{
+			{
+				Descriptor: v1.Descriptor{Platform: &v1.Platform{Architecture: "arm64"}},
+				Ref:        &manifesttypes.SerializableNamed{Named: ref},
+			},
+			{
+				Descriptor: v1.Descriptor{Platform: &v1.Platform{Architecture: "unknown"}},
+				Ref:        &manifesttypes.SerializableNamed{Named: ref},
+			},
+			{
+				Descriptor: v1.Descriptor{},
+			},
+		}, nil)
 
 	s := newServer(client)
 	err = s.Configure(provider.ConfigureRequest{})
@@ -338,6 +339,9 @@ func TestRead(t *testing.T) {
 			"tags": resource.NewArrayProperty([]resource.PropertyValue{
 				resource.NewStringProperty(tag),
 			}),
+			"digests": resource.NewObjectProperty(resource.PropertyMap{
+				"default": resource.NewStringProperty(digest),
+			}),
 		},
 	})
 	require.NoError(t, err)
@@ -355,6 +359,7 @@ func TestDiff(t *testing.T) {
 	baseState := ImageState{
 		ContextHash: "f04bea490d45e7ae69d542846511e7c90eb683deaa1e0df19e9fca4d227265c2",
 		ImageArgs:   baseArgs,
+		Digests:     map[string]string{},
 	}
 
 	tests := []struct {

From 0690ba6a9dd4124fbc7e2888186dc891adbf0d7a Mon Sep 17 00:00:00 2001
From: Bryce Lampe <bryce@pulumi.com>
Date: Tue, 5 Mar 2024 14:24:32 -0800
Subject: [PATCH 11/11] Regenerate SDK

---
 .../cmd/pulumi-resource-docker/schema.json    | 165 +++++---
 sdk/dotnet/Buildx/Enums.cs                    |  38 ++
 sdk/dotnet/Buildx/Image.cs                    | 187 ++++++++-
 sdk/dotnet/Buildx/Inputs/ExportEntryArgs.cs   |  13 -
 sdk/dotnet/Buildx/Inputs/ManifestArgs.cs      |  44 --
 .../Buildx/Inputs/ManifestPlatformArgs.cs     |  32 --
 sdk/dotnet/Buildx/Inputs/SSHArgs.cs           |  48 +++
 sdk/dotnet/Buildx/Outputs/ExportEntry.cs      |   8 -
 sdk/dotnet/Buildx/Outputs/Manifest.cs         |  49 ---
 sdk/dotnet/Buildx/Outputs/ManifestPlatform.cs |  35 --
 sdk/dotnet/Buildx/Outputs/SSH.cs              |  45 ++
 sdk/go/docker/buildx/image.go                 | 257 +++++++++++-
 sdk/go/docker/buildx/pulumiEnums.go           | 174 ++++++++
 sdk/go/docker/buildx/pulumiTypes.go           | 343 +++++++---------
 .../java/com/pulumi/docker/buildx/Image.java  | 213 +++++++++-
 .../com/pulumi/docker/buildx/ImageArgs.java   | 386 +++++++++++++++++-
 .../docker/buildx/enums/NetworkMode.java      |  46 +++
 .../docker/buildx/inputs/ExportEntryArgs.java |  54 ---
 .../docker/buildx/inputs/ManifestArgs.java    | 207 ----------
 .../buildx/inputs/ManifestPlatformArgs.java   | 125 ------
 .../pulumi/docker/buildx/inputs/SSHArgs.java  | 182 +++++++++
 .../docker/buildx/outputs/ExportEntry.java    |  28 --
 .../docker/buildx/outputs/Manifest.java       | 129 ------
 .../buildx/outputs/ManifestPlatform.java      |  81 ----
 .../com/pulumi/docker/buildx/outputs/SSH.java | 104 +++++
 sdk/nodejs/buildx/image.ts                    | 156 ++++++-
 sdk/nodejs/types/enums/buildx/index.ts        |  17 +
 sdk/nodejs/types/input.ts                     |  56 +--
 sdk/nodejs/types/output.ts                    |  56 +--
 sdk/python/pulumi_docker/buildx/_enums.py     |  16 +
 sdk/python/pulumi_docker/buildx/_inputs.py    | 183 +++------
 sdk/python/pulumi_docker/buildx/image.py      | 346 +++++++++++++++-
 sdk/python/pulumi_docker/buildx/outputs.py    | 147 +++----
 33 files changed, 2529 insertions(+), 1441 deletions(-)
 delete mode 100644 sdk/dotnet/Buildx/Inputs/ManifestArgs.cs
 delete mode 100644 sdk/dotnet/Buildx/Inputs/ManifestPlatformArgs.cs
 create mode 100644 sdk/dotnet/Buildx/Inputs/SSHArgs.cs
 delete mode 100644 sdk/dotnet/Buildx/Outputs/Manifest.cs
 delete mode 100644 sdk/dotnet/Buildx/Outputs/ManifestPlatform.cs
 create mode 100644 sdk/dotnet/Buildx/Outputs/SSH.cs
 create mode 100644 sdk/java/src/main/java/com/pulumi/docker/buildx/enums/NetworkMode.java
 delete mode 100644 sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ManifestArgs.java
 delete mode 100644 sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ManifestPlatformArgs.java
 create mode 100644 sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/SSHArgs.java
 delete mode 100644 sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/Manifest.java
 delete mode 100644 sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/ManifestPlatform.java
 create mode 100644 sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/SSH.java

diff --git a/provider/cmd/pulumi-resource-docker/schema.json b/provider/cmd/pulumi-resource-docker/schema.json
index c25cd489..0fdb8a63 100644
--- a/provider/cmd/pulumi-resource-docker/schema.json
+++ b/provider/cmd/pulumi-resource-docker/schema.json
@@ -726,13 +726,6 @@
                     "$ref": "#/types/docker:buildx/image:ExportLocal",
                     "description": "Export to a local directory as files and directories."
                 },
-                "manifests": {
-                    "type": "array",
-                    "items": {
-                        "$ref": "#/types/docker:buildx/image:Manifest"
-                    },
-                    "description": "An output property populated for exporters that pushed image\nmanifest(s) to a registry."
-                },
                 "oci": {
                     "$ref": "#/types/docker:buildx/image:ExportOCI",
                     "description": "Identical to the Docker exporter but uses OCI media types by default."
@@ -961,48 +954,21 @@
                 "dest"
             ]
         },
-        "docker:buildx/image:Manifest": {
-            "properties": {
-                "digest": {
-                    "type": "string",
-                    "description": "The SHA256 digest of the manifest."
-                },
-                "platform": {
-                    "$ref": "#/types/docker:buildx/image:ManifestPlatform",
-                    "description": "The manifest's platform."
-                },
-                "ref": {
-                    "type": "string",
-                    "description": "The manifest's canonical ref."
+        "docker:buildx/image:NetworkMode": {
+            "type": "string",
+            "enum": [
+                {
+                    "description": "The default sandbox network mode.",
+                    "value": "default"
                 },
-                "size": {
-                    "type": "integer",
-                    "description": "The size of the manifest in bytes."
-                }
-            },
-            "type": "object",
-            "required": [
-                "digest",
-                "platform",
-                "ref",
-                "size"
-            ]
-        },
-        "docker:buildx/image:ManifestPlatform": {
-            "properties": {
-                "architecture": {
-                    "type": "string",
-                    "description": "The manifest's architecture."
+                {
+                    "description": "Host network mode.",
+                    "value": "host"
                 },
-                "os": {
-                    "type": "string",
-                    "description": "The manifest's operating systen."
+                {
+                    "description": "Disable network access.",
+                    "value": "none"
                 }
-            },
-            "type": "object",
-            "required": [
-                "os",
-                "architecture"
             ]
         },
         "docker:buildx/image:Platform": {
@@ -1115,6 +1081,25 @@
                 "address"
             ]
         },
+        "docker:buildx/image:SSH": {
+            "properties": {
+                "id": {
+                    "type": "string",
+                    "description": "Useful for distinguishing different servers that are part of the same\nbuild.\n\nA value of `default` is appropriate if only dealing with a single host."
+                },
+                "paths": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "description": "SSH agent socket or private keys to expose to the build under the given\nidentifier.\n\nDefaults to `[$SSH_AUTH_SOCK]`.\n\nNote that your keys are **not** automatically added when using an\nagent. Run `ssh-add -l` locally to confirm which public keys are\nvisible to the agent; these will be exposed to your build."
+                }
+            },
+            "type": "object",
+            "required": [
+                "id"
+            ]
+        },
         "docker:config/registryAuth:registryAuth": {
             "properties": {
                 "address": {
@@ -3089,6 +3074,13 @@
         "docker:buildx/image:Image": {
             "description": "A Docker image built using buildx -- Docker's interface to the improved\nBuildKit backend.\n\n## Stability\n\n**This resource is experimental and subject to change.**\n\nAPI types are unstable. Subsequent releases _may_ require manual edits\nto your state file(s) in order to adopt API changes.\n\n`retainOnDelete: true` is recommended with this resource until it is\nstable. This enables future API changes to be adopted more easily by renaming\nresources.\n\nOnly use this resource if you understand and accept the risks.\n\n## Migrating v3 and v4 Image resources\n\nThe `buildx.Image` resource provides a superset of functionality over the `Image` resources available in versions 3 and 4 of the Pulumi Docker provider.\nExisting `Image` resources can be converted to `build.Image` resources with minor modifications.\n\n### Behavioral differences\n\nThere are several key behavioral differences to keep in mind when transitioning images to the new `buildx.Image` resource.\n\n#### Previews\n\nVersion `3.x` of the Pulumi Docker provider always builds images during preview operations.\nThis is helpful as a safeguard to prevent \"broken\" images from merging, but users found the behavior unnecessarily redundant when running previews and updates locally.\n\nVersion `4.x` changed build-on-preview behavior to be opt-in.\nBy default, `v4.x` `Image` resources do _not_ build during previews, but this behavior can be toggled with the `buildOnPreview` option.\nSome users felt this made previews in CI less helpful because they no longer detected bad images by default.\n\nThe default behavior of the `buildx.Image` resource has been changed to strike a better balance between CI use cases and manual updates.\nBy default, Pulumi will now only build `buildx.Image` resources during previews when it detects a CI environment like GitHub Actions.\nPreviews run in non-CI environments will not build images.\nThis behavior is still configurable with `buildOnPreview`.\n\n#### Push behavior\n\nVersions `3.x` and `4.x` of the Pulumi Docker provider attempt to push images to remote registries by default.\nThey expose a `skipPush: true` option to disable pushing.\n\nThe `buildx.Image` resource matches the Docker CLI's behavior and does not push images anywhere by default.\n\nTo push images to a registry you can include `push: true` (equivalent to Docker's `--push` flag) or configure an `export` of type `registry` (equivalent to Docker's `--output type=registry`).\nLike Docker, if an image is configured without exports you will see a warning with instructions for how to enable pushing, but the build will still proceed normally.\n\n#### Secrets\n\nVersion `3.x` of the Pulumi Docker provider supports secrets by way of the `extraOptions` field.\n\nVersion `4.x` of the Pulumi Docker provider does not support secrets.\n\nThe `buildx.Image` resource supports secrets but does not require those secrets to exist on-disk or in environment variables.\nInstead, they should be passed directly as values.\n(Please be sure to familiarize yourself with Pulumi's [native secret handling](https://www.pulumi.com/docs/concepts/secrets/).)\nPulumi also provides [ESC](https://www.pulumi.com/product/esc/) to make it easier to share secrets across stacks and environments.\n\n#### Caching\n\nVersion `3.x` of the Pulumi Docker provider exposes `cacheFrom: bool | { stages: [...] }`.\nIt builds targets individually and pushes them to separate images for caching.\n\nVersion `4.x` exposes a similar parameter `cacheFrom: { images: [...] }` which pushes and pulls inline caches.\n\nBoth versions 3 and 4 require specific environment variables to be set and deviate from Docker's native caching behavior.\nThis can result in inefficient builds due to unnecessary image pulls, repeated file transfers, etc.\n\nThe `buildx.Image` resource delegates all caching behavior to Docker.\n`cacheFrom` and `cacheTo` options (equivalent to Docker's `--cache-to` and `--cache-from`) are exposed and provide additional cache targets, such as local disk, S3 storage, etc.\n\n#### Outputs\n\nTODO:\n\n#### Tag deletion and refreshes\n\nVersions 3 and 4 of Pulumi Docker provider do not delete tags when the `Image` resource is deleted, nor do they confirm expected tags exist during `refresh` operations.\n\nThe `buidx.Image` will query your registries during `refresh` to ensure the expected tags exist.\nIf any are missing a subsequent `update` will push them.\n\nWhen a `buildx.Image` is deleted, it will _attempt_ to also delete any pushed tags.\nDeletion of remote tags is not guaranteed, because not all registries currently support this operation (`docker.io` in particular).\n\nUse the [`retainOnDelete: true`](https://www.pulumi.com/docs/concepts/options/retainondelete/) option if you do not want tags deleted.\n\n### Example migration\n\nExamples of \"fully-featured\" `v3` and `v4` `Image` resources are shown below, along with an example `buildx.Image` resource showing how they would look after migration.\n\nThe `v3` resource leverages `buildx` via a `DOCKER_BUILDKIT` environment variable and CLI flags passed in with `extraOption`.\nAfter migration, the environment variable is no longer needed and CLI flags are now properties on the `buildx.Image`.\nIn almost all cases, properties of `buildx.Image` are named after the Docker CLI flag they correspond to.\n\nThe `v4` resource is less functional than its `v3` counterpart because it lacks the flexibility of `extraOptions`.\nIt it is shown with parameters similar to the `v3` example for completeness.\n\n{{% examples %}}\n## Example Usage\n{{% example %}}\n### v3/v4 migration\n\n```typescript\n\n// v3 Image\nconst v3 = new docker.Image(\"v3-image\", {\n  imageName: \"myregistry.com/user/repo:latest\",\n  localImageName: \"local-tag\",\n  skipPush: false,\n  build: {\n    dockerfile: \"./Dockerfile\",\n    context: \"../app\",\n    target: \"mytarget\",\n    args: {\n      MY_BUILD_ARG: \"foo\",\n    },\n    env: {\n      DOCKER_BUILDKIT: \"1\",\n    },\n    extraOptions: [\n      \"--cache-from\",\n      \"type=registry,myregistry.com/user/repo:cache\",\n      \"--cache-to\",\n      \"type=registry,myregistry.com/user/repo:cache\",\n      \"--add-host\",\n      \"metadata.google.internal:169.254.169.254\",\n      \"--secret\",\n      \"id=mysecret,src=/local/secret\",\n      \"--ssh\",\n      \"default=/home/runner/.ssh/id_ed25519\",\n      \"--network\",\n      \"host\",\n      \"--platform\",\n      \"linux/amd64\",\n    ],\n  },\n  registry: {\n    server: \"myregistry.com\",\n    username: \"username\",\n    password: pulumi.secret(\"password\"),\n  },\n});\n\n// v3 Image after migrating to buildx.Image\nconst v3Migrated = new docker.buildx.Image(\"v3-to-buildx\", {\n    tags: [\"myregistry.com/user/repo:latest\", \"local-tag\"],\n    push: true,\n    dockerfile: {\n        location: \"./Dockerfile\",\n    },\n    context: {\n        location: \"../app\",\n    },\n    targets: [\"mytarget\"],\n    buildArgs: {\n        MY_BUILD_ARG: \"foo\",\n    },\n    cacheFrom: [{ registry: { ref: \"myregistry.com/user/repo:cache\" } }],\n    cacheTo: [{ registry: { ref: \"myregistry.com/user/repo:cache\" } }],\n    secrets: {\n        mysecret: \"value\",\n    },\n    addHosts: [\"metadata.google.internal:169.254.169.254\"],\n    ssh: {\n        default: [\"/home/runner/.ssh/id_ed25519\"],\n    },\n    network: \"host\",\n    platforms: [\"linux/amd64\"],\n    registries: [{\n        address: \"myregistry.com\",\n        username: \"username\",\n        password: pulumi.secret(\"password\"),\n    }],\n});\n\n\n// v4 Image\nconst v4 = new docker.Image(\"v4-image\", {\n    imageName: \"myregistry.com/user/repo:latest\",\n    skipPush: false,\n    build: {\n        dockerfile: \"./Dockerfile\",\n        context: \"../app\",\n        target: \"mytarget\",\n        args: {\n            MY_BUILD_ARG: \"foo\",\n        },\n        cacheFrom: {\n            images: [\"myregistry.com/user/repo:cache\"],\n        },\n        addHosts: [\"metadata.google.internal:169.254.169.254\"],\n        network: \"host\",\n        platform: \"linux/amd64\",\n    },\n    buildOnPreview: true,\n    registry: {\n        server: \"myregistry.com\",\n        username: \"username\",\n        password: pulumi.secret(\"password\"),\n    },\n});\n\n// v4 Image after migrating to buildx.Image\nconst v4Migrated = new docker.buildx.Image(\"v4-to-buildx\", {\n    tags: [\"myregistry.com/user/repo:latest\"],\n    push: true,\n    dockerfile: {\n        location: \"./Dockerfile\",\n    },\n    context: {\n        location: \"../app\",\n    },\n    targets: [\"mytarget\"],\n    buildArgs: {\n        MY_BUILD_ARG: \"foo\",\n    },\n    cacheFrom: [{ registry: { ref: \"myregistry.com/user/repo:cache\" } }],\n    cacheTo: [{ registry: { ref: \"myregistry.com/user/repo:cache\" } }],\n    addHosts: [\"metadata.google.internal:169.254.169.254\"],\n    network: \"host\",\n    platforms: [\"linux/amd64\"],\n    registries: [{\n        address: \"myregistry.com\",\n        username: \"username\",\n        password: pulumi.secret(\"password\"),\n    }],\n});\n\n```\n\n{{% /example %}}\n\n\n{{% examples %}}\n## Example Usage\n{{% example %}}\n### Push to AWS ECR with caching\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as aws from \"@pulumi/aws\";\nimport * as docker from \"@pulumi/docker\";\n\nconst ecrRepository = new aws.ecr.Repository(\"ecr-repository\", {});\nconst authToken = aws.ecr.getAuthorizationTokenOutput({\n    registryId: ecrRepository.registryId,\n});\nconst myImage = new docker.buildx.Image(\"my-image\", {\n    cacheFrom: [{\n        registry: {\n            ref: pulumi.interpolate`${ecrRepository.repositoryUrl}:cache`,\n        },\n    }],\n    cacheTo: [{\n        registry: {\n            imageManifest: true,\n            ociMediaTypes: true,\n            ref: pulumi.interpolate`${ecrRepository.repositoryUrl}:cache`,\n        },\n    }],\n    context: {\n        location: \"./app\",\n    },\n    dockerfile: {\n        location: \"./Dockerfile\",\n    },\n    push: true,\n    registries: [{\n        address: ecrRepository.repositoryUrl,\n        password: authToken.apply(authToken =\u003e authToken.password),\n        username: authToken.apply(authToken =\u003e authToken.userName),\n    }],\n    tags: [pulumi.interpolate`${ecrRepository.repositoryUrl}:latest`],\n});\n```\n```python\nimport pulumi\nimport pulumi_aws as aws\nimport pulumi_docker as docker\n\necr_repository = aws.ecr.Repository(\"ecr-repository\")\nauth_token = aws.ecr.get_authorization_token_output(registry_id=ecr_repository.registry_id)\nmy_image = docker.buildx.Image(\"my-image\",\n    cache_from=[docker.buildx.CacheFromEntryArgs(\n        registry=docker.buildx.CacheFromRegistryArgs(\n            ref=ecr_repository.repository_url.apply(lambda repository_url: f\"{repository_url}:cache\"),\n        ),\n    )],\n    cache_to=[docker.buildx.CacheToEntryArgs(\n        registry=docker.buildx.CacheToRegistryArgs(\n            image_manifest=True,\n            oci_media_types=True,\n            ref=ecr_repository.repository_url.apply(lambda repository_url: f\"{repository_url}:cache\"),\n        ),\n    )],\n    context=docker.buildx.BuildContextArgs(\n        location=\"./app\",\n    ),\n    dockerfile=docker.buildx.DockerfileArgs(\n        location=\"./Dockerfile\",\n    ),\n    push=True,\n    registries=[docker.buildx.RegistryAuthArgs(\n        address=ecr_repository.repository_url,\n        password=auth_token.password,\n        username=auth_token.user_name,\n    )],\n    tags=[ecr_repository.repository_url.apply(lambda repository_url: f\"{repository_url}:latest\")])\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Aws = Pulumi.Aws;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var ecrRepository = new Aws.Ecr.Repository(\"ecr-repository\");\n\n    var authToken = Aws.Ecr.GetAuthorizationToken.Invoke(new()\n    {\n        RegistryId = ecrRepository.RegistryId,\n    });\n\n    var myImage = new Docker.Buildx.Image(\"my-image\", new()\n    {\n        CacheFrom = new[]\n        {\n            new Docker.Buildx.Inputs.CacheFromEntryArgs\n            {\n                Registry = new Docker.Buildx.Inputs.CacheFromRegistryArgs\n                {\n                    Ref = ecrRepository.RepositoryUrl.Apply(repositoryUrl =\u003e $\"{repositoryUrl}:cache\"),\n                },\n            },\n        },\n        CacheTo = new[]\n        {\n            new Docker.Buildx.Inputs.CacheToEntryArgs\n            {\n                Registry = new Docker.Buildx.Inputs.CacheToRegistryArgs\n                {\n                    ImageManifest = true,\n                    OciMediaTypes = true,\n                    Ref = ecrRepository.RepositoryUrl.Apply(repositoryUrl =\u003e $\"{repositoryUrl}:cache\"),\n                },\n            },\n        },\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"./app\",\n        },\n        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs\n        {\n            Location = \"./Dockerfile\",\n        },\n        Push = true,\n        Registries = new[]\n        {\n            new Docker.Buildx.Inputs.RegistryAuthArgs\n            {\n                Address = ecrRepository.RepositoryUrl,\n                Password = authToken.Apply(getAuthorizationTokenResult =\u003e getAuthorizationTokenResult.Password),\n                Username = authToken.Apply(getAuthorizationTokenResult =\u003e getAuthorizationTokenResult.UserName),\n            },\n        },\n        Tags = new[]\n        {\n            ecrRepository.RepositoryUrl.Apply(repositoryUrl =\u003e $\"{repositoryUrl}:latest\"),\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/ecr\"\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\tecrRepository, err := ecr.NewRepository(ctx, \"ecr-repository\", nil)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tauthToken := ecr.GetAuthorizationTokenOutput(ctx, ecr.GetAuthorizationTokenOutputArgs{\n\t\t\tRegistryId: ecrRepository.RegistryId,\n\t\t}, nil)\n\t\t_, err = buildx.NewImage(ctx, \"my-image\", \u0026buildx.ImageArgs{\n\t\t\tCacheFrom: buildx.CacheFromEntryArray{\n\t\t\t\t\u0026buildx.CacheFromEntryArgs{\n\t\t\t\t\tRegistry: \u0026buildx.CacheFromRegistryArgs{\n\t\t\t\t\t\tRef: ecrRepository.RepositoryUrl.ApplyT(func(repositoryUrl string) (string, error) {\n\t\t\t\t\t\t\treturn fmt.Sprintf(\"%v:cache\", repositoryUrl), nil\n\t\t\t\t\t\t}).(pulumi.StringOutput),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tCacheTo: buildx.CacheToEntryArray{\n\t\t\t\t\u0026buildx.CacheToEntryArgs{\n\t\t\t\t\tRegistry: \u0026buildx.CacheToRegistryArgs{\n\t\t\t\t\t\tImageManifest: pulumi.Bool(true),\n\t\t\t\t\t\tOciMediaTypes: pulumi.Bool(true),\n\t\t\t\t\t\tRef: ecrRepository.RepositoryUrl.ApplyT(func(repositoryUrl string) (string, error) {\n\t\t\t\t\t\t\treturn fmt.Sprintf(\"%v:cache\", repositoryUrl), nil\n\t\t\t\t\t\t}).(pulumi.StringOutput),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"./app\"),\n\t\t\t},\n\t\t\tDockerfile: \u0026buildx.DockerfileArgs{\n\t\t\t\tLocation: pulumi.String(\"./Dockerfile\"),\n\t\t\t},\n\t\t\tPush: pulumi.Bool(true),\n\t\t\tRegistries: buildx.RegistryAuthArray{\n\t\t\t\t\u0026buildx.RegistryAuthArgs{\n\t\t\t\t\tAddress: ecrRepository.RepositoryUrl,\n\t\t\t\t\tPassword: authToken.ApplyT(func(authToken ecr.GetAuthorizationTokenResult) (*string, error) {\n\t\t\t\t\t\treturn \u0026authToken.Password, nil\n\t\t\t\t\t}).(pulumi.StringPtrOutput),\n\t\t\t\t\tUsername: authToken.ApplyT(func(authToken ecr.GetAuthorizationTokenResult) (*string, error) {\n\t\t\t\t\t\treturn \u0026authToken.UserName, nil\n\t\t\t\t\t}).(pulumi.StringPtrOutput),\n\t\t\t\t},\n\t\t\t},\n\t\t\tTags: pulumi.StringArray{\n\t\t\t\tecrRepository.RepositoryUrl.ApplyT(func(repositoryUrl string) (string, error) {\n\t\t\t\t\treturn fmt.Sprintf(\"%v:latest\", repositoryUrl), nil\n\t\t\t\t}).(pulumi.StringOutput),\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Push to AWS ECR with caching\nname: ecr\nresources:\n    ecr-repository:\n        type: aws:ecr:Repository\n    my-image:\n        properties:\n            cacheFrom:\n                - registry:\n                    ref: ${ecr-repository.repositoryUrl}:cache\n            cacheTo:\n                - registry:\n                    imageManifest: true\n                    ociMediaTypes: true\n                    ref: ${ecr-repository.repositoryUrl}:cache\n            context:\n                location: ./app\n            dockerfile:\n                location: ./Dockerfile\n            push: true\n            registries:\n                - address: ${ecr-repository.repositoryUrl}\n                  password: ${auth-token.password}\n                  username: ${auth-token.userName}\n            tags:\n                - ${ecr-repository.repositoryUrl}:latest\n        type: docker:buildx/image:Image\nruntime: yaml\nvariables:\n    auth-token:\n        fn::aws:ecr:getAuthorizationToken:\n            registryId: ${ecr-repository.registryId}\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.aws.ecr.Repository;\nimport com.pulumi.aws.ecr.EcrFunctions;\nimport com.pulumi.aws.ecr.inputs.GetAuthorizationTokenArgs;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.CacheFromEntryArgs;\nimport com.pulumi.docker.buildx.inputs.CacheFromRegistryArgs;\nimport com.pulumi.docker.buildx.inputs.CacheToEntryArgs;\nimport com.pulumi.docker.buildx.inputs.CacheToRegistryArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport com.pulumi.docker.buildx.inputs.DockerfileArgs;\nimport com.pulumi.docker.buildx.inputs.RegistryAuthArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var ecrRepository = new Repository(\"ecrRepository\");\n\n        final var authToken = EcrFunctions.getAuthorizationToken(GetAuthorizationTokenArgs.builder()\n            .registryId(ecrRepository.registryId())\n            .build());\n\n        var myImage = new Image(\"myImage\", ImageArgs.builder()        \n            .cacheFrom(CacheFromEntryArgs.builder()\n                .registry(CacheFromRegistryArgs.builder()\n                    .ref(ecrRepository.repositoryUrl().applyValue(repositoryUrl -\u003e String.format(\"%s:cache\", repositoryUrl)))\n                    .build())\n                .build())\n            .cacheTo(CacheToEntryArgs.builder()\n                .registry(CacheToRegistryArgs.builder()\n                    .imageManifest(true)\n                    .ociMediaTypes(true)\n                    .ref(ecrRepository.repositoryUrl().applyValue(repositoryUrl -\u003e String.format(\"%s:cache\", repositoryUrl)))\n                    .build())\n                .build())\n            .context(BuildContextArgs.builder()\n                .location(\"./app\")\n                .build())\n            .dockerfile(DockerfileArgs.builder()\n                .location(\"./Dockerfile\")\n                .build())\n            .push(true)\n            .registries(RegistryAuthArgs.builder()\n                .address(ecrRepository.repositoryUrl())\n                .password(authToken.applyValue(getAuthorizationTokenResult -\u003e getAuthorizationTokenResult).applyValue(authToken -\u003e authToken.applyValue(getAuthorizationTokenResult -\u003e getAuthorizationTokenResult.password())))\n                .username(authToken.applyValue(getAuthorizationTokenResult -\u003e getAuthorizationTokenResult).applyValue(authToken -\u003e authToken.applyValue(getAuthorizationTokenResult -\u003e getAuthorizationTokenResult.userName())))\n                .build())\n            .tags(ecrRepository.repositoryUrl().applyValue(repositoryUrl -\u003e String.format(\"%s:latest\", repositoryUrl)))\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% example %}}\n### Multi-platform image\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as docker from \"@pulumi/docker\";\n\nconst image = new docker.buildx.Image(\"image\", {\n    context: {\n        location: \"app\",\n    },\n    platforms: [\n        docker.buildx.image.Platform.Plan9_amd64,\n        docker.buildx.image.Platform.Plan9_386,\n    ],\n});\n```\n```python\nimport pulumi\nimport pulumi_docker as docker\n\nimage = docker.buildx.Image(\"image\",\n    context=docker.buildx.BuildContextArgs(\n        location=\"app\",\n    ),\n    platforms=[\n        docker.buildx/image.Platform.PLAN9_AMD64,\n        docker.buildx/image.Platform.PLAN9_386,\n    ])\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var image = new Docker.Buildx.Image(\"image\", new()\n    {\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"app\",\n        },\n        Platforms = new[]\n        {\n            Docker.Buildx.Image.Platform.Plan9_amd64,\n            Docker.Buildx.Image.Platform.Plan9_386,\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\t_, err := buildx.NewImage(ctx, \"image\", \u0026buildx.ImageArgs{\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"app\"),\n\t\t\t},\n\t\t\tPlatforms: buildx.PlatformArray{\n\t\t\t\tbuildx.Platform_Plan9_amd64,\n\t\t\t\tbuildx.Platform_Plan9_386,\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Multi-platform image\nname: multi-platform\nresources:\n    image:\n        properties:\n            context:\n                location: app\n            platforms:\n                - plan9/amd64\n                - plan9/386\n        type: docker:buildx/image:Image\nruntime: yaml\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var image = new Image(\"image\", ImageArgs.builder()        \n            .context(BuildContextArgs.builder()\n                .location(\"app\")\n                .build())\n            .platforms(            \n                \"plan9/amd64\",\n                \"plan9/386\")\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% example %}}\n### Registry export\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as docker from \"@pulumi/docker\";\n\nconst image = new docker.buildx.Image(\"image\", {\n    context: {\n        location: \"app\",\n    },\n    push: true,\n    registries: [{\n        address: \"docker.io\",\n        password: dockerHubPassword,\n        username: \"pulumibot\",\n    }],\n    tags: [\"docker.io/pulumi/pulumi:3.107.0\"],\n});\n```\n```python\nimport pulumi\nimport pulumi_docker as docker\n\nimage = docker.buildx.Image(\"image\",\n    context=docker.buildx.BuildContextArgs(\n        location=\"app\",\n    ),\n    push=True,\n    registries=[docker.buildx.RegistryAuthArgs(\n        address=\"docker.io\",\n        password=docker_hub_password,\n        username=\"pulumibot\",\n    )],\n    tags=[\"docker.io/pulumi/pulumi:3.107.0\"])\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var image = new Docker.Buildx.Image(\"image\", new()\n    {\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"app\",\n        },\n        Push = true,\n        Registries = new[]\n        {\n            new Docker.Buildx.Inputs.RegistryAuthArgs\n            {\n                Address = \"docker.io\",\n                Password = dockerHubPassword,\n                Username = \"pulumibot\",\n            },\n        },\n        Tags = new[]\n        {\n            \"docker.io/pulumi/pulumi:3.107.0\",\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\t_, err := buildx.NewImage(ctx, \"image\", \u0026buildx.ImageArgs{\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"app\"),\n\t\t\t},\n\t\t\tPush: pulumi.Bool(true),\n\t\t\tRegistries: buildx.RegistryAuthArray{\n\t\t\t\t\u0026buildx.RegistryAuthArgs{\n\t\t\t\t\tAddress:  pulumi.String(\"docker.io\"),\n\t\t\t\t\tPassword: pulumi.Any(dockerHubPassword),\n\t\t\t\t\tUsername: pulumi.String(\"pulumibot\"),\n\t\t\t\t},\n\t\t\t},\n\t\t\tTags: pulumi.StringArray{\n\t\t\t\tpulumi.String(\"docker.io/pulumi/pulumi:3.107.0\"),\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Registry export\nname: registry\nresources:\n    image:\n        properties:\n            context:\n                location: app\n            push: true\n            registries:\n                - address: docker.io\n                  password: ${dockerHubPassword}\n                  username: pulumibot\n            tags:\n                - docker.io/pulumi/pulumi:3.107.0\n        type: docker:buildx/image:Image\nruntime: yaml\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport com.pulumi.docker.buildx.inputs.RegistryAuthArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var image = new Image(\"image\", ImageArgs.builder()        \n            .context(BuildContextArgs.builder()\n                .location(\"app\")\n                .build())\n            .push(true)\n            .registries(RegistryAuthArgs.builder()\n                .address(\"docker.io\")\n                .password(dockerHubPassword)\n                .username(\"pulumibot\")\n                .build())\n            .tags(\"docker.io/pulumi/pulumi:3.107.0\")\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% example %}}\n### Caching\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as docker from \"@pulumi/docker\";\n\nconst image = new docker.buildx.Image(\"image\", {\n    cacheFrom: [{\n        local: {\n            src: \"tmp/cache\",\n        },\n    }],\n    cacheTo: [{\n        local: {\n            dest: \"tmp/cache\",\n            mode: docker.buildx.image.CacheMode.Max,\n        },\n    }],\n    context: {\n        location: \"app\",\n    },\n});\n```\n```python\nimport pulumi\nimport pulumi_docker as docker\n\nimage = docker.buildx.Image(\"image\",\n    cache_from=[docker.buildx.CacheFromEntryArgs(\n        local=docker.buildx.CacheFromLocalArgs(\n            src=\"tmp/cache\",\n        ),\n    )],\n    cache_to=[docker.buildx.CacheToEntryArgs(\n        local=docker.buildx.CacheToLocalArgs(\n            dest=\"tmp/cache\",\n            mode=docker.buildx/image.CacheMode.MAX,\n        ),\n    )],\n    context=docker.buildx.BuildContextArgs(\n        location=\"app\",\n    ))\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var image = new Docker.Buildx.Image(\"image\", new()\n    {\n        CacheFrom = new[]\n        {\n            new Docker.Buildx.Inputs.CacheFromEntryArgs\n            {\n                Local = new Docker.Buildx.Inputs.CacheFromLocalArgs\n                {\n                    Src = \"tmp/cache\",\n                },\n            },\n        },\n        CacheTo = new[]\n        {\n            new Docker.Buildx.Inputs.CacheToEntryArgs\n            {\n                Local = new Docker.Buildx.Inputs.CacheToLocalArgs\n                {\n                    Dest = \"tmp/cache\",\n                    Mode = Docker.Buildx.Image.CacheMode.Max,\n                },\n            },\n        },\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"app\",\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\t_, err := buildx.NewImage(ctx, \"image\", \u0026buildx.ImageArgs{\n\t\t\tCacheFrom: buildx.CacheFromEntryArray{\n\t\t\t\t\u0026buildx.CacheFromEntryArgs{\n\t\t\t\t\tLocal: \u0026buildx.CacheFromLocalArgs{\n\t\t\t\t\t\tSrc: pulumi.String(\"tmp/cache\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tCacheTo: buildx.CacheToEntryArray{\n\t\t\t\t\u0026buildx.CacheToEntryArgs{\n\t\t\t\t\tLocal: \u0026buildx.CacheToLocalArgs{\n\t\t\t\t\t\tDest: pulumi.String(\"tmp/cache\"),\n\t\t\t\t\t\tMode: buildx.CacheModeMax,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"app\"),\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Caching\nname: caching\nresources:\n    image:\n        properties:\n            cacheFrom:\n                - local:\n                    src: tmp/cache\n            cacheTo:\n                - local:\n                    dest: tmp/cache\n                    mode: max\n            context:\n                location: app\n        type: docker:buildx/image:Image\nruntime: yaml\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.CacheFromEntryArgs;\nimport com.pulumi.docker.buildx.inputs.CacheFromLocalArgs;\nimport com.pulumi.docker.buildx.inputs.CacheToEntryArgs;\nimport com.pulumi.docker.buildx.inputs.CacheToLocalArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var image = new Image(\"image\", ImageArgs.builder()        \n            .cacheFrom(CacheFromEntryArgs.builder()\n                .local(CacheFromLocalArgs.builder()\n                    .src(\"tmp/cache\")\n                    .build())\n                .build())\n            .cacheTo(CacheToEntryArgs.builder()\n                .local(CacheToLocalArgs.builder()\n                    .dest(\"tmp/cache\")\n                    .mode(\"max\")\n                    .build())\n                .build())\n            .context(BuildContextArgs.builder()\n                .location(\"app\")\n                .build())\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% example %}}\n### Build arguments\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as docker from \"@pulumi/docker\";\n\nconst image = new docker.buildx.Image(\"image\", {\n    buildArgs: {\n        SET_ME_TO_TRUE: \"true\",\n    },\n    context: {\n        location: \"app\",\n    },\n});\n```\n```python\nimport pulumi\nimport pulumi_docker as docker\n\nimage = docker.buildx.Image(\"image\",\n    build_args={\n        \"SET_ME_TO_TRUE\": \"true\",\n    },\n    context=docker.buildx.BuildContextArgs(\n        location=\"app\",\n    ))\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var image = new Docker.Buildx.Image(\"image\", new()\n    {\n        BuildArgs = \n        {\n            { \"SET_ME_TO_TRUE\", \"true\" },\n        },\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"app\",\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\t_, err := buildx.NewImage(ctx, \"image\", \u0026buildx.ImageArgs{\n\t\t\tBuildArgs: pulumi.StringMap{\n\t\t\t\t\"SET_ME_TO_TRUE\": pulumi.String(\"true\"),\n\t\t\t},\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"app\"),\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Build arguments\nname: build-args\nresources:\n    image:\n        properties:\n            buildArgs:\n                SET_ME_TO_TRUE: \"true\"\n            context:\n                location: app\n        type: docker:buildx/image:Image\nruntime: yaml\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var image = new Image(\"image\", ImageArgs.builder()        \n            .buildArgs(Map.of(\"SET_ME_TO_TRUE\", \"true\"))\n            .context(BuildContextArgs.builder()\n                .location(\"app\")\n                .build())\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% example %}}\n### Build targets\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as docker from \"@pulumi/docker\";\n\nconst image = new docker.buildx.Image(\"image\", {\n    context: {\n        location: \"app\",\n    },\n    targets: [\n        \"build-me\",\n        \"also-build-me\",\n    ],\n});\n```\n```python\nimport pulumi\nimport pulumi_docker as docker\n\nimage = docker.buildx.Image(\"image\",\n    context=docker.buildx.BuildContextArgs(\n        location=\"app\",\n    ),\n    targets=[\n        \"build-me\",\n        \"also-build-me\",\n    ])\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var image = new Docker.Buildx.Image(\"image\", new()\n    {\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"app\",\n        },\n        Targets = new[]\n        {\n            \"build-me\",\n            \"also-build-me\",\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\t_, err := buildx.NewImage(ctx, \"image\", \u0026buildx.ImageArgs{\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"app\"),\n\t\t\t},\n\t\t\tTargets: pulumi.StringArray{\n\t\t\t\tpulumi.String(\"build-me\"),\n\t\t\t\tpulumi.String(\"also-build-me\"),\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Build targets\nname: build-targets\nresources:\n    image:\n        properties:\n            context:\n                location: app\n            targets:\n                - build-me\n                - also-build-me\n        type: docker:buildx/image:Image\nruntime: yaml\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var image = new Image(\"image\", ImageArgs.builder()        \n            .context(BuildContextArgs.builder()\n                .location(\"app\")\n                .build())\n            .targets(            \n                \"build-me\",\n                \"also-build-me\")\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% example %}}\n### Named contexts\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as docker from \"@pulumi/docker\";\n\nconst image = new docker.buildx.Image(\"image\", {context: {\n    location: \"app\",\n    named: {\n        \"golang:latest\": {\n            location: \"docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984\",\n        },\n    },\n}});\n```\n```python\nimport pulumi\nimport pulumi_docker as docker\n\nimage = docker.buildx.Image(\"image\", context=docker.buildx.BuildContextArgs(\n    location=\"app\",\n    named={\n        \"golang:latest\": docker.buildx.ContextArgs(\n            location=\"docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984\",\n        ),\n    },\n))\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var image = new Docker.Buildx.Image(\"image\", new()\n    {\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"app\",\n            Named = \n            {\n                { \"golang:latest\", new Docker.Buildx.Inputs.ContextArgs\n                {\n                    Location = \"docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984\",\n                } },\n            },\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\t_, err := buildx.NewImage(ctx, \"image\", \u0026buildx.ImageArgs{\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"app\"),\n\t\t\t\tNamed: buildx.ContextMap{\n\t\t\t\t\t\"golang:latest\": \u0026buildx.ContextArgs{\n\t\t\t\t\t\tLocation: pulumi.String(\"docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Named contexts\nname: named-contexts\nresources:\n    image:\n        properties:\n            context:\n                location: app\n                named:\n                    golang:latest:\n                        location: docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984\n        type: docker:buildx/image:Image\nruntime: yaml\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var image = new Image(\"image\", ImageArgs.builder()        \n            .context(BuildContextArgs.builder()\n                .location(\"app\")\n                .named(Map.of(\"golang:latest\", Map.of(\"location\", \"docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984\")))\n                .build())\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% example %}}\n### Remote context\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as docker from \"@pulumi/docker\";\n\nconst image = new docker.buildx.Image(\"image\", {context: {\n    location: \"https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile\",\n}});\n```\n```python\nimport pulumi\nimport pulumi_docker as docker\n\nimage = docker.buildx.Image(\"image\", context=docker.buildx.BuildContextArgs(\n    location=\"https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile\",\n))\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var image = new Docker.Buildx.Image(\"image\", new()\n    {\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile\",\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\t_, err := buildx.NewImage(ctx, \"image\", \u0026buildx.ImageArgs{\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile\"),\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Remote context\nname: remote-context\nresources:\n    image:\n        properties:\n            context:\n                location: https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile\n        type: docker:buildx/image:Image\nruntime: yaml\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var image = new Image(\"image\", ImageArgs.builder()        \n            .context(BuildContextArgs.builder()\n                .location(\"https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile\")\n                .build())\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% example %}}\n### Inline Dockerfile\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as docker from \"@pulumi/docker\";\n\nconst image = new docker.buildx.Image(\"image\", {\n    context: {\n        location: \"app\",\n    },\n    dockerfile: {\n        inline: `FROM busybox\nCOPY hello.c ./\n`,\n    },\n});\n```\n```python\nimport pulumi\nimport pulumi_docker as docker\n\nimage = docker.buildx.Image(\"image\",\n    context=docker.buildx.BuildContextArgs(\n        location=\"app\",\n    ),\n    dockerfile=docker.buildx.DockerfileArgs(\n        inline=\"\"\"FROM busybox\nCOPY hello.c ./\n\"\"\",\n    ))\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var image = new Docker.Buildx.Image(\"image\", new()\n    {\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"app\",\n        },\n        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs\n        {\n            Inline = @\"FROM busybox\nCOPY hello.c ./\n\",\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\t_, err := buildx.NewImage(ctx, \"image\", \u0026buildx.ImageArgs{\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"app\"),\n\t\t\t},\n\t\t\tDockerfile: \u0026buildx.DockerfileArgs{\n\t\t\t\tInline: pulumi.String(\"FROM busybox\\nCOPY hello.c ./\\n\"),\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Inline Dockerfile\nname: inline\nresources:\n    image:\n        properties:\n            context:\n                location: app\n            dockerfile:\n                inline: |\n                    FROM busybox\n                    COPY hello.c ./\n        type: docker:buildx/image:Image\nruntime: yaml\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport com.pulumi.docker.buildx.inputs.DockerfileArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var image = new Image(\"image\", ImageArgs.builder()        \n            .context(BuildContextArgs.builder()\n                .location(\"app\")\n                .build())\n            .dockerfile(DockerfileArgs.builder()\n                .inline(\"\"\"\nFROM busybox\nCOPY hello.c ./\n                \"\"\")\n                .build())\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% example %}}\n### Remote context\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as docker from \"@pulumi/docker\";\n\nconst image = new docker.buildx.Image(\"image\", {\n    context: {\n        location: \"https://github.com/docker-library/hello-world.git\",\n    },\n    dockerfile: {\n        location: \"app/Dockerfile\",\n    },\n});\n```\n```python\nimport pulumi\nimport pulumi_docker as docker\n\nimage = docker.buildx.Image(\"image\",\n    context=docker.buildx.BuildContextArgs(\n        location=\"https://github.com/docker-library/hello-world.git\",\n    ),\n    dockerfile=docker.buildx.DockerfileArgs(\n        location=\"app/Dockerfile\",\n    ))\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var image = new Docker.Buildx.Image(\"image\", new()\n    {\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"https://github.com/docker-library/hello-world.git\",\n        },\n        Dockerfile = new Docker.Buildx.Inputs.DockerfileArgs\n        {\n            Location = \"app/Dockerfile\",\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\t_, err := buildx.NewImage(ctx, \"image\", \u0026buildx.ImageArgs{\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"https://github.com/docker-library/hello-world.git\"),\n\t\t\t},\n\t\t\tDockerfile: \u0026buildx.DockerfileArgs{\n\t\t\t\tLocation: pulumi.String(\"app/Dockerfile\"),\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Remote context\nname: remote-context\nresources:\n    image:\n        properties:\n            context:\n                location: https://github.com/docker-library/hello-world.git\n            dockerfile:\n                location: app/Dockerfile\n        type: docker:buildx/image:Image\nruntime: yaml\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport com.pulumi.docker.buildx.inputs.DockerfileArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var image = new Image(\"image\", ImageArgs.builder()        \n            .context(BuildContextArgs.builder()\n                .location(\"https://github.com/docker-library/hello-world.git\")\n                .build())\n            .dockerfile(DockerfileArgs.builder()\n                .location(\"app/Dockerfile\")\n                .build())\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% example %}}\n### Local export\n\n```typescript\nimport * as pulumi from \"@pulumi/pulumi\";\nimport * as docker from \"@pulumi/docker\";\n\nconst image = new docker.buildx.Image(\"image\", {\n    context: {\n        location: \"app\",\n    },\n    exports: [{\n        docker: {\n            tar: true,\n        },\n    }],\n});\n```\n```python\nimport pulumi\nimport pulumi_docker as docker\n\nimage = docker.buildx.Image(\"image\",\n    context=docker.buildx.BuildContextArgs(\n        location=\"app\",\n    ),\n    exports=[docker.buildx.ExportEntryArgs(\n        docker=docker.buildx.ExportDockerArgs(\n            tar=True,\n        ),\n    )])\n```\n```csharp\nusing System.Collections.Generic;\nusing System.Linq;\nusing Pulumi;\nusing Docker = Pulumi.Docker;\n\nreturn await Deployment.RunAsync(() =\u003e \n{\n    var image = new Docker.Buildx.Image(\"image\", new()\n    {\n        Context = new Docker.Buildx.Inputs.BuildContextArgs\n        {\n            Location = \"app\",\n        },\n        Exports = new[]\n        {\n            new Docker.Buildx.Inputs.ExportEntryArgs\n            {\n                Docker = new Docker.Buildx.Inputs.ExportDockerArgs\n                {\n                    Tar = true,\n                },\n            },\n        },\n    });\n\n});\n\n```\n```go\npackage main\n\nimport (\n\t\"github.com/pulumi/pulumi-docker/sdk/v4/go/docker/buildx\"\n\t\"github.com/pulumi/pulumi/sdk/v3/go/pulumi\"\n)\n\nfunc main() {\n\tpulumi.Run(func(ctx *pulumi.Context) error {\n\t\t_, err := buildx.NewImage(ctx, \"image\", \u0026buildx.ImageArgs{\n\t\t\tContext: \u0026buildx.BuildContextArgs{\n\t\t\t\tLocation: pulumi.String(\"app\"),\n\t\t\t},\n\t\t\tExports: buildx.ExportEntryArray{\n\t\t\t\t\u0026buildx.ExportEntryArgs{\n\t\t\t\t\tDocker: \u0026buildx.ExportDockerArgs{\n\t\t\t\t\t\tTar: pulumi.Bool(true),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n}\n```\n```yaml\ndescription: Local export\nname: docker-load\nresources:\n    image:\n        properties:\n            context:\n                location: app\n            exports:\n                - docker:\n                    tar: true\n        type: docker:buildx/image:Image\nruntime: yaml\n```\n```java\npackage generated_program;\n\nimport com.pulumi.Context;\nimport com.pulumi.Pulumi;\nimport com.pulumi.core.Output;\nimport com.pulumi.docker.buildx.Image;\nimport com.pulumi.docker.buildx.ImageArgs;\nimport com.pulumi.docker.buildx.inputs.BuildContextArgs;\nimport com.pulumi.docker.buildx.inputs.ExportEntryArgs;\nimport com.pulumi.docker.buildx.inputs.ExportDockerArgs;\nimport java.util.List;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.io.File;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\n\npublic class App {\n    public static void main(String[] args) {\n        Pulumi.run(App::stack);\n    }\n\n    public static void stack(Context ctx) {\n        var image = new Image(\"image\", ImageArgs.builder()        \n            .context(BuildContextArgs.builder()\n                .location(\"app\")\n                .build())\n            .exports(ExportEntryArgs.builder()\n                .docker(ExportDockerArgs.builder()\n                    .tar(true)\n                    .build())\n                .build())\n            .build());\n\n    }\n}\n```\n{{% /example %}}\n{{% /examples %}}",
             "properties": {
+                "addHosts": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "description": "Custom `host:ip` mappings to use during the build.\n\nEquivalent to Docker's `--add-host` flag."
+                },
                 "buildArgs": {
                     "type": "object",
                     "additionalProperties": {
@@ -3098,7 +3090,7 @@
                 },
                 "buildOnPreview": {
                     "type": "boolean",
-                    "description": "When `true`, attempt to build the image during previews. The image will\nnot be pushed to registries, however caches will still be populated."
+                    "description": "By default, preview behavior depends on the execution environment. If\nPulumi detects the operation is running on a CI system (GitHub Actions,\nTravis CI, Azure Pipelines, etc.) then it will build images during\npreviews as a safeguard. Otherwise, if not running on CI, previews will\nnot build images.\n\nSetting this to `false` forces previews to never perform builds, and\nsetting it to `true` will always build the image during previews.\n\nImages built during previews are never exported to registries, however\ncache manifests are still exported.\n\nOn-disk Dockerfiles are always validated for syntactic correctness\nregardless of this setting."
                 },
                 "builder": {
                     "$ref": "#/types/docker:buildx/image:BuilderConfig",
@@ -3129,12 +3121,9 @@
                 "digests": {
                     "type": "object",
                     "additionalProperties": {
-                        "type": "array",
-                        "items": {
-                            "type": "string"
-                        }
+                        "type": "string"
                     },
-                    "description": "A mapping of platform type to refs which were pushed to registries."
+                    "description": "A mapping of target names to the SHA256 digest of their pushed manifest.\n\nIf no target was specified 'default' is used as the target name.\n\nPushed manifests can be referenced as `\u003ctag\u003e@\u003cdigest\u003e`."
                 },
                 "dockerfile": {
                     "$ref": "#/types/docker:buildx/image:Dockerfile",
@@ -3154,6 +3143,19 @@
                     },
                     "description": "Attach arbitrary key/value metadata to the image.\n\nEquivalent to Docker's `--label` flag."
                 },
+                "load": {
+                    "type": "boolean",
+                    "description": "When `true` the build will automatically include a `docker` export.\n\nDefaults to `false`.\n\nEquivalent to Docker's `--load` flag."
+                },
+                "network": {
+                    "$ref": "#/types/docker:buildx/image:NetworkMode",
+                    "description": "Set the network mode for `RUN` instructions. Defaults to `default`.\n\nFor custom networks, configure your builder with `--driver-opt network=...`.\n\nEquivalent to Docker's `--network` flag.",
+                    "default": "default"
+                },
+                "noCache": {
+                    "type": "boolean",
+                    "description": "Do not import cache manifests when building the image.\n\nEquivalent to Docker's `--no-cache` flag."
+                },
                 "platforms": {
                     "type": "array",
                     "items": {
@@ -3165,6 +3167,14 @@
                     "type": "boolean",
                     "description": "Always pull referenced images.\n\nEquivalent to Docker's `--pull` flag."
                 },
+                "push": {
+                    "type": "boolean",
+                    "description": "When `true` the build will automatically include a `registry` export.\n\nDefaults to `false`.\n\nEquivalent to Docker's `--push` flag."
+                },
+                "ref": {
+                    "type": "string",
+                    "description": "If the image was pushed to any registries then this will contain a\nsingle fully-qualified tag including the build's digest.\n\nThis is only for convenience and may not be appropriate for situations\nwhere multiple tags or registries are involved. In those cases this\noutput is not guaranteed to be stable.\n\nFor more control over tags consumed by downstream resources you should\nuse the `Digests` output."
+                },
                 "registries": {
                     "type": "array",
                     "items": {
@@ -3177,8 +3187,14 @@
                     "additionalProperties": {
                         "type": "string"
                     },
-                    "description": "A mapping of secret names to their corresponding values.\n\nUnlike the Docker CLI, these can be passed by value and do not need to\nexist on-disk or in environment variables.\n\nBuild arguments and environment variables are persistent in the final\nimage, so you should use this for sensitive values.\n\nSimilar to Docker's `--secret` flag.",
-                    "secret": true
+                    "description": "A mapping of secret names to their corresponding values.\n\nUnlike the Docker CLI, these can be passed by value and do not need to\nexist on-disk or in environment variables.\n\nBuild arguments and environment variables are persistent in the final\nimage, so you should use this for sensitive values.\n\nSimilar to Docker's `--secret` flag."
+                },
+                "ssh": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/types/docker:buildx/image:SSH"
+                    },
+                    "description": "SSH agent socket or keys to expose to the build.\n\nEquivalent to Docker's `--ssh` flag."
                 },
                 "tags": {
                     "type": "array",
@@ -3195,7 +3211,19 @@
                     "description": "Set the target build stage(s) to build.\n\nIf not specified all targets will be built by default.\n\nEquivalent to Docker's `--target` flag."
                 }
             },
+            "required": [
+                "digests",
+                "contextHash",
+                "ref"
+            ],
             "inputProperties": {
+                "addHosts": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "description": "Custom `host:ip` mappings to use during the build.\n\nEquivalent to Docker's `--add-host` flag."
+                },
                 "buildArgs": {
                     "type": "object",
                     "additionalProperties": {
@@ -3205,7 +3233,7 @@
                 },
                 "buildOnPreview": {
                     "type": "boolean",
-                    "description": "When `true`, attempt to build the image during previews. The image will\nnot be pushed to registries, however caches will still be populated."
+                    "description": "By default, preview behavior depends on the execution environment. If\nPulumi detects the operation is running on a CI system (GitHub Actions,\nTravis CI, Azure Pipelines, etc.) then it will build images during\npreviews as a safeguard. Otherwise, if not running on CI, previews will\nnot build images.\n\nSetting this to `false` forces previews to never perform builds, and\nsetting it to `true` will always build the image during previews.\n\nImages built during previews are never exported to registries, however\ncache manifests are still exported.\n\nOn-disk Dockerfiles are always validated for syntactic correctness\nregardless of this setting."
                 },
                 "builder": {
                     "$ref": "#/types/docker:buildx/image:BuilderConfig",
@@ -3247,6 +3275,19 @@
                     },
                     "description": "Attach arbitrary key/value metadata to the image.\n\nEquivalent to Docker's `--label` flag."
                 },
+                "load": {
+                    "type": "boolean",
+                    "description": "When `true` the build will automatically include a `docker` export.\n\nDefaults to `false`.\n\nEquivalent to Docker's `--load` flag."
+                },
+                "network": {
+                    "$ref": "#/types/docker:buildx/image:NetworkMode",
+                    "description": "Set the network mode for `RUN` instructions. Defaults to `default`.\n\nFor custom networks, configure your builder with `--driver-opt network=...`.\n\nEquivalent to Docker's `--network` flag.",
+                    "default": "default"
+                },
+                "noCache": {
+                    "type": "boolean",
+                    "description": "Do not import cache manifests when building the image.\n\nEquivalent to Docker's `--no-cache` flag."
+                },
                 "platforms": {
                     "type": "array",
                     "items": {
@@ -3258,6 +3299,10 @@
                     "type": "boolean",
                     "description": "Always pull referenced images.\n\nEquivalent to Docker's `--pull` flag."
                 },
+                "push": {
+                    "type": "boolean",
+                    "description": "When `true` the build will automatically include a `registry` export.\n\nDefaults to `false`.\n\nEquivalent to Docker's `--push` flag."
+                },
                 "registries": {
                     "type": "array",
                     "items": {
@@ -3270,8 +3315,14 @@
                     "additionalProperties": {
                         "type": "string"
                     },
-                    "description": "A mapping of secret names to their corresponding values.\n\nUnlike the Docker CLI, these can be passed by value and do not need to\nexist on-disk or in environment variables.\n\nBuild arguments and environment variables are persistent in the final\nimage, so you should use this for sensitive values.\n\nSimilar to Docker's `--secret` flag.",
-                    "secret": true
+                    "description": "A mapping of secret names to their corresponding values.\n\nUnlike the Docker CLI, these can be passed by value and do not need to\nexist on-disk or in environment variables.\n\nBuild arguments and environment variables are persistent in the final\nimage, so you should use this for sensitive values.\n\nSimilar to Docker's `--secret` flag."
+                },
+                "ssh": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/types/docker:buildx/image:SSH"
+                    },
+                    "description": "SSH agent socket or keys to expose to the build.\n\nEquivalent to Docker's `--ssh` flag."
                 },
                 "tags": {
                     "type": "array",
diff --git a/sdk/dotnet/Buildx/Enums.cs b/sdk/dotnet/Buildx/Enums.cs
index de7584c1..39bfcadd 100644
--- a/sdk/dotnet/Buildx/Enums.cs
+++ b/sdk/dotnet/Buildx/Enums.cs
@@ -79,6 +79,44 @@ private CompressionType(string value)
         public override string ToString() => _value;
     }
 
+    [EnumType]
+    public readonly struct NetworkMode : IEquatable<NetworkMode>
+    {
+        private readonly string _value;
+
+        private NetworkMode(string value)
+        {
+            _value = value ?? throw new ArgumentNullException(nameof(value));
+        }
+
+        /// <summary>
+        /// The default sandbox network mode.
+        /// </summary>
+        public static NetworkMode @Default { get; } = new NetworkMode("default");
+        /// <summary>
+        /// Host network mode.
+        /// </summary>
+        public static NetworkMode Host { get; } = new NetworkMode("host");
+        /// <summary>
+        /// Disable network access.
+        /// </summary>
+        public static NetworkMode None { get; } = new NetworkMode("none");
+
+        public static bool operator ==(NetworkMode left, NetworkMode right) => left.Equals(right);
+        public static bool operator !=(NetworkMode left, NetworkMode right) => !left.Equals(right);
+
+        public static explicit operator string(NetworkMode value) => value._value;
+
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override bool Equals(object? obj) => obj is NetworkMode other && Equals(other);
+        public bool Equals(NetworkMode other) => string.Equals(_value, other._value, StringComparison.Ordinal);
+
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override int GetHashCode() => _value?.GetHashCode() ?? 0;
+
+        public override string ToString() => _value;
+    }
+
     [EnumType]
     public readonly struct Platform : IEquatable<Platform>
     {
diff --git a/sdk/dotnet/Buildx/Image.cs b/sdk/dotnet/Buildx/Image.cs
index 68629861..d031d3b4 100644
--- a/sdk/dotnet/Buildx/Image.cs
+++ b/sdk/dotnet/Buildx/Image.cs
@@ -461,6 +461,14 @@ namespace Pulumi.Docker.Buildx
     [DockerResourceType("docker:buildx/image:Image")]
     public partial class Image : global::Pulumi.CustomResource
     {
+        /// <summary>
+        /// Custom `host:ip` mappings to use during the build.
+        /// 
+        /// Equivalent to Docker's `--add-host` flag.
+        /// </summary>
+        [Output("addHosts")]
+        public Output<ImmutableArray<string>> AddHosts { get; private set; } = null!;
+
         /// <summary>
         /// `ARG` names and values to set during the build.
         /// 
@@ -476,8 +484,20 @@ public partial class Image : global::Pulumi.CustomResource
         public Output<ImmutableDictionary<string, string>?> BuildArgs { get; private set; } = null!;
 
         /// <summary>
-        /// When `true`, attempt to build the image during previews. The image will
-        /// not be pushed to registries, however caches will still be populated.
+        /// By default, preview behavior depends on the execution environment. If
+        /// Pulumi detects the operation is running on a CI system (GitHub Actions,
+        /// Travis CI, Azure Pipelines, etc.) then it will build images during
+        /// previews as a safeguard. Otherwise, if not running on CI, previews will
+        /// not build images.
+        /// 
+        /// Setting this to `false` forces previews to never perform builds, and
+        /// setting it to `true` will always build the image during previews.
+        /// 
+        /// Images built during previews are never exported to registries, however
+        /// cache manifests are still exported.
+        /// 
+        /// On-disk Dockerfiles are always validated for syntactic correctness
+        /// regardless of this setting.
         /// </summary>
         [Output("buildOnPreview")]
         public Output<bool?> BuildOnPreview { get; private set; } = null!;
@@ -518,13 +538,17 @@ public partial class Image : global::Pulumi.CustomResource
         /// Pulumi uses this to determine if an image _may_ need to be re-built.
         /// </summary>
         [Output("contextHash")]
-        public Output<string?> ContextHash { get; private set; } = null!;
+        public Output<string> ContextHash { get; private set; } = null!;
 
         /// <summary>
-        /// A mapping of platform type to refs which were pushed to registries.
+        /// A mapping of target names to the SHA256 digest of their pushed manifest.
+        /// 
+        /// If no target was specified 'default' is used as the target name.
+        /// 
+        /// Pushed manifests can be referenced as `&lt;tag&gt;@&lt;digest&gt;`.
         /// </summary>
         [Output("digests")]
-        public Output<ImmutableDictionary<string, ImmutableArray<string>>?> Digests { get; private set; } = null!;
+        public Output<ImmutableDictionary<string, string>> Digests { get; private set; } = null!;
 
         /// <summary>
         /// Dockerfile settings.
@@ -553,6 +577,34 @@ public partial class Image : global::Pulumi.CustomResource
         [Output("labels")]
         public Output<ImmutableDictionary<string, string>?> Labels { get; private set; } = null!;
 
+        /// <summary>
+        /// When `true` the build will automatically include a `docker` export.
+        /// 
+        /// Defaults to `false`.
+        /// 
+        /// Equivalent to Docker's `--load` flag.
+        /// </summary>
+        [Output("load")]
+        public Output<bool?> Load { get; private set; } = null!;
+
+        /// <summary>
+        /// Set the network mode for `RUN` instructions. Defaults to `default`.
+        /// 
+        /// For custom networks, configure your builder with `--driver-opt network=...`.
+        /// 
+        /// Equivalent to Docker's `--network` flag.
+        /// </summary>
+        [Output("network")]
+        public Output<Pulumi.Docker.Buildx.NetworkMode?> Network { get; private set; } = null!;
+
+        /// <summary>
+        /// Do not import cache manifests when building the image.
+        /// 
+        /// Equivalent to Docker's `--no-cache` flag.
+        /// </summary>
+        [Output("noCache")]
+        public Output<bool?> NoCache { get; private set; } = null!;
+
         /// <summary>
         /// Set target platform(s) for the build. Defaults to the host's platform.
         /// 
@@ -569,6 +621,30 @@ public partial class Image : global::Pulumi.CustomResource
         [Output("pull")]
         public Output<bool?> Pull { get; private set; } = null!;
 
+        /// <summary>
+        /// When `true` the build will automatically include a `registry` export.
+        /// 
+        /// Defaults to `false`.
+        /// 
+        /// Equivalent to Docker's `--push` flag.
+        /// </summary>
+        [Output("push")]
+        public Output<bool?> Push { get; private set; } = null!;
+
+        /// <summary>
+        /// If the image was pushed to any registries then this will contain a
+        /// single fully-qualified tag including the build's digest.
+        /// 
+        /// This is only for convenience and may not be appropriate for situations
+        /// where multiple tags or registries are involved. In those cases this
+        /// output is not guaranteed to be stable.
+        /// 
+        /// For more control over tags consumed by downstream resources you should
+        /// use the `Digests` output.
+        /// </summary>
+        [Output("ref")]
+        public Output<string> Ref { get; private set; } = null!;
+
         /// <summary>
         /// Registry credentials. Required if reading or exporting to private
         /// repositories.
@@ -595,6 +671,14 @@ public partial class Image : global::Pulumi.CustomResource
         [Output("secrets")]
         public Output<ImmutableDictionary<string, string>?> Secrets { get; private set; } = null!;
 
+        /// <summary>
+        /// SSH agent socket or keys to expose to the build.
+        /// 
+        /// Equivalent to Docker's `--ssh` flag.
+        /// </summary>
+        [Output("ssh")]
+        public Output<ImmutableArray<Outputs.SSH>> Ssh { get; private set; } = null!;
+
         /// <summary>
         /// Name and optionally a tag (format: `name:tag`).
         /// 
@@ -639,10 +723,6 @@ private static CustomResourceOptions MakeResourceOptions(CustomResourceOptions?
             var defaultOptions = new CustomResourceOptions
             {
                 Version = Utilities.Version,
-                AdditionalSecretOutputs =
-                {
-                    "secrets",
-                },
             };
             var merged = CustomResourceOptions.Merge(defaultOptions, options);
             // Override the ID if one was specified for consistency with other language SDKs.
@@ -665,6 +745,20 @@ public static Image Get(string name, Input<string> id, CustomResourceOptions? op
 
     public sealed class ImageArgs : global::Pulumi.ResourceArgs
     {
+        [Input("addHosts")]
+        private InputList<string>? _addHosts;
+
+        /// <summary>
+        /// Custom `host:ip` mappings to use during the build.
+        /// 
+        /// Equivalent to Docker's `--add-host` flag.
+        /// </summary>
+        public InputList<string> AddHosts
+        {
+            get => _addHosts ?? (_addHosts = new InputList<string>());
+            set => _addHosts = value;
+        }
+
         [Input("buildArgs")]
         private InputMap<string>? _buildArgs;
 
@@ -686,8 +780,20 @@ public InputMap<string> BuildArgs
         }
 
         /// <summary>
-        /// When `true`, attempt to build the image during previews. The image will
-        /// not be pushed to registries, however caches will still be populated.
+        /// By default, preview behavior depends on the execution environment. If
+        /// Pulumi detects the operation is running on a CI system (GitHub Actions,
+        /// Travis CI, Azure Pipelines, etc.) then it will build images during
+        /// previews as a safeguard. Otherwise, if not running on CI, previews will
+        /// not build images.
+        /// 
+        /// Setting this to `false` forces previews to never perform builds, and
+        /// setting it to `true` will always build the image during previews.
+        /// 
+        /// Images built during previews are never exported to registries, however
+        /// cache manifests are still exported.
+        /// 
+        /// On-disk Dockerfiles are always validated for syntactic correctness
+        /// regardless of this setting.
         /// </summary>
         [Input("buildOnPreview")]
         public Input<bool>? BuildOnPreview { get; set; }
@@ -773,6 +879,34 @@ public InputMap<string> Labels
             set => _labels = value;
         }
 
+        /// <summary>
+        /// When `true` the build will automatically include a `docker` export.
+        /// 
+        /// Defaults to `false`.
+        /// 
+        /// Equivalent to Docker's `--load` flag.
+        /// </summary>
+        [Input("load")]
+        public Input<bool>? Load { get; set; }
+
+        /// <summary>
+        /// Set the network mode for `RUN` instructions. Defaults to `default`.
+        /// 
+        /// For custom networks, configure your builder with `--driver-opt network=...`.
+        /// 
+        /// Equivalent to Docker's `--network` flag.
+        /// </summary>
+        [Input("network")]
+        public Input<Pulumi.Docker.Buildx.NetworkMode>? Network { get; set; }
+
+        /// <summary>
+        /// Do not import cache manifests when building the image.
+        /// 
+        /// Equivalent to Docker's `--no-cache` flag.
+        /// </summary>
+        [Input("noCache")]
+        public Input<bool>? NoCache { get; set; }
+
         [Input("platforms")]
         private InputList<Pulumi.Docker.Buildx.Platform>? _platforms;
 
@@ -795,6 +929,16 @@ public InputList<Pulumi.Docker.Buildx.Platform> Platforms
         [Input("pull")]
         public Input<bool>? Pull { get; set; }
 
+        /// <summary>
+        /// When `true` the build will automatically include a `registry` export.
+        /// 
+        /// Defaults to `false`.
+        /// 
+        /// Equivalent to Docker's `--push` flag.
+        /// </summary>
+        [Input("push")]
+        public Input<bool>? Push { get; set; }
+
         [Input("registries")]
         private InputList<Inputs.RegistryAuthArgs>? _registries;
 
@@ -830,11 +974,21 @@ public InputList<Inputs.RegistryAuthArgs> Registries
         public InputMap<string> Secrets
         {
             get => _secrets ?? (_secrets = new InputMap<string>());
-            set
-            {
-                var emptySecret = Output.CreateSecret(ImmutableDictionary.Create<string, string>());
-                _secrets = Output.All(value, emptySecret).Apply(v => v[0]);
-            }
+            set => _secrets = value;
+        }
+
+        [Input("ssh")]
+        private InputList<Inputs.SSHArgs>? _ssh;
+
+        /// <summary>
+        /// SSH agent socket or keys to expose to the build.
+        /// 
+        /// Equivalent to Docker's `--ssh` flag.
+        /// </summary>
+        public InputList<Inputs.SSHArgs> Ssh
+        {
+            get => _ssh ?? (_ssh = new InputList<Inputs.SSHArgs>());
+            set => _ssh = value;
         }
 
         [Input("tags")]
@@ -872,6 +1026,7 @@ public InputList<string> Targets
 
         public ImageArgs()
         {
+            Network = Pulumi.Docker.Buildx.NetworkMode.@Default;
         }
         public static new ImageArgs Empty => new ImageArgs();
     }
diff --git a/sdk/dotnet/Buildx/Inputs/ExportEntryArgs.cs b/sdk/dotnet/Buildx/Inputs/ExportEntryArgs.cs
index 6e5583c9..e7b816c4 100644
--- a/sdk/dotnet/Buildx/Inputs/ExportEntryArgs.cs
+++ b/sdk/dotnet/Buildx/Inputs/ExportEntryArgs.cs
@@ -36,19 +36,6 @@ public sealed class ExportEntryArgs : global::Pulumi.ResourceArgs
         [Input("local")]
         public Input<Inputs.ExportLocalArgs>? Local { get; set; }
 
-        [Input("manifests")]
-        private InputList<Inputs.ManifestArgs>? _manifests;
-
-        /// <summary>
-        /// An output property populated for exporters that pushed image
-        /// manifest(s) to a registry.
-        /// </summary>
-        public InputList<Inputs.ManifestArgs> Manifests
-        {
-            get => _manifests ?? (_manifests = new InputList<Inputs.ManifestArgs>());
-            set => _manifests = value;
-        }
-
         /// <summary>
         /// Identical to the Docker exporter but uses OCI media types by default.
         /// </summary>
diff --git a/sdk/dotnet/Buildx/Inputs/ManifestArgs.cs b/sdk/dotnet/Buildx/Inputs/ManifestArgs.cs
deleted file mode 100644
index b371ec8d..00000000
--- a/sdk/dotnet/Buildx/Inputs/ManifestArgs.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-// *** WARNING: this file was generated by the Pulumi Terraform Bridge (tfgen) Tool. ***
-// *** Do not edit by hand unless you're certain you know what you are doing! ***
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Threading.Tasks;
-using Pulumi.Serialization;
-
-namespace Pulumi.Docker.Buildx.Inputs
-{
-
-    public sealed class ManifestArgs : global::Pulumi.ResourceArgs
-    {
-        /// <summary>
-        /// The SHA256 digest of the manifest.
-        /// </summary>
-        [Input("digest", required: true)]
-        public Input<string> Digest { get; set; } = null!;
-
-        /// <summary>
-        /// The manifest's platform.
-        /// </summary>
-        [Input("platform", required: true)]
-        public Input<Inputs.ManifestPlatformArgs> Platform { get; set; } = null!;
-
-        /// <summary>
-        /// The manifest's canonical ref.
-        /// </summary>
-        [Input("ref", required: true)]
-        public Input<string> Ref { get; set; } = null!;
-
-        /// <summary>
-        /// The size of the manifest in bytes.
-        /// </summary>
-        [Input("size", required: true)]
-        public Input<int> Size { get; set; } = null!;
-
-        public ManifestArgs()
-        {
-        }
-        public static new ManifestArgs Empty => new ManifestArgs();
-    }
-}
diff --git a/sdk/dotnet/Buildx/Inputs/ManifestPlatformArgs.cs b/sdk/dotnet/Buildx/Inputs/ManifestPlatformArgs.cs
deleted file mode 100644
index 9b95fb8a..00000000
--- a/sdk/dotnet/Buildx/Inputs/ManifestPlatformArgs.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// *** WARNING: this file was generated by the Pulumi Terraform Bridge (tfgen) Tool. ***
-// *** Do not edit by hand unless you're certain you know what you are doing! ***
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Threading.Tasks;
-using Pulumi.Serialization;
-
-namespace Pulumi.Docker.Buildx.Inputs
-{
-
-    public sealed class ManifestPlatformArgs : global::Pulumi.ResourceArgs
-    {
-        /// <summary>
-        /// The manifest's architecture.
-        /// </summary>
-        [Input("architecture", required: true)]
-        public Input<string> Architecture { get; set; } = null!;
-
-        /// <summary>
-        /// The manifest's operating systen.
-        /// </summary>
-        [Input("os", required: true)]
-        public Input<string> Os { get; set; } = null!;
-
-        public ManifestPlatformArgs()
-        {
-        }
-        public static new ManifestPlatformArgs Empty => new ManifestPlatformArgs();
-    }
-}
diff --git a/sdk/dotnet/Buildx/Inputs/SSHArgs.cs b/sdk/dotnet/Buildx/Inputs/SSHArgs.cs
new file mode 100644
index 00000000..2f07c7ac
--- /dev/null
+++ b/sdk/dotnet/Buildx/Inputs/SSHArgs.cs
@@ -0,0 +1,48 @@
+// *** WARNING: this file was generated by the Pulumi Terraform Bridge (tfgen) Tool. ***
+// *** Do not edit by hand unless you're certain you know what you are doing! ***
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Threading.Tasks;
+using Pulumi.Serialization;
+
+namespace Pulumi.Docker.Buildx.Inputs
+{
+
+    public sealed class SSHArgs : global::Pulumi.ResourceArgs
+    {
+        /// <summary>
+        /// Useful for distinguishing different servers that are part of the same
+        /// build.
+        /// 
+        /// A value of `default` is appropriate if only dealing with a single host.
+        /// </summary>
+        [Input("id", required: true)]
+        public Input<string> Id { get; set; } = null!;
+
+        [Input("paths")]
+        private InputList<string>? _paths;
+
+        /// <summary>
+        /// SSH agent socket or private keys to expose to the build under the given
+        /// identifier.
+        /// 
+        /// Defaults to `[$SSH_AUTH_SOCK]`.
+        /// 
+        /// Note that your keys are **not** automatically added when using an
+        /// agent. Run `ssh-add -l` locally to confirm which public keys are
+        /// visible to the agent; these will be exposed to your build.
+        /// </summary>
+        public InputList<string> Paths
+        {
+            get => _paths ?? (_paths = new InputList<string>());
+            set => _paths = value;
+        }
+
+        public SSHArgs()
+        {
+        }
+        public static new SSHArgs Empty => new SSHArgs();
+    }
+}
diff --git a/sdk/dotnet/Buildx/Outputs/ExportEntry.cs b/sdk/dotnet/Buildx/Outputs/ExportEntry.cs
index 727ede06..e294ffc4 100644
--- a/sdk/dotnet/Buildx/Outputs/ExportEntry.cs
+++ b/sdk/dotnet/Buildx/Outputs/ExportEntry.cs
@@ -30,11 +30,6 @@ public sealed class ExportEntry
         /// </summary>
         public readonly Outputs.ExportLocal? Local;
         /// <summary>
-        /// An output property populated for exporters that pushed image
-        /// manifest(s) to a registry.
-        /// </summary>
-        public readonly ImmutableArray<Outputs.Manifest> Manifests;
-        /// <summary>
         /// Identical to the Docker exporter but uses OCI media types by default.
         /// </summary>
         public readonly Outputs.ExportOCI? Oci;
@@ -62,8 +57,6 @@ private ExportEntry(
 
             Outputs.ExportLocal? local,
 
-            ImmutableArray<Outputs.Manifest> manifests,
-
             Outputs.ExportOCI? oci,
 
             string? raw,
@@ -76,7 +69,6 @@ private ExportEntry(
             Docker = docker;
             Image = image;
             Local = local;
-            Manifests = manifests;
             Oci = oci;
             Raw = raw;
             Registry = registry;
diff --git a/sdk/dotnet/Buildx/Outputs/Manifest.cs b/sdk/dotnet/Buildx/Outputs/Manifest.cs
deleted file mode 100644
index 1badef99..00000000
--- a/sdk/dotnet/Buildx/Outputs/Manifest.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-// *** WARNING: this file was generated by the Pulumi Terraform Bridge (tfgen) Tool. ***
-// *** Do not edit by hand unless you're certain you know what you are doing! ***
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Threading.Tasks;
-using Pulumi.Serialization;
-
-namespace Pulumi.Docker.Buildx.Outputs
-{
-
-    [OutputType]
-    public sealed class Manifest
-    {
-        /// <summary>
-        /// The SHA256 digest of the manifest.
-        /// </summary>
-        public readonly string Digest;
-        /// <summary>
-        /// The manifest's platform.
-        /// </summary>
-        public readonly Outputs.ManifestPlatform Platform;
-        /// <summary>
-        /// The manifest's canonical ref.
-        /// </summary>
-        public readonly string Ref;
-        /// <summary>
-        /// The size of the manifest in bytes.
-        /// </summary>
-        public readonly int Size;
-
-        [OutputConstructor]
-        private Manifest(
-            string digest,
-
-            Outputs.ManifestPlatform platform,
-
-            string @ref,
-
-            int size)
-        {
-            Digest = digest;
-            Platform = platform;
-            Ref = @ref;
-            Size = size;
-        }
-    }
-}
diff --git a/sdk/dotnet/Buildx/Outputs/ManifestPlatform.cs b/sdk/dotnet/Buildx/Outputs/ManifestPlatform.cs
deleted file mode 100644
index 7c8aec5c..00000000
--- a/sdk/dotnet/Buildx/Outputs/ManifestPlatform.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-// *** WARNING: this file was generated by the Pulumi Terraform Bridge (tfgen) Tool. ***
-// *** Do not edit by hand unless you're certain you know what you are doing! ***
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Threading.Tasks;
-using Pulumi.Serialization;
-
-namespace Pulumi.Docker.Buildx.Outputs
-{
-
-    [OutputType]
-    public sealed class ManifestPlatform
-    {
-        /// <summary>
-        /// The manifest's architecture.
-        /// </summary>
-        public readonly string Architecture;
-        /// <summary>
-        /// The manifest's operating systen.
-        /// </summary>
-        public readonly string Os;
-
-        [OutputConstructor]
-        private ManifestPlatform(
-            string architecture,
-
-            string os)
-        {
-            Architecture = architecture;
-            Os = os;
-        }
-    }
-}
diff --git a/sdk/dotnet/Buildx/Outputs/SSH.cs b/sdk/dotnet/Buildx/Outputs/SSH.cs
new file mode 100644
index 00000000..296684d6
--- /dev/null
+++ b/sdk/dotnet/Buildx/Outputs/SSH.cs
@@ -0,0 +1,45 @@
+// *** WARNING: this file was generated by the Pulumi Terraform Bridge (tfgen) Tool. ***
+// *** Do not edit by hand unless you're certain you know what you are doing! ***
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Threading.Tasks;
+using Pulumi.Serialization;
+
+namespace Pulumi.Docker.Buildx.Outputs
+{
+
+    [OutputType]
+    public sealed class SSH
+    {
+        /// <summary>
+        /// Useful for distinguishing different servers that are part of the same
+        /// build.
+        /// 
+        /// A value of `default` is appropriate if only dealing with a single host.
+        /// </summary>
+        public readonly string Id;
+        /// <summary>
+        /// SSH agent socket or private keys to expose to the build under the given
+        /// identifier.
+        /// 
+        /// Defaults to `[$SSH_AUTH_SOCK]`.
+        /// 
+        /// Note that your keys are **not** automatically added when using an
+        /// agent. Run `ssh-add -l` locally to confirm which public keys are
+        /// visible to the agent; these will be exposed to your build.
+        /// </summary>
+        public readonly ImmutableArray<string> Paths;
+
+        [OutputConstructor]
+        private SSH(
+            string id,
+
+            ImmutableArray<string> paths)
+        {
+            Id = id;
+            Paths = paths;
+        }
+    }
+}
diff --git a/sdk/go/docker/buildx/image.go b/sdk/go/docker/buildx/image.go
index 782929d0..6de584bb 100644
--- a/sdk/go/docker/buildx/image.go
+++ b/sdk/go/docker/buildx/image.go
@@ -508,6 +508,10 @@ import (
 type Image struct {
 	pulumi.CustomResourceState
 
+	// Custom `host:ip` mappings to use during the build.
+	//
+	// Equivalent to Docker's `--add-host` flag.
+	AddHosts pulumi.StringArrayOutput `pulumi:"addHosts"`
 	// `ARG` names and values to set during the build.
 	//
 	// These variables are accessed like environment variables inside `RUN`
@@ -518,8 +522,20 @@ type Image struct {
 	//
 	// Equivalent to Docker's `--build-arg` flag.
 	BuildArgs pulumi.StringMapOutput `pulumi:"buildArgs"`
-	// When `true`, attempt to build the image during previews. The image will
-	// not be pushed to registries, however caches will still be populated.
+	// By default, preview behavior depends on the execution environment. If
+	// Pulumi detects the operation is running on a CI system (GitHub Actions,
+	// Travis CI, Azure Pipelines, etc.) then it will build images during
+	// previews as a safeguard. Otherwise, if not running on CI, previews will
+	// not build images.
+	//
+	// Setting this to `false` forces previews to never perform builds, and
+	// setting it to `true` will always build the image during previews.
+	//
+	// Images built during previews are never exported to registries, however
+	// cache manifests are still exported.
+	//
+	// On-disk Dockerfiles are always validated for syntactic correctness
+	// regardless of this setting.
 	BuildOnPreview pulumi.BoolPtrOutput `pulumi:"buildOnPreview"`
 	// Builder configuration.
 	Builder BuilderConfigPtrOutput `pulumi:"builder"`
@@ -538,9 +554,13 @@ type Image struct {
 	// A preliminary hash of the image's build context.
 	//
 	// Pulumi uses this to determine if an image _may_ need to be re-built.
-	ContextHash pulumi.StringPtrOutput `pulumi:"contextHash"`
-	// A mapping of platform type to refs which were pushed to registries.
-	Digests pulumi.StringArrayMapOutput `pulumi:"digests"`
+	ContextHash pulumi.StringOutput `pulumi:"contextHash"`
+	// A mapping of target names to the SHA256 digest of their pushed manifest.
+	//
+	// If no target was specified 'default' is used as the target name.
+	//
+	// Pushed manifests can be referenced as `<tag>@<digest>`.
+	Digests pulumi.StringMapOutput `pulumi:"digests"`
 	// Dockerfile settings.
 	//
 	// Equivalent to Docker's `--file` flag.
@@ -556,6 +576,22 @@ type Image struct {
 	//
 	// Equivalent to Docker's `--label` flag.
 	Labels pulumi.StringMapOutput `pulumi:"labels"`
+	// When `true` the build will automatically include a `docker` export.
+	//
+	// Defaults to `false`.
+	//
+	// Equivalent to Docker's `--load` flag.
+	Load pulumi.BoolPtrOutput `pulumi:"load"`
+	// Set the network mode for `RUN` instructions. Defaults to `default`.
+	//
+	// For custom networks, configure your builder with `--driver-opt network=...`.
+	//
+	// Equivalent to Docker's `--network` flag.
+	Network NetworkModePtrOutput `pulumi:"network"`
+	// Do not import cache manifests when building the image.
+	//
+	// Equivalent to Docker's `--no-cache` flag.
+	NoCache pulumi.BoolPtrOutput `pulumi:"noCache"`
 	// Set target platform(s) for the build. Defaults to the host's platform.
 	//
 	// Equivalent to Docker's `--platform` flag.
@@ -564,6 +600,22 @@ type Image struct {
 	//
 	// Equivalent to Docker's `--pull` flag.
 	Pull pulumi.BoolPtrOutput `pulumi:"pull"`
+	// When `true` the build will automatically include a `registry` export.
+	//
+	// Defaults to `false`.
+	//
+	// Equivalent to Docker's `--push` flag.
+	Push pulumi.BoolPtrOutput `pulumi:"push"`
+	// If the image was pushed to any registries then this will contain a
+	// single fully-qualified tag including the build's digest.
+	//
+	// This is only for convenience and may not be appropriate for situations
+	// where multiple tags or registries are involved. In those cases this
+	// output is not guaranteed to be stable.
+	//
+	// For more control over tags consumed by downstream resources you should
+	// use the `Digests` output.
+	Ref pulumi.StringOutput `pulumi:"ref"`
 	// Registry credentials. Required if reading or exporting to private
 	// repositories.
 	//
@@ -582,6 +634,10 @@ type Image struct {
 	//
 	// Similar to Docker's `--secret` flag.
 	Secrets pulumi.StringMapOutput `pulumi:"secrets"`
+	// SSH agent socket or keys to expose to the build.
+	//
+	// Equivalent to Docker's `--ssh` flag.
+	Ssh SSHArrayOutput `pulumi:"ssh"`
 	// Name and optionally a tag (format: `name:tag`).
 	//
 	// If exporting to a registry, the name should include the fully qualified
@@ -604,13 +660,9 @@ func NewImage(ctx *pulumi.Context,
 		args = &ImageArgs{}
 	}
 
-	if args.Secrets != nil {
-		args.Secrets = pulumi.ToSecret(args.Secrets).(pulumi.StringMapInput)
+	if args.Network == nil {
+		args.Network = NetworkMode("default")
 	}
-	secrets := pulumi.AdditionalSecretOutputs([]string{
-		"secrets",
-	})
-	opts = append(opts, secrets)
 	opts = internal.PkgResourceDefaultOpts(opts)
 	var resource Image
 	err := ctx.RegisterResource("docker:buildx/image:Image", name, args, &resource, opts...)
@@ -644,6 +696,10 @@ func (ImageState) ElementType() reflect.Type {
 }
 
 type imageArgs struct {
+	// Custom `host:ip` mappings to use during the build.
+	//
+	// Equivalent to Docker's `--add-host` flag.
+	AddHosts []string `pulumi:"addHosts"`
 	// `ARG` names and values to set during the build.
 	//
 	// These variables are accessed like environment variables inside `RUN`
@@ -654,8 +710,20 @@ type imageArgs struct {
 	//
 	// Equivalent to Docker's `--build-arg` flag.
 	BuildArgs map[string]string `pulumi:"buildArgs"`
-	// When `true`, attempt to build the image during previews. The image will
-	// not be pushed to registries, however caches will still be populated.
+	// By default, preview behavior depends on the execution environment. If
+	// Pulumi detects the operation is running on a CI system (GitHub Actions,
+	// Travis CI, Azure Pipelines, etc.) then it will build images during
+	// previews as a safeguard. Otherwise, if not running on CI, previews will
+	// not build images.
+	//
+	// Setting this to `false` forces previews to never perform builds, and
+	// setting it to `true` will always build the image during previews.
+	//
+	// Images built during previews are never exported to registries, however
+	// cache manifests are still exported.
+	//
+	// On-disk Dockerfiles are always validated for syntactic correctness
+	// regardless of this setting.
 	BuildOnPreview *bool `pulumi:"buildOnPreview"`
 	// Builder configuration.
 	Builder *BuilderConfig `pulumi:"builder"`
@@ -686,6 +754,22 @@ type imageArgs struct {
 	//
 	// Equivalent to Docker's `--label` flag.
 	Labels map[string]string `pulumi:"labels"`
+	// When `true` the build will automatically include a `docker` export.
+	//
+	// Defaults to `false`.
+	//
+	// Equivalent to Docker's `--load` flag.
+	Load *bool `pulumi:"load"`
+	// Set the network mode for `RUN` instructions. Defaults to `default`.
+	//
+	// For custom networks, configure your builder with `--driver-opt network=...`.
+	//
+	// Equivalent to Docker's `--network` flag.
+	Network *NetworkMode `pulumi:"network"`
+	// Do not import cache manifests when building the image.
+	//
+	// Equivalent to Docker's `--no-cache` flag.
+	NoCache *bool `pulumi:"noCache"`
 	// Set target platform(s) for the build. Defaults to the host's platform.
 	//
 	// Equivalent to Docker's `--platform` flag.
@@ -694,6 +778,12 @@ type imageArgs struct {
 	//
 	// Equivalent to Docker's `--pull` flag.
 	Pull *bool `pulumi:"pull"`
+	// When `true` the build will automatically include a `registry` export.
+	//
+	// Defaults to `false`.
+	//
+	// Equivalent to Docker's `--push` flag.
+	Push *bool `pulumi:"push"`
 	// Registry credentials. Required if reading or exporting to private
 	// repositories.
 	//
@@ -712,6 +802,10 @@ type imageArgs struct {
 	//
 	// Similar to Docker's `--secret` flag.
 	Secrets map[string]string `pulumi:"secrets"`
+	// SSH agent socket or keys to expose to the build.
+	//
+	// Equivalent to Docker's `--ssh` flag.
+	Ssh []SSH `pulumi:"ssh"`
 	// Name and optionally a tag (format: `name:tag`).
 	//
 	// If exporting to a registry, the name should include the fully qualified
@@ -729,6 +823,10 @@ type imageArgs struct {
 
 // The set of arguments for constructing a Image resource.
 type ImageArgs struct {
+	// Custom `host:ip` mappings to use during the build.
+	//
+	// Equivalent to Docker's `--add-host` flag.
+	AddHosts pulumi.StringArrayInput
 	// `ARG` names and values to set during the build.
 	//
 	// These variables are accessed like environment variables inside `RUN`
@@ -739,8 +837,20 @@ type ImageArgs struct {
 	//
 	// Equivalent to Docker's `--build-arg` flag.
 	BuildArgs pulumi.StringMapInput
-	// When `true`, attempt to build the image during previews. The image will
-	// not be pushed to registries, however caches will still be populated.
+	// By default, preview behavior depends on the execution environment. If
+	// Pulumi detects the operation is running on a CI system (GitHub Actions,
+	// Travis CI, Azure Pipelines, etc.) then it will build images during
+	// previews as a safeguard. Otherwise, if not running on CI, previews will
+	// not build images.
+	//
+	// Setting this to `false` forces previews to never perform builds, and
+	// setting it to `true` will always build the image during previews.
+	//
+	// Images built during previews are never exported to registries, however
+	// cache manifests are still exported.
+	//
+	// On-disk Dockerfiles are always validated for syntactic correctness
+	// regardless of this setting.
 	BuildOnPreview pulumi.BoolPtrInput
 	// Builder configuration.
 	Builder BuilderConfigPtrInput
@@ -771,6 +881,22 @@ type ImageArgs struct {
 	//
 	// Equivalent to Docker's `--label` flag.
 	Labels pulumi.StringMapInput
+	// When `true` the build will automatically include a `docker` export.
+	//
+	// Defaults to `false`.
+	//
+	// Equivalent to Docker's `--load` flag.
+	Load pulumi.BoolPtrInput
+	// Set the network mode for `RUN` instructions. Defaults to `default`.
+	//
+	// For custom networks, configure your builder with `--driver-opt network=...`.
+	//
+	// Equivalent to Docker's `--network` flag.
+	Network NetworkModePtrInput
+	// Do not import cache manifests when building the image.
+	//
+	// Equivalent to Docker's `--no-cache` flag.
+	NoCache pulumi.BoolPtrInput
 	// Set target platform(s) for the build. Defaults to the host's platform.
 	//
 	// Equivalent to Docker's `--platform` flag.
@@ -779,6 +905,12 @@ type ImageArgs struct {
 	//
 	// Equivalent to Docker's `--pull` flag.
 	Pull pulumi.BoolPtrInput
+	// When `true` the build will automatically include a `registry` export.
+	//
+	// Defaults to `false`.
+	//
+	// Equivalent to Docker's `--push` flag.
+	Push pulumi.BoolPtrInput
 	// Registry credentials. Required if reading or exporting to private
 	// repositories.
 	//
@@ -797,6 +929,10 @@ type ImageArgs struct {
 	//
 	// Similar to Docker's `--secret` flag.
 	Secrets pulumi.StringMapInput
+	// SSH agent socket or keys to expose to the build.
+	//
+	// Equivalent to Docker's `--ssh` flag.
+	Ssh SSHArrayInput
 	// Name and optionally a tag (format: `name:tag`).
 	//
 	// If exporting to a registry, the name should include the fully qualified
@@ -899,6 +1035,13 @@ func (o ImageOutput) ToImageOutputWithContext(ctx context.Context) ImageOutput {
 	return o
 }
 
+// Custom `host:ip` mappings to use during the build.
+//
+// Equivalent to Docker's `--add-host` flag.
+func (o ImageOutput) AddHosts() pulumi.StringArrayOutput {
+	return o.ApplyT(func(v *Image) pulumi.StringArrayOutput { return v.AddHosts }).(pulumi.StringArrayOutput)
+}
+
 // `ARG` names and values to set during the build.
 //
 // These variables are accessed like environment variables inside `RUN`
@@ -912,8 +1055,20 @@ func (o ImageOutput) BuildArgs() pulumi.StringMapOutput {
 	return o.ApplyT(func(v *Image) pulumi.StringMapOutput { return v.BuildArgs }).(pulumi.StringMapOutput)
 }
 
-// When `true`, attempt to build the image during previews. The image will
-// not be pushed to registries, however caches will still be populated.
+// By default, preview behavior depends on the execution environment. If
+// Pulumi detects the operation is running on a CI system (GitHub Actions,
+// Travis CI, Azure Pipelines, etc.) then it will build images during
+// previews as a safeguard. Otherwise, if not running on CI, previews will
+// not build images.
+//
+// Setting this to `false` forces previews to never perform builds, and
+// setting it to `true` will always build the image during previews.
+//
+// Images built during previews are never exported to registries, however
+// cache manifests are still exported.
+//
+// On-disk Dockerfiles are always validated for syntactic correctness
+// regardless of this setting.
 func (o ImageOutput) BuildOnPreview() pulumi.BoolPtrOutput {
 	return o.ApplyT(func(v *Image) pulumi.BoolPtrOutput { return v.BuildOnPreview }).(pulumi.BoolPtrOutput)
 }
@@ -947,13 +1102,17 @@ func (o ImageOutput) Context() BuildContextPtrOutput {
 // A preliminary hash of the image's build context.
 //
 // Pulumi uses this to determine if an image _may_ need to be re-built.
-func (o ImageOutput) ContextHash() pulumi.StringPtrOutput {
-	return o.ApplyT(func(v *Image) pulumi.StringPtrOutput { return v.ContextHash }).(pulumi.StringPtrOutput)
+func (o ImageOutput) ContextHash() pulumi.StringOutput {
+	return o.ApplyT(func(v *Image) pulumi.StringOutput { return v.ContextHash }).(pulumi.StringOutput)
 }
 
-// A mapping of platform type to refs which were pushed to registries.
-func (o ImageOutput) Digests() pulumi.StringArrayMapOutput {
-	return o.ApplyT(func(v *Image) pulumi.StringArrayMapOutput { return v.Digests }).(pulumi.StringArrayMapOutput)
+// A mapping of target names to the SHA256 digest of their pushed manifest.
+//
+// If no target was specified 'default' is used as the target name.
+//
+// Pushed manifests can be referenced as `<tag>@<digest>`.
+func (o ImageOutput) Digests() pulumi.StringMapOutput {
+	return o.ApplyT(func(v *Image) pulumi.StringMapOutput { return v.Digests }).(pulumi.StringMapOutput)
 }
 
 // Dockerfile settings.
@@ -980,6 +1139,31 @@ func (o ImageOutput) Labels() pulumi.StringMapOutput {
 	return o.ApplyT(func(v *Image) pulumi.StringMapOutput { return v.Labels }).(pulumi.StringMapOutput)
 }
 
+// When `true` the build will automatically include a `docker` export.
+//
+// Defaults to `false`.
+//
+// Equivalent to Docker's `--load` flag.
+func (o ImageOutput) Load() pulumi.BoolPtrOutput {
+	return o.ApplyT(func(v *Image) pulumi.BoolPtrOutput { return v.Load }).(pulumi.BoolPtrOutput)
+}
+
+// Set the network mode for `RUN` instructions. Defaults to `default`.
+//
+// For custom networks, configure your builder with `--driver-opt network=...`.
+//
+// Equivalent to Docker's `--network` flag.
+func (o ImageOutput) Network() NetworkModePtrOutput {
+	return o.ApplyT(func(v *Image) NetworkModePtrOutput { return v.Network }).(NetworkModePtrOutput)
+}
+
+// Do not import cache manifests when building the image.
+//
+// Equivalent to Docker's `--no-cache` flag.
+func (o ImageOutput) NoCache() pulumi.BoolPtrOutput {
+	return o.ApplyT(func(v *Image) pulumi.BoolPtrOutput { return v.NoCache }).(pulumi.BoolPtrOutput)
+}
+
 // Set target platform(s) for the build. Defaults to the host's platform.
 //
 // Equivalent to Docker's `--platform` flag.
@@ -994,6 +1178,28 @@ func (o ImageOutput) Pull() pulumi.BoolPtrOutput {
 	return o.ApplyT(func(v *Image) pulumi.BoolPtrOutput { return v.Pull }).(pulumi.BoolPtrOutput)
 }
 
+// When `true` the build will automatically include a `registry` export.
+//
+// Defaults to `false`.
+//
+// Equivalent to Docker's `--push` flag.
+func (o ImageOutput) Push() pulumi.BoolPtrOutput {
+	return o.ApplyT(func(v *Image) pulumi.BoolPtrOutput { return v.Push }).(pulumi.BoolPtrOutput)
+}
+
+// If the image was pushed to any registries then this will contain a
+// single fully-qualified tag including the build's digest.
+//
+// This is only for convenience and may not be appropriate for situations
+// where multiple tags or registries are involved. In those cases this
+// output is not guaranteed to be stable.
+//
+// For more control over tags consumed by downstream resources you should
+// use the `Digests` output.
+func (o ImageOutput) Ref() pulumi.StringOutput {
+	return o.ApplyT(func(v *Image) pulumi.StringOutput { return v.Ref }).(pulumi.StringOutput)
+}
+
 // Registry credentials. Required if reading or exporting to private
 // repositories.
 //
@@ -1018,6 +1224,13 @@ func (o ImageOutput) Secrets() pulumi.StringMapOutput {
 	return o.ApplyT(func(v *Image) pulumi.StringMapOutput { return v.Secrets }).(pulumi.StringMapOutput)
 }
 
+// SSH agent socket or keys to expose to the build.
+//
+// Equivalent to Docker's `--ssh` flag.
+func (o ImageOutput) Ssh() SSHArrayOutput {
+	return o.ApplyT(func(v *Image) SSHArrayOutput { return v.Ssh }).(SSHArrayOutput)
+}
+
 // Name and optionally a tag (format: `name:tag`).
 //
 // If exporting to a registry, the name should include the fully qualified
diff --git a/sdk/go/docker/buildx/pulumiEnums.go b/sdk/go/docker/buildx/pulumiEnums.go
index 5a230a8c..098931dc 100644
--- a/sdk/go/docker/buildx/pulumiEnums.go
+++ b/sdk/go/docker/buildx/pulumiEnums.go
@@ -347,6 +347,176 @@ func (in *compressionTypePtr) ToCompressionTypePtrOutputWithContext(ctx context.
 	return pulumi.ToOutputWithContext(ctx, in).(CompressionTypePtrOutput)
 }
 
+type NetworkMode string
+
+const (
+	// The default sandbox network mode.
+	NetworkModeDefault = NetworkMode("default")
+	// Host network mode.
+	NetworkModeHost = NetworkMode("host")
+	// Disable network access.
+	NetworkModeNone = NetworkMode("none")
+)
+
+func (NetworkMode) ElementType() reflect.Type {
+	return reflect.TypeOf((*NetworkMode)(nil)).Elem()
+}
+
+func (e NetworkMode) ToNetworkModeOutput() NetworkModeOutput {
+	return pulumi.ToOutput(e).(NetworkModeOutput)
+}
+
+func (e NetworkMode) ToNetworkModeOutputWithContext(ctx context.Context) NetworkModeOutput {
+	return pulumi.ToOutputWithContext(ctx, e).(NetworkModeOutput)
+}
+
+func (e NetworkMode) ToNetworkModePtrOutput() NetworkModePtrOutput {
+	return e.ToNetworkModePtrOutputWithContext(context.Background())
+}
+
+func (e NetworkMode) ToNetworkModePtrOutputWithContext(ctx context.Context) NetworkModePtrOutput {
+	return NetworkMode(e).ToNetworkModeOutputWithContext(ctx).ToNetworkModePtrOutputWithContext(ctx)
+}
+
+func (e NetworkMode) ToStringOutput() pulumi.StringOutput {
+	return pulumi.ToOutput(pulumi.String(e)).(pulumi.StringOutput)
+}
+
+func (e NetworkMode) ToStringOutputWithContext(ctx context.Context) pulumi.StringOutput {
+	return pulumi.ToOutputWithContext(ctx, pulumi.String(e)).(pulumi.StringOutput)
+}
+
+func (e NetworkMode) ToStringPtrOutput() pulumi.StringPtrOutput {
+	return pulumi.String(e).ToStringPtrOutputWithContext(context.Background())
+}
+
+func (e NetworkMode) ToStringPtrOutputWithContext(ctx context.Context) pulumi.StringPtrOutput {
+	return pulumi.String(e).ToStringOutputWithContext(ctx).ToStringPtrOutputWithContext(ctx)
+}
+
+type NetworkModeOutput struct{ *pulumi.OutputState }
+
+func (NetworkModeOutput) ElementType() reflect.Type {
+	return reflect.TypeOf((*NetworkMode)(nil)).Elem()
+}
+
+func (o NetworkModeOutput) ToNetworkModeOutput() NetworkModeOutput {
+	return o
+}
+
+func (o NetworkModeOutput) ToNetworkModeOutputWithContext(ctx context.Context) NetworkModeOutput {
+	return o
+}
+
+func (o NetworkModeOutput) ToNetworkModePtrOutput() NetworkModePtrOutput {
+	return o.ToNetworkModePtrOutputWithContext(context.Background())
+}
+
+func (o NetworkModeOutput) ToNetworkModePtrOutputWithContext(ctx context.Context) NetworkModePtrOutput {
+	return o.ApplyTWithContext(ctx, func(_ context.Context, v NetworkMode) *NetworkMode {
+		return &v
+	}).(NetworkModePtrOutput)
+}
+
+func (o NetworkModeOutput) ToStringOutput() pulumi.StringOutput {
+	return o.ToStringOutputWithContext(context.Background())
+}
+
+func (o NetworkModeOutput) ToStringOutputWithContext(ctx context.Context) pulumi.StringOutput {
+	return o.ApplyTWithContext(ctx, func(_ context.Context, e NetworkMode) string {
+		return string(e)
+	}).(pulumi.StringOutput)
+}
+
+func (o NetworkModeOutput) ToStringPtrOutput() pulumi.StringPtrOutput {
+	return o.ToStringPtrOutputWithContext(context.Background())
+}
+
+func (o NetworkModeOutput) ToStringPtrOutputWithContext(ctx context.Context) pulumi.StringPtrOutput {
+	return o.ApplyTWithContext(ctx, func(_ context.Context, e NetworkMode) *string {
+		v := string(e)
+		return &v
+	}).(pulumi.StringPtrOutput)
+}
+
+type NetworkModePtrOutput struct{ *pulumi.OutputState }
+
+func (NetworkModePtrOutput) ElementType() reflect.Type {
+	return reflect.TypeOf((**NetworkMode)(nil)).Elem()
+}
+
+func (o NetworkModePtrOutput) ToNetworkModePtrOutput() NetworkModePtrOutput {
+	return o
+}
+
+func (o NetworkModePtrOutput) ToNetworkModePtrOutputWithContext(ctx context.Context) NetworkModePtrOutput {
+	return o
+}
+
+func (o NetworkModePtrOutput) Elem() NetworkModeOutput {
+	return o.ApplyT(func(v *NetworkMode) NetworkMode {
+		if v != nil {
+			return *v
+		}
+		var ret NetworkMode
+		return ret
+	}).(NetworkModeOutput)
+}
+
+func (o NetworkModePtrOutput) ToStringPtrOutput() pulumi.StringPtrOutput {
+	return o.ToStringPtrOutputWithContext(context.Background())
+}
+
+func (o NetworkModePtrOutput) ToStringPtrOutputWithContext(ctx context.Context) pulumi.StringPtrOutput {
+	return o.ApplyTWithContext(ctx, func(_ context.Context, e *NetworkMode) *string {
+		if e == nil {
+			return nil
+		}
+		v := string(*e)
+		return &v
+	}).(pulumi.StringPtrOutput)
+}
+
+// NetworkModeInput is an input type that accepts values of the NetworkMode enum
+// A concrete instance of `NetworkModeInput` can be one of the following:
+//
+//	NetworkModeDefault
+//	NetworkModeHost
+//	NetworkModeNone
+type NetworkModeInput interface {
+	pulumi.Input
+
+	ToNetworkModeOutput() NetworkModeOutput
+	ToNetworkModeOutputWithContext(context.Context) NetworkModeOutput
+}
+
+var networkModePtrType = reflect.TypeOf((**NetworkMode)(nil)).Elem()
+
+type NetworkModePtrInput interface {
+	pulumi.Input
+
+	ToNetworkModePtrOutput() NetworkModePtrOutput
+	ToNetworkModePtrOutputWithContext(context.Context) NetworkModePtrOutput
+}
+
+type networkModePtr string
+
+func NetworkModePtr(v string) NetworkModePtrInput {
+	return (*networkModePtr)(&v)
+}
+
+func (*networkModePtr) ElementType() reflect.Type {
+	return networkModePtrType
+}
+
+func (in *networkModePtr) ToNetworkModePtrOutput() NetworkModePtrOutput {
+	return pulumi.ToOutput(in).(NetworkModePtrOutput)
+}
+
+func (in *networkModePtr) ToNetworkModePtrOutputWithContext(ctx context.Context) NetworkModePtrOutput {
+	return pulumi.ToOutputWithContext(ctx, in).(NetworkModePtrOutput)
+}
+
 type Platform string
 
 const (
@@ -614,6 +784,8 @@ func init() {
 	pulumi.RegisterInputType(reflect.TypeOf((*CacheModePtrInput)(nil)).Elem(), CacheMode("min"))
 	pulumi.RegisterInputType(reflect.TypeOf((*CompressionTypeInput)(nil)).Elem(), CompressionType("gzip"))
 	pulumi.RegisterInputType(reflect.TypeOf((*CompressionTypePtrInput)(nil)).Elem(), CompressionType("gzip"))
+	pulumi.RegisterInputType(reflect.TypeOf((*NetworkModeInput)(nil)).Elem(), NetworkMode("default"))
+	pulumi.RegisterInputType(reflect.TypeOf((*NetworkModePtrInput)(nil)).Elem(), NetworkMode("default"))
 	pulumi.RegisterInputType(reflect.TypeOf((*PlatformInput)(nil)).Elem(), Platform("darwin/386"))
 	pulumi.RegisterInputType(reflect.TypeOf((*PlatformPtrInput)(nil)).Elem(), Platform("darwin/386"))
 	pulumi.RegisterInputType(reflect.TypeOf((*PlatformArrayInput)(nil)).Elem(), PlatformArray{})
@@ -621,6 +793,8 @@ func init() {
 	pulumi.RegisterOutputType(CacheModePtrOutput{})
 	pulumi.RegisterOutputType(CompressionTypeOutput{})
 	pulumi.RegisterOutputType(CompressionTypePtrOutput{})
+	pulumi.RegisterOutputType(NetworkModeOutput{})
+	pulumi.RegisterOutputType(NetworkModePtrOutput{})
 	pulumi.RegisterOutputType(PlatformOutput{})
 	pulumi.RegisterOutputType(PlatformPtrOutput{})
 	pulumi.RegisterOutputType(PlatformArrayOutput{})
diff --git a/sdk/go/docker/buildx/pulumiTypes.go b/sdk/go/docker/buildx/pulumiTypes.go
index 2026da88..0b396711 100644
--- a/sdk/go/docker/buildx/pulumiTypes.go
+++ b/sdk/go/docker/buildx/pulumiTypes.go
@@ -4268,9 +4268,6 @@ type ExportEntry struct {
 	Image *ExportImage `pulumi:"image"`
 	// Export to a local directory as files and directories.
 	Local *ExportLocal `pulumi:"local"`
-	// An output property populated for exporters that pushed image
-	// manifest(s) to a registry.
-	Manifests []Manifest `pulumi:"manifests"`
 	// Identical to the Docker exporter but uses OCI media types by default.
 	Oci *ExportOCI `pulumi:"oci"`
 	// A raw string as you would provide it to the Docker CLI (e.g.,
@@ -4319,9 +4316,6 @@ type ExportEntryArgs struct {
 	Image ExportImagePtrInput `pulumi:"image"`
 	// Export to a local directory as files and directories.
 	Local ExportLocalPtrInput `pulumi:"local"`
-	// An output property populated for exporters that pushed image
-	// manifest(s) to a registry.
-	Manifests ManifestArrayInput `pulumi:"manifests"`
 	// Identical to the Docker exporter but uses OCI media types by default.
 	Oci ExportOCIPtrInput `pulumi:"oci"`
 	// A raw string as you would provide it to the Docker CLI (e.g.,
@@ -4413,12 +4407,6 @@ func (o ExportEntryOutput) Local() ExportLocalPtrOutput {
 	return o.ApplyT(func(v ExportEntry) *ExportLocal { return v.Local }).(ExportLocalPtrOutput)
 }
 
-// An output property populated for exporters that pushed image
-// manifest(s) to a registry.
-func (o ExportEntryOutput) Manifests() ManifestArrayOutput {
-	return o.ApplyT(func(v ExportEntry) []Manifest { return v.Manifests }).(ManifestArrayOutput)
-}
-
 // Identical to the Docker exporter but uses OCI media types by default.
 func (o ExportEntryOutput) Oci() ExportOCIPtrOutput {
 	return o.ApplyT(func(v ExportEntry) *ExportOCI { return v.Oci }).(ExportOCIPtrOutput)
@@ -5953,191 +5941,6 @@ func (o ExportTarPtrOutput) Dest() pulumi.StringPtrOutput {
 	}).(pulumi.StringPtrOutput)
 }
 
-type Manifest struct {
-	// The SHA256 digest of the manifest.
-	Digest string `pulumi:"digest"`
-	// The manifest's platform.
-	Platform ManifestPlatform `pulumi:"platform"`
-	// The manifest's canonical ref.
-	Ref string `pulumi:"ref"`
-	// The size of the manifest in bytes.
-	Size int `pulumi:"size"`
-}
-
-// ManifestInput is an input type that accepts ManifestArgs and ManifestOutput values.
-// You can construct a concrete instance of `ManifestInput` via:
-//
-//	ManifestArgs{...}
-type ManifestInput interface {
-	pulumi.Input
-
-	ToManifestOutput() ManifestOutput
-	ToManifestOutputWithContext(context.Context) ManifestOutput
-}
-
-type ManifestArgs struct {
-	// The SHA256 digest of the manifest.
-	Digest pulumi.StringInput `pulumi:"digest"`
-	// The manifest's platform.
-	Platform ManifestPlatformInput `pulumi:"platform"`
-	// The manifest's canonical ref.
-	Ref pulumi.StringInput `pulumi:"ref"`
-	// The size of the manifest in bytes.
-	Size pulumi.IntInput `pulumi:"size"`
-}
-
-func (ManifestArgs) ElementType() reflect.Type {
-	return reflect.TypeOf((*Manifest)(nil)).Elem()
-}
-
-func (i ManifestArgs) ToManifestOutput() ManifestOutput {
-	return i.ToManifestOutputWithContext(context.Background())
-}
-
-func (i ManifestArgs) ToManifestOutputWithContext(ctx context.Context) ManifestOutput {
-	return pulumi.ToOutputWithContext(ctx, i).(ManifestOutput)
-}
-
-// ManifestArrayInput is an input type that accepts ManifestArray and ManifestArrayOutput values.
-// You can construct a concrete instance of `ManifestArrayInput` via:
-//
-//	ManifestArray{ ManifestArgs{...} }
-type ManifestArrayInput interface {
-	pulumi.Input
-
-	ToManifestArrayOutput() ManifestArrayOutput
-	ToManifestArrayOutputWithContext(context.Context) ManifestArrayOutput
-}
-
-type ManifestArray []ManifestInput
-
-func (ManifestArray) ElementType() reflect.Type {
-	return reflect.TypeOf((*[]Manifest)(nil)).Elem()
-}
-
-func (i ManifestArray) ToManifestArrayOutput() ManifestArrayOutput {
-	return i.ToManifestArrayOutputWithContext(context.Background())
-}
-
-func (i ManifestArray) ToManifestArrayOutputWithContext(ctx context.Context) ManifestArrayOutput {
-	return pulumi.ToOutputWithContext(ctx, i).(ManifestArrayOutput)
-}
-
-type ManifestOutput struct{ *pulumi.OutputState }
-
-func (ManifestOutput) ElementType() reflect.Type {
-	return reflect.TypeOf((*Manifest)(nil)).Elem()
-}
-
-func (o ManifestOutput) ToManifestOutput() ManifestOutput {
-	return o
-}
-
-func (o ManifestOutput) ToManifestOutputWithContext(ctx context.Context) ManifestOutput {
-	return o
-}
-
-// The SHA256 digest of the manifest.
-func (o ManifestOutput) Digest() pulumi.StringOutput {
-	return o.ApplyT(func(v Manifest) string { return v.Digest }).(pulumi.StringOutput)
-}
-
-// The manifest's platform.
-func (o ManifestOutput) Platform() ManifestPlatformOutput {
-	return o.ApplyT(func(v Manifest) ManifestPlatform { return v.Platform }).(ManifestPlatformOutput)
-}
-
-// The manifest's canonical ref.
-func (o ManifestOutput) Ref() pulumi.StringOutput {
-	return o.ApplyT(func(v Manifest) string { return v.Ref }).(pulumi.StringOutput)
-}
-
-// The size of the manifest in bytes.
-func (o ManifestOutput) Size() pulumi.IntOutput {
-	return o.ApplyT(func(v Manifest) int { return v.Size }).(pulumi.IntOutput)
-}
-
-type ManifestArrayOutput struct{ *pulumi.OutputState }
-
-func (ManifestArrayOutput) ElementType() reflect.Type {
-	return reflect.TypeOf((*[]Manifest)(nil)).Elem()
-}
-
-func (o ManifestArrayOutput) ToManifestArrayOutput() ManifestArrayOutput {
-	return o
-}
-
-func (o ManifestArrayOutput) ToManifestArrayOutputWithContext(ctx context.Context) ManifestArrayOutput {
-	return o
-}
-
-func (o ManifestArrayOutput) Index(i pulumi.IntInput) ManifestOutput {
-	return pulumi.All(o, i).ApplyT(func(vs []interface{}) Manifest {
-		return vs[0].([]Manifest)[vs[1].(int)]
-	}).(ManifestOutput)
-}
-
-type ManifestPlatform struct {
-	// The manifest's architecture.
-	Architecture string `pulumi:"architecture"`
-	// The manifest's operating systen.
-	Os string `pulumi:"os"`
-}
-
-// ManifestPlatformInput is an input type that accepts ManifestPlatformArgs and ManifestPlatformOutput values.
-// You can construct a concrete instance of `ManifestPlatformInput` via:
-//
-//	ManifestPlatformArgs{...}
-type ManifestPlatformInput interface {
-	pulumi.Input
-
-	ToManifestPlatformOutput() ManifestPlatformOutput
-	ToManifestPlatformOutputWithContext(context.Context) ManifestPlatformOutput
-}
-
-type ManifestPlatformArgs struct {
-	// The manifest's architecture.
-	Architecture pulumi.StringInput `pulumi:"architecture"`
-	// The manifest's operating systen.
-	Os pulumi.StringInput `pulumi:"os"`
-}
-
-func (ManifestPlatformArgs) ElementType() reflect.Type {
-	return reflect.TypeOf((*ManifestPlatform)(nil)).Elem()
-}
-
-func (i ManifestPlatformArgs) ToManifestPlatformOutput() ManifestPlatformOutput {
-	return i.ToManifestPlatformOutputWithContext(context.Background())
-}
-
-func (i ManifestPlatformArgs) ToManifestPlatformOutputWithContext(ctx context.Context) ManifestPlatformOutput {
-	return pulumi.ToOutputWithContext(ctx, i).(ManifestPlatformOutput)
-}
-
-type ManifestPlatformOutput struct{ *pulumi.OutputState }
-
-func (ManifestPlatformOutput) ElementType() reflect.Type {
-	return reflect.TypeOf((*ManifestPlatform)(nil)).Elem()
-}
-
-func (o ManifestPlatformOutput) ToManifestPlatformOutput() ManifestPlatformOutput {
-	return o
-}
-
-func (o ManifestPlatformOutput) ToManifestPlatformOutputWithContext(ctx context.Context) ManifestPlatformOutput {
-	return o
-}
-
-// The manifest's architecture.
-func (o ManifestPlatformOutput) Architecture() pulumi.StringOutput {
-	return o.ApplyT(func(v ManifestPlatform) string { return v.Architecture }).(pulumi.StringOutput)
-}
-
-// The manifest's operating systen.
-func (o ManifestPlatformOutput) Os() pulumi.StringOutput {
-	return o.ApplyT(func(v ManifestPlatform) string { return v.Os }).(pulumi.StringOutput)
-}
-
 type RegistryAuth struct {
 	// The registry's address (e.g. "docker.io").
 	Address string `pulumi:"address"`
@@ -6253,6 +6056,142 @@ func (o RegistryAuthArrayOutput) Index(i pulumi.IntInput) RegistryAuthOutput {
 	}).(RegistryAuthOutput)
 }
 
+type SSH struct {
+	// Useful for distinguishing different servers that are part of the same
+	// build.
+	//
+	// A value of `default` is appropriate if only dealing with a single host.
+	Id string `pulumi:"id"`
+	// SSH agent socket or private keys to expose to the build under the given
+	// identifier.
+	//
+	// Defaults to `[$SSH_AUTH_SOCK]`.
+	//
+	// Note that your keys are **not** automatically added when using an
+	// agent. Run `ssh-add -l` locally to confirm which public keys are
+	// visible to the agent; these will be exposed to your build.
+	Paths []string `pulumi:"paths"`
+}
+
+// SSHInput is an input type that accepts SSHArgs and SSHOutput values.
+// You can construct a concrete instance of `SSHInput` via:
+//
+//	SSHArgs{...}
+type SSHInput interface {
+	pulumi.Input
+
+	ToSSHOutput() SSHOutput
+	ToSSHOutputWithContext(context.Context) SSHOutput
+}
+
+type SSHArgs struct {
+	// Useful for distinguishing different servers that are part of the same
+	// build.
+	//
+	// A value of `default` is appropriate if only dealing with a single host.
+	Id pulumi.StringInput `pulumi:"id"`
+	// SSH agent socket or private keys to expose to the build under the given
+	// identifier.
+	//
+	// Defaults to `[$SSH_AUTH_SOCK]`.
+	//
+	// Note that your keys are **not** automatically added when using an
+	// agent. Run `ssh-add -l` locally to confirm which public keys are
+	// visible to the agent; these will be exposed to your build.
+	Paths pulumi.StringArrayInput `pulumi:"paths"`
+}
+
+func (SSHArgs) ElementType() reflect.Type {
+	return reflect.TypeOf((*SSH)(nil)).Elem()
+}
+
+func (i SSHArgs) ToSSHOutput() SSHOutput {
+	return i.ToSSHOutputWithContext(context.Background())
+}
+
+func (i SSHArgs) ToSSHOutputWithContext(ctx context.Context) SSHOutput {
+	return pulumi.ToOutputWithContext(ctx, i).(SSHOutput)
+}
+
+// SSHArrayInput is an input type that accepts SSHArray and SSHArrayOutput values.
+// You can construct a concrete instance of `SSHArrayInput` via:
+//
+//	SSHArray{ SSHArgs{...} }
+type SSHArrayInput interface {
+	pulumi.Input
+
+	ToSSHArrayOutput() SSHArrayOutput
+	ToSSHArrayOutputWithContext(context.Context) SSHArrayOutput
+}
+
+type SSHArray []SSHInput
+
+func (SSHArray) ElementType() reflect.Type {
+	return reflect.TypeOf((*[]SSH)(nil)).Elem()
+}
+
+func (i SSHArray) ToSSHArrayOutput() SSHArrayOutput {
+	return i.ToSSHArrayOutputWithContext(context.Background())
+}
+
+func (i SSHArray) ToSSHArrayOutputWithContext(ctx context.Context) SSHArrayOutput {
+	return pulumi.ToOutputWithContext(ctx, i).(SSHArrayOutput)
+}
+
+type SSHOutput struct{ *pulumi.OutputState }
+
+func (SSHOutput) ElementType() reflect.Type {
+	return reflect.TypeOf((*SSH)(nil)).Elem()
+}
+
+func (o SSHOutput) ToSSHOutput() SSHOutput {
+	return o
+}
+
+func (o SSHOutput) ToSSHOutputWithContext(ctx context.Context) SSHOutput {
+	return o
+}
+
+// Useful for distinguishing different servers that are part of the same
+// build.
+//
+// A value of `default` is appropriate if only dealing with a single host.
+func (o SSHOutput) Id() pulumi.StringOutput {
+	return o.ApplyT(func(v SSH) string { return v.Id }).(pulumi.StringOutput)
+}
+
+// SSH agent socket or private keys to expose to the build under the given
+// identifier.
+//
+// Defaults to `[$SSH_AUTH_SOCK]`.
+//
+// Note that your keys are **not** automatically added when using an
+// agent. Run `ssh-add -l` locally to confirm which public keys are
+// visible to the agent; these will be exposed to your build.
+func (o SSHOutput) Paths() pulumi.StringArrayOutput {
+	return o.ApplyT(func(v SSH) []string { return v.Paths }).(pulumi.StringArrayOutput)
+}
+
+type SSHArrayOutput struct{ *pulumi.OutputState }
+
+func (SSHArrayOutput) ElementType() reflect.Type {
+	return reflect.TypeOf((*[]SSH)(nil)).Elem()
+}
+
+func (o SSHArrayOutput) ToSSHArrayOutput() SSHArrayOutput {
+	return o
+}
+
+func (o SSHArrayOutput) ToSSHArrayOutputWithContext(ctx context.Context) SSHArrayOutput {
+	return o
+}
+
+func (o SSHArrayOutput) Index(i pulumi.IntInput) SSHOutput {
+	return pulumi.All(o, i).ApplyT(func(vs []interface{}) SSH {
+		return vs[0].([]SSH)[vs[1].(int)]
+	}).(SSHOutput)
+}
+
 func init() {
 	pulumi.RegisterInputType(reflect.TypeOf((*BuildContextInput)(nil)).Elem(), BuildContextArgs{})
 	pulumi.RegisterInputType(reflect.TypeOf((*BuildContextPtrInput)(nil)).Elem(), BuildContextArgs{})
@@ -6302,11 +6241,10 @@ func init() {
 	pulumi.RegisterInputType(reflect.TypeOf((*ExportRegistryPtrInput)(nil)).Elem(), ExportRegistryArgs{})
 	pulumi.RegisterInputType(reflect.TypeOf((*ExportTarInput)(nil)).Elem(), ExportTarArgs{})
 	pulumi.RegisterInputType(reflect.TypeOf((*ExportTarPtrInput)(nil)).Elem(), ExportTarArgs{})
-	pulumi.RegisterInputType(reflect.TypeOf((*ManifestInput)(nil)).Elem(), ManifestArgs{})
-	pulumi.RegisterInputType(reflect.TypeOf((*ManifestArrayInput)(nil)).Elem(), ManifestArray{})
-	pulumi.RegisterInputType(reflect.TypeOf((*ManifestPlatformInput)(nil)).Elem(), ManifestPlatformArgs{})
 	pulumi.RegisterInputType(reflect.TypeOf((*RegistryAuthInput)(nil)).Elem(), RegistryAuthArgs{})
 	pulumi.RegisterInputType(reflect.TypeOf((*RegistryAuthArrayInput)(nil)).Elem(), RegistryAuthArray{})
+	pulumi.RegisterInputType(reflect.TypeOf((*SSHInput)(nil)).Elem(), SSHArgs{})
+	pulumi.RegisterInputType(reflect.TypeOf((*SSHArrayInput)(nil)).Elem(), SSHArray{})
 	pulumi.RegisterOutputType(BuildContextOutput{})
 	pulumi.RegisterOutputType(BuildContextPtrOutput{})
 	pulumi.RegisterOutputType(BuilderConfigOutput{})
@@ -6355,9 +6293,8 @@ func init() {
 	pulumi.RegisterOutputType(ExportRegistryPtrOutput{})
 	pulumi.RegisterOutputType(ExportTarOutput{})
 	pulumi.RegisterOutputType(ExportTarPtrOutput{})
-	pulumi.RegisterOutputType(ManifestOutput{})
-	pulumi.RegisterOutputType(ManifestArrayOutput{})
-	pulumi.RegisterOutputType(ManifestPlatformOutput{})
 	pulumi.RegisterOutputType(RegistryAuthOutput{})
 	pulumi.RegisterOutputType(RegistryAuthArrayOutput{})
+	pulumi.RegisterOutputType(SSHOutput{})
+	pulumi.RegisterOutputType(SSHArrayOutput{})
 }
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/Image.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/Image.java
index 1bff2d86..38198db8 100644
--- a/sdk/java/src/main/java/com/pulumi/docker/buildx/Image.java
+++ b/sdk/java/src/main/java/com/pulumi/docker/buildx/Image.java
@@ -9,6 +9,7 @@
 import com.pulumi.core.internal.Codegen;
 import com.pulumi.docker.Utilities;
 import com.pulumi.docker.buildx.ImageArgs;
+import com.pulumi.docker.buildx.enums.NetworkMode;
 import com.pulumi.docker.buildx.enums.Platform;
 import com.pulumi.docker.buildx.outputs.BuildContext;
 import com.pulumi.docker.buildx.outputs.BuilderConfig;
@@ -17,6 +18,7 @@
 import com.pulumi.docker.buildx.outputs.Dockerfile;
 import com.pulumi.docker.buildx.outputs.ExportEntry;
 import com.pulumi.docker.buildx.outputs.RegistryAuth;
+import com.pulumi.docker.buildx.outputs.SSH;
 import java.lang.Boolean;
 import java.lang.String;
 import java.util.List;
@@ -570,6 +572,24 @@
  */
 @ResourceType(type="docker:buildx/image:Image")
 public class Image extends com.pulumi.resources.CustomResource {
+    /**
+     * Custom `host:ip` mappings to use during the build.
+     * 
+     * Equivalent to Docker&#39;s `--add-host` flag.
+     * 
+     */
+    @Export(name="addHosts", refs={List.class,String.class}, tree="[0,1]")
+    private Output</* @Nullable */ List<String>> addHosts;
+
+    /**
+     * @return Custom `host:ip` mappings to use during the build.
+     * 
+     * Equivalent to Docker&#39;s `--add-host` flag.
+     * 
+     */
+    public Output<Optional<List<String>>> addHosts() {
+        return Codegen.optional(this.addHosts);
+    }
     /**
      * `ARG` names and values to set during the build.
      * 
@@ -601,16 +621,40 @@ public Output<Optional<Map<String,String>>> buildArgs() {
         return Codegen.optional(this.buildArgs);
     }
     /**
-     * When `true`, attempt to build the image during previews. The image will
-     * not be pushed to registries, however caches will still be populated.
+     * By default, preview behavior depends on the execution environment. If
+     * Pulumi detects the operation is running on a CI system (GitHub Actions,
+     * Travis CI, Azure Pipelines, etc.) then it will build images during
+     * previews as a safeguard. Otherwise, if not running on CI, previews will
+     * not build images.
+     * 
+     * Setting this to `false` forces previews to never perform builds, and
+     * setting it to `true` will always build the image during previews.
+     * 
+     * Images built during previews are never exported to registries, however
+     * cache manifests are still exported.
+     * 
+     * On-disk Dockerfiles are always validated for syntactic correctness
+     * regardless of this setting.
      * 
      */
     @Export(name="buildOnPreview", refs={Boolean.class}, tree="[0]")
     private Output</* @Nullable */ Boolean> buildOnPreview;
 
     /**
-     * @return When `true`, attempt to build the image during previews. The image will
-     * not be pushed to registries, however caches will still be populated.
+     * @return By default, preview behavior depends on the execution environment. If
+     * Pulumi detects the operation is running on a CI system (GitHub Actions,
+     * Travis CI, Azure Pipelines, etc.) then it will build images during
+     * previews as a safeguard. Otherwise, if not running on CI, previews will
+     * not build images.
+     * 
+     * Setting this to `false` forces previews to never perform builds, and
+     * setting it to `true` will always build the image during previews.
+     * 
+     * Images built during previews are never exported to registries, however
+     * cache manifests are still exported.
+     * 
+     * On-disk Dockerfiles are always validated for syntactic correctness
+     * regardless of this setting.
      * 
      */
     public Output<Optional<Boolean>> buildOnPreview() {
@@ -691,7 +735,7 @@ public Output<Optional<BuildContext>> context() {
      * 
      */
     @Export(name="contextHash", refs={String.class}, tree="[0]")
-    private Output</* @Nullable */ String> contextHash;
+    private Output<String> contextHash;
 
     /**
      * @return A preliminary hash of the image&#39;s build context.
@@ -699,22 +743,30 @@ public Output<Optional<BuildContext>> context() {
      * Pulumi uses this to determine if an image _may_ need to be re-built.
      * 
      */
-    public Output<Optional<String>> contextHash() {
-        return Codegen.optional(this.contextHash);
+    public Output<String> contextHash() {
+        return this.contextHash;
     }
     /**
-     * A mapping of platform type to refs which were pushed to registries.
+     * A mapping of target names to the SHA256 digest of their pushed manifest.
+     * 
+     * If no target was specified &#39;default&#39; is used as the target name.
+     * 
+     * Pushed manifests can be referenced as `&lt;tag&gt;@&lt;digest&gt;`.
      * 
      */
-    @Export(name="digests", refs={Map.class,String.class,List.class}, tree="[0,1,[2,1]]")
-    private Output</* @Nullable */ Map<String,List<String>>> digests;
+    @Export(name="digests", refs={Map.class,String.class}, tree="[0,1,1]")
+    private Output<Map<String,String>> digests;
 
     /**
-     * @return A mapping of platform type to refs which were pushed to registries.
+     * @return A mapping of target names to the SHA256 digest of their pushed manifest.
+     * 
+     * If no target was specified &#39;default&#39; is used as the target name.
+     * 
+     * Pushed manifests can be referenced as `&lt;tag&gt;@&lt;digest&gt;`.
      * 
      */
-    public Output<Optional<Map<String,List<String>>>> digests() {
-        return Codegen.optional(this.digests);
+    public Output<Map<String,String>> digests() {
+        return this.digests;
     }
     /**
      * Dockerfile settings.
@@ -776,6 +828,68 @@ public Output<Optional<List<ExportEntry>>> exports() {
     public Output<Optional<Map<String,String>>> labels() {
         return Codegen.optional(this.labels);
     }
+    /**
+     * When `true` the build will automatically include a `docker` export.
+     * 
+     * Defaults to `false`.
+     * 
+     * Equivalent to Docker&#39;s `--load` flag.
+     * 
+     */
+    @Export(name="load", refs={Boolean.class}, tree="[0]")
+    private Output</* @Nullable */ Boolean> load;
+
+    /**
+     * @return When `true` the build will automatically include a `docker` export.
+     * 
+     * Defaults to `false`.
+     * 
+     * Equivalent to Docker&#39;s `--load` flag.
+     * 
+     */
+    public Output<Optional<Boolean>> load() {
+        return Codegen.optional(this.load);
+    }
+    /**
+     * Set the network mode for `RUN` instructions. Defaults to `default`.
+     * 
+     * For custom networks, configure your builder with `--driver-opt network=...`.
+     * 
+     * Equivalent to Docker&#39;s `--network` flag.
+     * 
+     */
+    @Export(name="network", refs={NetworkMode.class}, tree="[0]")
+    private Output</* @Nullable */ NetworkMode> network;
+
+    /**
+     * @return Set the network mode for `RUN` instructions. Defaults to `default`.
+     * 
+     * For custom networks, configure your builder with `--driver-opt network=...`.
+     * 
+     * Equivalent to Docker&#39;s `--network` flag.
+     * 
+     */
+    public Output<Optional<NetworkMode>> network() {
+        return Codegen.optional(this.network);
+    }
+    /**
+     * Do not import cache manifests when building the image.
+     * 
+     * Equivalent to Docker&#39;s `--no-cache` flag.
+     * 
+     */
+    @Export(name="noCache", refs={Boolean.class}, tree="[0]")
+    private Output</* @Nullable */ Boolean> noCache;
+
+    /**
+     * @return Do not import cache manifests when building the image.
+     * 
+     * Equivalent to Docker&#39;s `--no-cache` flag.
+     * 
+     */
+    public Output<Optional<Boolean>> noCache() {
+        return Codegen.optional(this.noCache);
+    }
     /**
      * Set target platform(s) for the build. Defaults to the host&#39;s platform.
      * 
@@ -812,6 +926,58 @@ public Output<Optional<List<Platform>>> platforms() {
     public Output<Optional<Boolean>> pull() {
         return Codegen.optional(this.pull);
     }
+    /**
+     * When `true` the build will automatically include a `registry` export.
+     * 
+     * Defaults to `false`.
+     * 
+     * Equivalent to Docker&#39;s `--push` flag.
+     * 
+     */
+    @Export(name="push", refs={Boolean.class}, tree="[0]")
+    private Output</* @Nullable */ Boolean> push;
+
+    /**
+     * @return When `true` the build will automatically include a `registry` export.
+     * 
+     * Defaults to `false`.
+     * 
+     * Equivalent to Docker&#39;s `--push` flag.
+     * 
+     */
+    public Output<Optional<Boolean>> push() {
+        return Codegen.optional(this.push);
+    }
+    /**
+     * If the image was pushed to any registries then this will contain a
+     * single fully-qualified tag including the build&#39;s digest.
+     * 
+     * This is only for convenience and may not be appropriate for situations
+     * where multiple tags or registries are involved. In those cases this
+     * output is not guaranteed to be stable.
+     * 
+     * For more control over tags consumed by downstream resources you should
+     * use the `Digests` output.
+     * 
+     */
+    @Export(name="ref", refs={String.class}, tree="[0]")
+    private Output<String> ref;
+
+    /**
+     * @return If the image was pushed to any registries then this will contain a
+     * single fully-qualified tag including the build&#39;s digest.
+     * 
+     * This is only for convenience and may not be appropriate for situations
+     * where multiple tags or registries are involved. In those cases this
+     * output is not guaranteed to be stable.
+     * 
+     * For more control over tags consumed by downstream resources you should
+     * use the `Digests` output.
+     * 
+     */
+    public Output<String> ref() {
+        return this.ref;
+    }
     /**
      * Registry credentials. Required if reading or exporting to private
      * repositories.
@@ -868,6 +1034,24 @@ public Output<Optional<List<RegistryAuth>>> registries() {
     public Output<Optional<Map<String,String>>> secrets() {
         return Codegen.optional(this.secrets);
     }
+    /**
+     * SSH agent socket or keys to expose to the build.
+     * 
+     * Equivalent to Docker&#39;s `--ssh` flag.
+     * 
+     */
+    @Export(name="ssh", refs={List.class,SSH.class}, tree="[0,1]")
+    private Output</* @Nullable */ List<SSH>> ssh;
+
+    /**
+     * @return SSH agent socket or keys to expose to the build.
+     * 
+     * Equivalent to Docker&#39;s `--ssh` flag.
+     * 
+     */
+    public Output<Optional<List<SSH>>> ssh() {
+        return Codegen.optional(this.ssh);
+    }
     /**
      * Name and optionally a tag (format: `name:tag`).
      * 
@@ -947,9 +1131,6 @@ private Image(String name, Output<String> id, @Nullable com.pulumi.resources.Cus
     private static com.pulumi.resources.CustomResourceOptions makeResourceOptions(@Nullable com.pulumi.resources.CustomResourceOptions options, @Nullable Output<String> id) {
         var defaultOptions = com.pulumi.resources.CustomResourceOptions.builder()
             .version(Utilities.getVersion())
-            .additionalSecretOutputs(List.of(
-                "secrets"
-            ))
             .build();
         return com.pulumi.resources.CustomResourceOptions.merge(defaultOptions, options, id);
     }
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/ImageArgs.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/ImageArgs.java
index b53352b4..2406a894 100644
--- a/sdk/java/src/main/java/com/pulumi/docker/buildx/ImageArgs.java
+++ b/sdk/java/src/main/java/com/pulumi/docker/buildx/ImageArgs.java
@@ -5,6 +5,8 @@
 
 import com.pulumi.core.Output;
 import com.pulumi.core.annotations.Import;
+import com.pulumi.core.internal.Codegen;
+import com.pulumi.docker.buildx.enums.NetworkMode;
 import com.pulumi.docker.buildx.enums.Platform;
 import com.pulumi.docker.buildx.inputs.BuildContextArgs;
 import com.pulumi.docker.buildx.inputs.BuilderConfigArgs;
@@ -13,6 +15,7 @@
 import com.pulumi.docker.buildx.inputs.DockerfileArgs;
 import com.pulumi.docker.buildx.inputs.ExportEntryArgs;
 import com.pulumi.docker.buildx.inputs.RegistryAuthArgs;
+import com.pulumi.docker.buildx.inputs.SSHArgs;
 import java.lang.Boolean;
 import java.lang.String;
 import java.util.List;
@@ -26,6 +29,25 @@ public final class ImageArgs extends com.pulumi.resources.ResourceArgs {
 
     public static final ImageArgs Empty = new ImageArgs();
 
+    /**
+     * Custom `host:ip` mappings to use during the build.
+     * 
+     * Equivalent to Docker&#39;s `--add-host` flag.
+     * 
+     */
+    @Import(name="addHosts")
+    private @Nullable Output<List<String>> addHosts;
+
+    /**
+     * @return Custom `host:ip` mappings to use during the build.
+     * 
+     * Equivalent to Docker&#39;s `--add-host` flag.
+     * 
+     */
+    public Optional<Output<List<String>>> addHosts() {
+        return Optional.ofNullable(this.addHosts);
+    }
+
     /**
      * `ARG` names and values to set during the build.
      * 
@@ -58,16 +80,40 @@ public Optional<Output<Map<String,String>>> buildArgs() {
     }
 
     /**
-     * When `true`, attempt to build the image during previews. The image will
-     * not be pushed to registries, however caches will still be populated.
+     * By default, preview behavior depends on the execution environment. If
+     * Pulumi detects the operation is running on a CI system (GitHub Actions,
+     * Travis CI, Azure Pipelines, etc.) then it will build images during
+     * previews as a safeguard. Otherwise, if not running on CI, previews will
+     * not build images.
+     * 
+     * Setting this to `false` forces previews to never perform builds, and
+     * setting it to `true` will always build the image during previews.
+     * 
+     * Images built during previews are never exported to registries, however
+     * cache manifests are still exported.
+     * 
+     * On-disk Dockerfiles are always validated for syntactic correctness
+     * regardless of this setting.
      * 
      */
     @Import(name="buildOnPreview")
     private @Nullable Output<Boolean> buildOnPreview;
 
     /**
-     * @return When `true`, attempt to build the image during previews. The image will
-     * not be pushed to registries, however caches will still be populated.
+     * @return By default, preview behavior depends on the execution environment. If
+     * Pulumi detects the operation is running on a CI system (GitHub Actions,
+     * Travis CI, Azure Pipelines, etc.) then it will build images during
+     * previews as a safeguard. Otherwise, if not running on CI, previews will
+     * not build images.
+     * 
+     * Setting this to `false` forces previews to never perform builds, and
+     * setting it to `true` will always build the image during previews.
+     * 
+     * Images built during previews are never exported to registries, however
+     * cache manifests are still exported.
+     * 
+     * On-disk Dockerfiles are always validated for syntactic correctness
+     * regardless of this setting.
      * 
      */
     public Optional<Output<Boolean>> buildOnPreview() {
@@ -209,6 +255,71 @@ public Optional<Output<Map<String,String>>> labels() {
         return Optional.ofNullable(this.labels);
     }
 
+    /**
+     * When `true` the build will automatically include a `docker` export.
+     * 
+     * Defaults to `false`.
+     * 
+     * Equivalent to Docker&#39;s `--load` flag.
+     * 
+     */
+    @Import(name="load")
+    private @Nullable Output<Boolean> load;
+
+    /**
+     * @return When `true` the build will automatically include a `docker` export.
+     * 
+     * Defaults to `false`.
+     * 
+     * Equivalent to Docker&#39;s `--load` flag.
+     * 
+     */
+    public Optional<Output<Boolean>> load() {
+        return Optional.ofNullable(this.load);
+    }
+
+    /**
+     * Set the network mode for `RUN` instructions. Defaults to `default`.
+     * 
+     * For custom networks, configure your builder with `--driver-opt network=...`.
+     * 
+     * Equivalent to Docker&#39;s `--network` flag.
+     * 
+     */
+    @Import(name="network")
+    private @Nullable Output<NetworkMode> network;
+
+    /**
+     * @return Set the network mode for `RUN` instructions. Defaults to `default`.
+     * 
+     * For custom networks, configure your builder with `--driver-opt network=...`.
+     * 
+     * Equivalent to Docker&#39;s `--network` flag.
+     * 
+     */
+    public Optional<Output<NetworkMode>> network() {
+        return Optional.ofNullable(this.network);
+    }
+
+    /**
+     * Do not import cache manifests when building the image.
+     * 
+     * Equivalent to Docker&#39;s `--no-cache` flag.
+     * 
+     */
+    @Import(name="noCache")
+    private @Nullable Output<Boolean> noCache;
+
+    /**
+     * @return Do not import cache manifests when building the image.
+     * 
+     * Equivalent to Docker&#39;s `--no-cache` flag.
+     * 
+     */
+    public Optional<Output<Boolean>> noCache() {
+        return Optional.ofNullable(this.noCache);
+    }
+
     /**
      * Set target platform(s) for the build. Defaults to the host&#39;s platform.
      * 
@@ -247,6 +358,29 @@ public Optional<Output<Boolean>> pull() {
         return Optional.ofNullable(this.pull);
     }
 
+    /**
+     * When `true` the build will automatically include a `registry` export.
+     * 
+     * Defaults to `false`.
+     * 
+     * Equivalent to Docker&#39;s `--push` flag.
+     * 
+     */
+    @Import(name="push")
+    private @Nullable Output<Boolean> push;
+
+    /**
+     * @return When `true` the build will automatically include a `registry` export.
+     * 
+     * Defaults to `false`.
+     * 
+     * Equivalent to Docker&#39;s `--push` flag.
+     * 
+     */
+    public Optional<Output<Boolean>> push() {
+        return Optional.ofNullable(this.push);
+    }
+
     /**
      * Registry credentials. Required if reading or exporting to private
      * repositories.
@@ -305,6 +439,25 @@ public Optional<Output<Map<String,String>>> secrets() {
         return Optional.ofNullable(this.secrets);
     }
 
+    /**
+     * SSH agent socket or keys to expose to the build.
+     * 
+     * Equivalent to Docker&#39;s `--ssh` flag.
+     * 
+     */
+    @Import(name="ssh")
+    private @Nullable Output<List<SSHArgs>> ssh;
+
+    /**
+     * @return SSH agent socket or keys to expose to the build.
+     * 
+     * Equivalent to Docker&#39;s `--ssh` flag.
+     * 
+     */
+    public Optional<Output<List<SSHArgs>>> ssh() {
+        return Optional.ofNullable(this.ssh);
+    }
+
     /**
      * Name and optionally a tag (format: `name:tag`).
      * 
@@ -356,6 +509,7 @@ public Optional<Output<List<String>>> targets() {
     private ImageArgs() {}
 
     private ImageArgs(ImageArgs $) {
+        this.addHosts = $.addHosts;
         this.buildArgs = $.buildArgs;
         this.buildOnPreview = $.buildOnPreview;
         this.builder = $.builder;
@@ -365,10 +519,15 @@ private ImageArgs(ImageArgs $) {
         this.dockerfile = $.dockerfile;
         this.exports = $.exports;
         this.labels = $.labels;
+        this.load = $.load;
+        this.network = $.network;
+        this.noCache = $.noCache;
         this.platforms = $.platforms;
         this.pull = $.pull;
+        this.push = $.push;
         this.registries = $.registries;
         this.secrets = $.secrets;
+        this.ssh = $.ssh;
         this.tags = $.tags;
         this.targets = $.targets;
     }
@@ -391,6 +550,43 @@ public Builder(ImageArgs defaults) {
             $ = new ImageArgs(Objects.requireNonNull(defaults));
         }
 
+        /**
+         * @param addHosts Custom `host:ip` mappings to use during the build.
+         * 
+         * Equivalent to Docker&#39;s `--add-host` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder addHosts(@Nullable Output<List<String>> addHosts) {
+            $.addHosts = addHosts;
+            return this;
+        }
+
+        /**
+         * @param addHosts Custom `host:ip` mappings to use during the build.
+         * 
+         * Equivalent to Docker&#39;s `--add-host` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder addHosts(List<String> addHosts) {
+            return addHosts(Output.of(addHosts));
+        }
+
+        /**
+         * @param addHosts Custom `host:ip` mappings to use during the build.
+         * 
+         * Equivalent to Docker&#39;s `--add-host` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder addHosts(String... addHosts) {
+            return addHosts(List.of(addHosts));
+        }
+
         /**
          * @param buildArgs `ARG` names and values to set during the build.
          * 
@@ -429,8 +625,20 @@ public Builder buildArgs(Map<String,String> buildArgs) {
         }
 
         /**
-         * @param buildOnPreview When `true`, attempt to build the image during previews. The image will
-         * not be pushed to registries, however caches will still be populated.
+         * @param buildOnPreview By default, preview behavior depends on the execution environment. If
+         * Pulumi detects the operation is running on a CI system (GitHub Actions,
+         * Travis CI, Azure Pipelines, etc.) then it will build images during
+         * previews as a safeguard. Otherwise, if not running on CI, previews will
+         * not build images.
+         * 
+         * Setting this to `false` forces previews to never perform builds, and
+         * setting it to `true` will always build the image during previews.
+         * 
+         * Images built during previews are never exported to registries, however
+         * cache manifests are still exported.
+         * 
+         * On-disk Dockerfiles are always validated for syntactic correctness
+         * regardless of this setting.
          * 
          * @return builder
          * 
@@ -441,8 +649,20 @@ public Builder buildOnPreview(@Nullable Output<Boolean> buildOnPreview) {
         }
 
         /**
-         * @param buildOnPreview When `true`, attempt to build the image during previews. The image will
-         * not be pushed to registries, however caches will still be populated.
+         * @param buildOnPreview By default, preview behavior depends on the execution environment. If
+         * Pulumi detects the operation is running on a CI system (GitHub Actions,
+         * Travis CI, Azure Pipelines, etc.) then it will build images during
+         * previews as a safeguard. Otherwise, if not running on CI, previews will
+         * not build images.
+         * 
+         * Setting this to `false` forces previews to never perform builds, and
+         * setting it to `true` will always build the image during previews.
+         * 
+         * Images built during previews are never exported to registries, however
+         * cache manifests are still exported.
+         * 
+         * On-disk Dockerfiles are always validated for syntactic correctness
+         * regardless of this setting.
          * 
          * @return builder
          * 
@@ -667,6 +887,89 @@ public Builder labels(Map<String,String> labels) {
             return labels(Output.of(labels));
         }
 
+        /**
+         * @param load When `true` the build will automatically include a `docker` export.
+         * 
+         * Defaults to `false`.
+         * 
+         * Equivalent to Docker&#39;s `--load` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder load(@Nullable Output<Boolean> load) {
+            $.load = load;
+            return this;
+        }
+
+        /**
+         * @param load When `true` the build will automatically include a `docker` export.
+         * 
+         * Defaults to `false`.
+         * 
+         * Equivalent to Docker&#39;s `--load` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder load(Boolean load) {
+            return load(Output.of(load));
+        }
+
+        /**
+         * @param network Set the network mode for `RUN` instructions. Defaults to `default`.
+         * 
+         * For custom networks, configure your builder with `--driver-opt network=...`.
+         * 
+         * Equivalent to Docker&#39;s `--network` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder network(@Nullable Output<NetworkMode> network) {
+            $.network = network;
+            return this;
+        }
+
+        /**
+         * @param network Set the network mode for `RUN` instructions. Defaults to `default`.
+         * 
+         * For custom networks, configure your builder with `--driver-opt network=...`.
+         * 
+         * Equivalent to Docker&#39;s `--network` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder network(NetworkMode network) {
+            return network(Output.of(network));
+        }
+
+        /**
+         * @param noCache Do not import cache manifests when building the image.
+         * 
+         * Equivalent to Docker&#39;s `--no-cache` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder noCache(@Nullable Output<Boolean> noCache) {
+            $.noCache = noCache;
+            return this;
+        }
+
+        /**
+         * @param noCache Do not import cache manifests when building the image.
+         * 
+         * Equivalent to Docker&#39;s `--no-cache` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder noCache(Boolean noCache) {
+            return noCache(Output.of(noCache));
+        }
+
         /**
          * @param platforms Set target platform(s) for the build. Defaults to the host&#39;s platform.
          * 
@@ -729,6 +1032,35 @@ public Builder pull(Boolean pull) {
             return pull(Output.of(pull));
         }
 
+        /**
+         * @param push When `true` the build will automatically include a `registry` export.
+         * 
+         * Defaults to `false`.
+         * 
+         * Equivalent to Docker&#39;s `--push` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder push(@Nullable Output<Boolean> push) {
+            $.push = push;
+            return this;
+        }
+
+        /**
+         * @param push When `true` the build will automatically include a `registry` export.
+         * 
+         * Defaults to `false`.
+         * 
+         * Equivalent to Docker&#39;s `--push` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder push(Boolean push) {
+            return push(Output.of(push));
+        }
+
         /**
          * @param registries Registry credentials. Required if reading or exporting to private
          * repositories.
@@ -815,6 +1147,43 @@ public Builder secrets(Map<String,String> secrets) {
             return secrets(Output.of(secrets));
         }
 
+        /**
+         * @param ssh SSH agent socket or keys to expose to the build.
+         * 
+         * Equivalent to Docker&#39;s `--ssh` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder ssh(@Nullable Output<List<SSHArgs>> ssh) {
+            $.ssh = ssh;
+            return this;
+        }
+
+        /**
+         * @param ssh SSH agent socket or keys to expose to the build.
+         * 
+         * Equivalent to Docker&#39;s `--ssh` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder ssh(List<SSHArgs> ssh) {
+            return ssh(Output.of(ssh));
+        }
+
+        /**
+         * @param ssh SSH agent socket or keys to expose to the build.
+         * 
+         * Equivalent to Docker&#39;s `--ssh` flag.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder ssh(SSHArgs... ssh) {
+            return ssh(List.of(ssh));
+        }
+
         /**
          * @param tags Name and optionally a tag (format: `name:tag`).
          * 
@@ -905,6 +1274,7 @@ public Builder targets(String... targets) {
         }
 
         public ImageArgs build() {
+            $.network = Codegen.objectProp("network", NetworkMode.class).output().arg($.network).def(NetworkMode.Default_).getNullable();
             return $;
         }
     }
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/enums/NetworkMode.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/enums/NetworkMode.java
new file mode 100644
index 00000000..707c9e36
--- /dev/null
+++ b/sdk/java/src/main/java/com/pulumi/docker/buildx/enums/NetworkMode.java
@@ -0,0 +1,46 @@
+// *** WARNING: this file was generated by pulumi-java-gen. ***
+// *** Do not edit by hand unless you're certain you know what you are doing! ***
+
+package com.pulumi.docker.buildx.enums;
+
+import com.pulumi.core.annotations.EnumType;
+import java.lang.String;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+    @EnumType
+    public enum NetworkMode {
+        /**
+         * The default sandbox network mode.
+         * 
+         */
+        Default_("default"),
+        /**
+         * Host network mode.
+         * 
+         */
+        Host("host"),
+        /**
+         * Disable network access.
+         * 
+         */
+        None("none");
+
+        private final String value;
+
+        NetworkMode(String value) {
+            this.value = Objects.requireNonNull(value);
+        }
+
+        @EnumType.Converter
+        public String getValue() {
+            return this.value;
+        }
+
+        @Override
+        public String toString() {
+            return new StringJoiner(", ", "NetworkMode[", "]")
+                .add("value='" + this.value + "'")
+                .toString();
+        }
+    }
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ExportEntryArgs.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ExportEntryArgs.java
index adb18808..7501c12b 100644
--- a/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ExportEntryArgs.java
+++ b/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ExportEntryArgs.java
@@ -11,10 +11,8 @@
 import com.pulumi.docker.buildx.inputs.ExportOCIArgs;
 import com.pulumi.docker.buildx.inputs.ExportRegistryArgs;
 import com.pulumi.docker.buildx.inputs.ExportTarArgs;
-import com.pulumi.docker.buildx.inputs.ManifestArgs;
 import java.lang.Boolean;
 import java.lang.String;
-import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import javax.annotation.Nullable;
@@ -84,23 +82,6 @@ public Optional<Output<ExportLocalArgs>> local() {
         return Optional.ofNullable(this.local);
     }
 
-    /**
-     * An output property populated for exporters that pushed image
-     * manifest(s) to a registry.
-     * 
-     */
-    @Import(name="manifests")
-    private @Nullable Output<List<ManifestArgs>> manifests;
-
-    /**
-     * @return An output property populated for exporters that pushed image
-     * manifest(s) to a registry.
-     * 
-     */
-    public Optional<Output<List<ManifestArgs>>> manifests() {
-        return Optional.ofNullable(this.manifests);
-    }
-
     /**
      * Identical to the Docker exporter but uses OCI media types by default.
      * 
@@ -170,7 +151,6 @@ private ExportEntryArgs(ExportEntryArgs $) {
         this.docker = $.docker;
         this.image = $.image;
         this.local = $.local;
-        this.manifests = $.manifests;
         this.oci = $.oci;
         this.raw = $.raw;
         this.registry = $.registry;
@@ -279,40 +259,6 @@ public Builder local(ExportLocalArgs local) {
             return local(Output.of(local));
         }
 
-        /**
-         * @param manifests An output property populated for exporters that pushed image
-         * manifest(s) to a registry.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder manifests(@Nullable Output<List<ManifestArgs>> manifests) {
-            $.manifests = manifests;
-            return this;
-        }
-
-        /**
-         * @param manifests An output property populated for exporters that pushed image
-         * manifest(s) to a registry.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder manifests(List<ManifestArgs> manifests) {
-            return manifests(Output.of(manifests));
-        }
-
-        /**
-         * @param manifests An output property populated for exporters that pushed image
-         * manifest(s) to a registry.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder manifests(ManifestArgs... manifests) {
-            return manifests(List.of(manifests));
-        }
-
         /**
          * @param oci Identical to the Docker exporter but uses OCI media types by default.
          * 
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ManifestArgs.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ManifestArgs.java
deleted file mode 100644
index 374c19c7..00000000
--- a/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ManifestArgs.java
+++ /dev/null
@@ -1,207 +0,0 @@
-// *** WARNING: this file was generated by pulumi-java-gen. ***
-// *** Do not edit by hand unless you're certain you know what you are doing! ***
-
-package com.pulumi.docker.buildx.inputs;
-
-import com.pulumi.core.Output;
-import com.pulumi.core.annotations.Import;
-import com.pulumi.docker.buildx.inputs.ManifestPlatformArgs;
-import com.pulumi.exceptions.MissingRequiredPropertyException;
-import java.lang.Integer;
-import java.lang.String;
-import java.util.Objects;
-
-
-public final class ManifestArgs extends com.pulumi.resources.ResourceArgs {
-
-    public static final ManifestArgs Empty = new ManifestArgs();
-
-    /**
-     * The SHA256 digest of the manifest.
-     * 
-     */
-    @Import(name="digest", required=true)
-    private Output<String> digest;
-
-    /**
-     * @return The SHA256 digest of the manifest.
-     * 
-     */
-    public Output<String> digest() {
-        return this.digest;
-    }
-
-    /**
-     * The manifest&#39;s platform.
-     * 
-     */
-    @Import(name="platform", required=true)
-    private Output<ManifestPlatformArgs> platform;
-
-    /**
-     * @return The manifest&#39;s platform.
-     * 
-     */
-    public Output<ManifestPlatformArgs> platform() {
-        return this.platform;
-    }
-
-    /**
-     * The manifest&#39;s canonical ref.
-     * 
-     */
-    @Import(name="ref", required=true)
-    private Output<String> ref;
-
-    /**
-     * @return The manifest&#39;s canonical ref.
-     * 
-     */
-    public Output<String> ref() {
-        return this.ref;
-    }
-
-    /**
-     * The size of the manifest in bytes.
-     * 
-     */
-    @Import(name="size", required=true)
-    private Output<Integer> size;
-
-    /**
-     * @return The size of the manifest in bytes.
-     * 
-     */
-    public Output<Integer> size() {
-        return this.size;
-    }
-
-    private ManifestArgs() {}
-
-    private ManifestArgs(ManifestArgs $) {
-        this.digest = $.digest;
-        this.platform = $.platform;
-        this.ref = $.ref;
-        this.size = $.size;
-    }
-
-    public static Builder builder() {
-        return new Builder();
-    }
-    public static Builder builder(ManifestArgs defaults) {
-        return new Builder(defaults);
-    }
-
-    public static final class Builder {
-        private ManifestArgs $;
-
-        public Builder() {
-            $ = new ManifestArgs();
-        }
-
-        public Builder(ManifestArgs defaults) {
-            $ = new ManifestArgs(Objects.requireNonNull(defaults));
-        }
-
-        /**
-         * @param digest The SHA256 digest of the manifest.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder digest(Output<String> digest) {
-            $.digest = digest;
-            return this;
-        }
-
-        /**
-         * @param digest The SHA256 digest of the manifest.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder digest(String digest) {
-            return digest(Output.of(digest));
-        }
-
-        /**
-         * @param platform The manifest&#39;s platform.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder platform(Output<ManifestPlatformArgs> platform) {
-            $.platform = platform;
-            return this;
-        }
-
-        /**
-         * @param platform The manifest&#39;s platform.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder platform(ManifestPlatformArgs platform) {
-            return platform(Output.of(platform));
-        }
-
-        /**
-         * @param ref The manifest&#39;s canonical ref.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder ref(Output<String> ref) {
-            $.ref = ref;
-            return this;
-        }
-
-        /**
-         * @param ref The manifest&#39;s canonical ref.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder ref(String ref) {
-            return ref(Output.of(ref));
-        }
-
-        /**
-         * @param size The size of the manifest in bytes.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder size(Output<Integer> size) {
-            $.size = size;
-            return this;
-        }
-
-        /**
-         * @param size The size of the manifest in bytes.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder size(Integer size) {
-            return size(Output.of(size));
-        }
-
-        public ManifestArgs build() {
-            if ($.digest == null) {
-                throw new MissingRequiredPropertyException("ManifestArgs", "digest");
-            }
-            if ($.platform == null) {
-                throw new MissingRequiredPropertyException("ManifestArgs", "platform");
-            }
-            if ($.ref == null) {
-                throw new MissingRequiredPropertyException("ManifestArgs", "ref");
-            }
-            if ($.size == null) {
-                throw new MissingRequiredPropertyException("ManifestArgs", "size");
-            }
-            return $;
-        }
-    }
-
-}
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ManifestPlatformArgs.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ManifestPlatformArgs.java
deleted file mode 100644
index 6b8deb81..00000000
--- a/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/ManifestPlatformArgs.java
+++ /dev/null
@@ -1,125 +0,0 @@
-// *** WARNING: this file was generated by pulumi-java-gen. ***
-// *** Do not edit by hand unless you're certain you know what you are doing! ***
-
-package com.pulumi.docker.buildx.inputs;
-
-import com.pulumi.core.Output;
-import com.pulumi.core.annotations.Import;
-import com.pulumi.exceptions.MissingRequiredPropertyException;
-import java.lang.String;
-import java.util.Objects;
-
-
-public final class ManifestPlatformArgs extends com.pulumi.resources.ResourceArgs {
-
-    public static final ManifestPlatformArgs Empty = new ManifestPlatformArgs();
-
-    /**
-     * The manifest&#39;s architecture.
-     * 
-     */
-    @Import(name="architecture", required=true)
-    private Output<String> architecture;
-
-    /**
-     * @return The manifest&#39;s architecture.
-     * 
-     */
-    public Output<String> architecture() {
-        return this.architecture;
-    }
-
-    /**
-     * The manifest&#39;s operating systen.
-     * 
-     */
-    @Import(name="os", required=true)
-    private Output<String> os;
-
-    /**
-     * @return The manifest&#39;s operating systen.
-     * 
-     */
-    public Output<String> os() {
-        return this.os;
-    }
-
-    private ManifestPlatformArgs() {}
-
-    private ManifestPlatformArgs(ManifestPlatformArgs $) {
-        this.architecture = $.architecture;
-        this.os = $.os;
-    }
-
-    public static Builder builder() {
-        return new Builder();
-    }
-    public static Builder builder(ManifestPlatformArgs defaults) {
-        return new Builder(defaults);
-    }
-
-    public static final class Builder {
-        private ManifestPlatformArgs $;
-
-        public Builder() {
-            $ = new ManifestPlatformArgs();
-        }
-
-        public Builder(ManifestPlatformArgs defaults) {
-            $ = new ManifestPlatformArgs(Objects.requireNonNull(defaults));
-        }
-
-        /**
-         * @param architecture The manifest&#39;s architecture.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder architecture(Output<String> architecture) {
-            $.architecture = architecture;
-            return this;
-        }
-
-        /**
-         * @param architecture The manifest&#39;s architecture.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder architecture(String architecture) {
-            return architecture(Output.of(architecture));
-        }
-
-        /**
-         * @param os The manifest&#39;s operating systen.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder os(Output<String> os) {
-            $.os = os;
-            return this;
-        }
-
-        /**
-         * @param os The manifest&#39;s operating systen.
-         * 
-         * @return builder
-         * 
-         */
-        public Builder os(String os) {
-            return os(Output.of(os));
-        }
-
-        public ManifestPlatformArgs build() {
-            if ($.architecture == null) {
-                throw new MissingRequiredPropertyException("ManifestPlatformArgs", "architecture");
-            }
-            if ($.os == null) {
-                throw new MissingRequiredPropertyException("ManifestPlatformArgs", "os");
-            }
-            return $;
-        }
-    }
-
-}
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/SSHArgs.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/SSHArgs.java
new file mode 100644
index 00000000..33e78b8a
--- /dev/null
+++ b/sdk/java/src/main/java/com/pulumi/docker/buildx/inputs/SSHArgs.java
@@ -0,0 +1,182 @@
+// *** WARNING: this file was generated by pulumi-java-gen. ***
+// *** Do not edit by hand unless you're certain you know what you are doing! ***
+
+package com.pulumi.docker.buildx.inputs;
+
+import com.pulumi.core.Output;
+import com.pulumi.core.annotations.Import;
+import com.pulumi.exceptions.MissingRequiredPropertyException;
+import java.lang.String;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import javax.annotation.Nullable;
+
+
+public final class SSHArgs extends com.pulumi.resources.ResourceArgs {
+
+    public static final SSHArgs Empty = new SSHArgs();
+
+    /**
+     * Useful for distinguishing different servers that are part of the same
+     * build.
+     * 
+     * A value of `default` is appropriate if only dealing with a single host.
+     * 
+     */
+    @Import(name="id", required=true)
+    private Output<String> id;
+
+    /**
+     * @return Useful for distinguishing different servers that are part of the same
+     * build.
+     * 
+     * A value of `default` is appropriate if only dealing with a single host.
+     * 
+     */
+    public Output<String> id() {
+        return this.id;
+    }
+
+    /**
+     * SSH agent socket or private keys to expose to the build under the given
+     * identifier.
+     * 
+     * Defaults to `[$SSH_AUTH_SOCK]`.
+     * 
+     * Note that your keys are **not** automatically added when using an
+     * agent. Run `ssh-add -l` locally to confirm which public keys are
+     * visible to the agent; these will be exposed to your build.
+     * 
+     */
+    @Import(name="paths")
+    private @Nullable Output<List<String>> paths;
+
+    /**
+     * @return SSH agent socket or private keys to expose to the build under the given
+     * identifier.
+     * 
+     * Defaults to `[$SSH_AUTH_SOCK]`.
+     * 
+     * Note that your keys are **not** automatically added when using an
+     * agent. Run `ssh-add -l` locally to confirm which public keys are
+     * visible to the agent; these will be exposed to your build.
+     * 
+     */
+    public Optional<Output<List<String>>> paths() {
+        return Optional.ofNullable(this.paths);
+    }
+
+    private SSHArgs() {}
+
+    private SSHArgs(SSHArgs $) {
+        this.id = $.id;
+        this.paths = $.paths;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+    public static Builder builder(SSHArgs defaults) {
+        return new Builder(defaults);
+    }
+
+    public static final class Builder {
+        private SSHArgs $;
+
+        public Builder() {
+            $ = new SSHArgs();
+        }
+
+        public Builder(SSHArgs defaults) {
+            $ = new SSHArgs(Objects.requireNonNull(defaults));
+        }
+
+        /**
+         * @param id Useful for distinguishing different servers that are part of the same
+         * build.
+         * 
+         * A value of `default` is appropriate if only dealing with a single host.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder id(Output<String> id) {
+            $.id = id;
+            return this;
+        }
+
+        /**
+         * @param id Useful for distinguishing different servers that are part of the same
+         * build.
+         * 
+         * A value of `default` is appropriate if only dealing with a single host.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder id(String id) {
+            return id(Output.of(id));
+        }
+
+        /**
+         * @param paths SSH agent socket or private keys to expose to the build under the given
+         * identifier.
+         * 
+         * Defaults to `[$SSH_AUTH_SOCK]`.
+         * 
+         * Note that your keys are **not** automatically added when using an
+         * agent. Run `ssh-add -l` locally to confirm which public keys are
+         * visible to the agent; these will be exposed to your build.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder paths(@Nullable Output<List<String>> paths) {
+            $.paths = paths;
+            return this;
+        }
+
+        /**
+         * @param paths SSH agent socket or private keys to expose to the build under the given
+         * identifier.
+         * 
+         * Defaults to `[$SSH_AUTH_SOCK]`.
+         * 
+         * Note that your keys are **not** automatically added when using an
+         * agent. Run `ssh-add -l` locally to confirm which public keys are
+         * visible to the agent; these will be exposed to your build.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder paths(List<String> paths) {
+            return paths(Output.of(paths));
+        }
+
+        /**
+         * @param paths SSH agent socket or private keys to expose to the build under the given
+         * identifier.
+         * 
+         * Defaults to `[$SSH_AUTH_SOCK]`.
+         * 
+         * Note that your keys are **not** automatically added when using an
+         * agent. Run `ssh-add -l` locally to confirm which public keys are
+         * visible to the agent; these will be exposed to your build.
+         * 
+         * @return builder
+         * 
+         */
+        public Builder paths(String... paths) {
+            return paths(List.of(paths));
+        }
+
+        public SSHArgs build() {
+            if ($.id == null) {
+                throw new MissingRequiredPropertyException("SSHArgs", "id");
+            }
+            return $;
+        }
+    }
+
+}
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/ExportEntry.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/ExportEntry.java
index a7fbdf62..a17f1481 100644
--- a/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/ExportEntry.java
+++ b/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/ExportEntry.java
@@ -10,10 +10,8 @@
 import com.pulumi.docker.buildx.outputs.ExportOCI;
 import com.pulumi.docker.buildx.outputs.ExportRegistry;
 import com.pulumi.docker.buildx.outputs.ExportTar;
-import com.pulumi.docker.buildx.outputs.Manifest;
 import java.lang.Boolean;
 import java.lang.String;
-import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import javax.annotation.Nullable;
@@ -40,12 +38,6 @@ public final class ExportEntry {
      * 
      */
     private @Nullable ExportLocal local;
-    /**
-     * @return An output property populated for exporters that pushed image
-     * manifest(s) to a registry.
-     * 
-     */
-    private @Nullable List<Manifest> manifests;
     /**
      * @return Identical to the Docker exporter but uses OCI media types by default.
      * 
@@ -97,14 +89,6 @@ public Optional<ExportImage> image() {
     public Optional<ExportLocal> local() {
         return Optional.ofNullable(this.local);
     }
-    /**
-     * @return An output property populated for exporters that pushed image
-     * manifest(s) to a registry.
-     * 
-     */
-    public List<Manifest> manifests() {
-        return this.manifests == null ? List.of() : this.manifests;
-    }
     /**
      * @return Identical to the Docker exporter but uses OCI media types by default.
      * 
@@ -148,7 +132,6 @@ public static final class Builder {
         private @Nullable ExportDocker docker;
         private @Nullable ExportImage image;
         private @Nullable ExportLocal local;
-        private @Nullable List<Manifest> manifests;
         private @Nullable ExportOCI oci;
         private @Nullable String raw;
         private @Nullable ExportRegistry registry;
@@ -160,7 +143,6 @@ public Builder(ExportEntry defaults) {
     	      this.docker = defaults.docker;
     	      this.image = defaults.image;
     	      this.local = defaults.local;
-    	      this.manifests = defaults.manifests;
     	      this.oci = defaults.oci;
     	      this.raw = defaults.raw;
     	      this.registry = defaults.registry;
@@ -192,15 +174,6 @@ public Builder local(@Nullable ExportLocal local) {
             return this;
         }
         @CustomType.Setter
-        public Builder manifests(@Nullable List<Manifest> manifests) {
-
-            this.manifests = manifests;
-            return this;
-        }
-        public Builder manifests(Manifest... manifests) {
-            return manifests(List.of(manifests));
-        }
-        @CustomType.Setter
         public Builder oci(@Nullable ExportOCI oci) {
 
             this.oci = oci;
@@ -230,7 +203,6 @@ public ExportEntry build() {
             _resultValue.docker = docker;
             _resultValue.image = image;
             _resultValue.local = local;
-            _resultValue.manifests = manifests;
             _resultValue.oci = oci;
             _resultValue.raw = raw;
             _resultValue.registry = registry;
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/Manifest.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/Manifest.java
deleted file mode 100644
index 7635db5b..00000000
--- a/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/Manifest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-// *** WARNING: this file was generated by pulumi-java-gen. ***
-// *** Do not edit by hand unless you're certain you know what you are doing! ***
-
-package com.pulumi.docker.buildx.outputs;
-
-import com.pulumi.core.annotations.CustomType;
-import com.pulumi.docker.buildx.outputs.ManifestPlatform;
-import com.pulumi.exceptions.MissingRequiredPropertyException;
-import java.lang.Integer;
-import java.lang.String;
-import java.util.Objects;
-
-@CustomType
-public final class Manifest {
-    /**
-     * @return The SHA256 digest of the manifest.
-     * 
-     */
-    private String digest;
-    /**
-     * @return The manifest&#39;s platform.
-     * 
-     */
-    private ManifestPlatform platform;
-    /**
-     * @return The manifest&#39;s canonical ref.
-     * 
-     */
-    private String ref;
-    /**
-     * @return The size of the manifest in bytes.
-     * 
-     */
-    private Integer size;
-
-    private Manifest() {}
-    /**
-     * @return The SHA256 digest of the manifest.
-     * 
-     */
-    public String digest() {
-        return this.digest;
-    }
-    /**
-     * @return The manifest&#39;s platform.
-     * 
-     */
-    public ManifestPlatform platform() {
-        return this.platform;
-    }
-    /**
-     * @return The manifest&#39;s canonical ref.
-     * 
-     */
-    public String ref() {
-        return this.ref;
-    }
-    /**
-     * @return The size of the manifest in bytes.
-     * 
-     */
-    public Integer size() {
-        return this.size;
-    }
-
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    public static Builder builder(Manifest defaults) {
-        return new Builder(defaults);
-    }
-    @CustomType.Builder
-    public static final class Builder {
-        private String digest;
-        private ManifestPlatform platform;
-        private String ref;
-        private Integer size;
-        public Builder() {}
-        public Builder(Manifest defaults) {
-    	      Objects.requireNonNull(defaults);
-    	      this.digest = defaults.digest;
-    	      this.platform = defaults.platform;
-    	      this.ref = defaults.ref;
-    	      this.size = defaults.size;
-        }
-
-        @CustomType.Setter
-        public Builder digest(String digest) {
-            if (digest == null) {
-              throw new MissingRequiredPropertyException("Manifest", "digest");
-            }
-            this.digest = digest;
-            return this;
-        }
-        @CustomType.Setter
-        public Builder platform(ManifestPlatform platform) {
-            if (platform == null) {
-              throw new MissingRequiredPropertyException("Manifest", "platform");
-            }
-            this.platform = platform;
-            return this;
-        }
-        @CustomType.Setter
-        public Builder ref(String ref) {
-            if (ref == null) {
-              throw new MissingRequiredPropertyException("Manifest", "ref");
-            }
-            this.ref = ref;
-            return this;
-        }
-        @CustomType.Setter
-        public Builder size(Integer size) {
-            if (size == null) {
-              throw new MissingRequiredPropertyException("Manifest", "size");
-            }
-            this.size = size;
-            return this;
-        }
-        public Manifest build() {
-            final var _resultValue = new Manifest();
-            _resultValue.digest = digest;
-            _resultValue.platform = platform;
-            _resultValue.ref = ref;
-            _resultValue.size = size;
-            return _resultValue;
-        }
-    }
-}
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/ManifestPlatform.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/ManifestPlatform.java
deleted file mode 100644
index f96447e3..00000000
--- a/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/ManifestPlatform.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// *** WARNING: this file was generated by pulumi-java-gen. ***
-// *** Do not edit by hand unless you're certain you know what you are doing! ***
-
-package com.pulumi.docker.buildx.outputs;
-
-import com.pulumi.core.annotations.CustomType;
-import com.pulumi.exceptions.MissingRequiredPropertyException;
-import java.lang.String;
-import java.util.Objects;
-
-@CustomType
-public final class ManifestPlatform {
-    /**
-     * @return The manifest&#39;s architecture.
-     * 
-     */
-    private String architecture;
-    /**
-     * @return The manifest&#39;s operating systen.
-     * 
-     */
-    private String os;
-
-    private ManifestPlatform() {}
-    /**
-     * @return The manifest&#39;s architecture.
-     * 
-     */
-    public String architecture() {
-        return this.architecture;
-    }
-    /**
-     * @return The manifest&#39;s operating systen.
-     * 
-     */
-    public String os() {
-        return this.os;
-    }
-
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    public static Builder builder(ManifestPlatform defaults) {
-        return new Builder(defaults);
-    }
-    @CustomType.Builder
-    public static final class Builder {
-        private String architecture;
-        private String os;
-        public Builder() {}
-        public Builder(ManifestPlatform defaults) {
-    	      Objects.requireNonNull(defaults);
-    	      this.architecture = defaults.architecture;
-    	      this.os = defaults.os;
-        }
-
-        @CustomType.Setter
-        public Builder architecture(String architecture) {
-            if (architecture == null) {
-              throw new MissingRequiredPropertyException("ManifestPlatform", "architecture");
-            }
-            this.architecture = architecture;
-            return this;
-        }
-        @CustomType.Setter
-        public Builder os(String os) {
-            if (os == null) {
-              throw new MissingRequiredPropertyException("ManifestPlatform", "os");
-            }
-            this.os = os;
-            return this;
-        }
-        public ManifestPlatform build() {
-            final var _resultValue = new ManifestPlatform();
-            _resultValue.architecture = architecture;
-            _resultValue.os = os;
-            return _resultValue;
-        }
-    }
-}
diff --git a/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/SSH.java b/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/SSH.java
new file mode 100644
index 00000000..50289939
--- /dev/null
+++ b/sdk/java/src/main/java/com/pulumi/docker/buildx/outputs/SSH.java
@@ -0,0 +1,104 @@
+// *** WARNING: this file was generated by pulumi-java-gen. ***
+// *** Do not edit by hand unless you're certain you know what you are doing! ***
+
+package com.pulumi.docker.buildx.outputs;
+
+import com.pulumi.core.annotations.CustomType;
+import com.pulumi.exceptions.MissingRequiredPropertyException;
+import java.lang.String;
+import java.util.List;
+import java.util.Objects;
+import javax.annotation.Nullable;
+
+@CustomType
+public final class SSH {
+    /**
+     * @return Useful for distinguishing different servers that are part of the same
+     * build.
+     * 
+     * A value of `default` is appropriate if only dealing with a single host.
+     * 
+     */
+    private String id;
+    /**
+     * @return SSH agent socket or private keys to expose to the build under the given
+     * identifier.
+     * 
+     * Defaults to `[$SSH_AUTH_SOCK]`.
+     * 
+     * Note that your keys are **not** automatically added when using an
+     * agent. Run `ssh-add -l` locally to confirm which public keys are
+     * visible to the agent; these will be exposed to your build.
+     * 
+     */
+    private @Nullable List<String> paths;
+
+    private SSH() {}
+    /**
+     * @return Useful for distinguishing different servers that are part of the same
+     * build.
+     * 
+     * A value of `default` is appropriate if only dealing with a single host.
+     * 
+     */
+    public String id() {
+        return this.id;
+    }
+    /**
+     * @return SSH agent socket or private keys to expose to the build under the given
+     * identifier.
+     * 
+     * Defaults to `[$SSH_AUTH_SOCK]`.
+     * 
+     * Note that your keys are **not** automatically added when using an
+     * agent. Run `ssh-add -l` locally to confirm which public keys are
+     * visible to the agent; these will be exposed to your build.
+     * 
+     */
+    public List<String> paths() {
+        return this.paths == null ? List.of() : this.paths;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static Builder builder(SSH defaults) {
+        return new Builder(defaults);
+    }
+    @CustomType.Builder
+    public static final class Builder {
+        private String id;
+        private @Nullable List<String> paths;
+        public Builder() {}
+        public Builder(SSH defaults) {
+    	      Objects.requireNonNull(defaults);
+    	      this.id = defaults.id;
+    	      this.paths = defaults.paths;
+        }
+
+        @CustomType.Setter
+        public Builder id(String id) {
+            if (id == null) {
+              throw new MissingRequiredPropertyException("SSH", "id");
+            }
+            this.id = id;
+            return this;
+        }
+        @CustomType.Setter
+        public Builder paths(@Nullable List<String> paths) {
+
+            this.paths = paths;
+            return this;
+        }
+        public Builder paths(String... paths) {
+            return paths(List.of(paths));
+        }
+        public SSH build() {
+            final var _resultValue = new SSH();
+            _resultValue.id = id;
+            _resultValue.paths = paths;
+            return _resultValue;
+        }
+    }
+}
diff --git a/sdk/nodejs/buildx/image.ts b/sdk/nodejs/buildx/image.ts
index c3a92a55..62ac37c6 100644
--- a/sdk/nodejs/buildx/image.ts
+++ b/sdk/nodejs/buildx/image.ts
@@ -470,6 +470,12 @@ export class Image extends pulumi.CustomResource {
         return obj['__pulumiType'] === Image.__pulumiType;
     }
 
+    /**
+     * Custom `host:ip` mappings to use during the build.
+     *
+     * Equivalent to Docker's `--add-host` flag.
+     */
+    public readonly addHosts!: pulumi.Output<string[] | undefined>;
     /**
      * `ARG` names and values to set during the build.
      *
@@ -483,8 +489,20 @@ export class Image extends pulumi.CustomResource {
      */
     public readonly buildArgs!: pulumi.Output<{[key: string]: string} | undefined>;
     /**
-     * When `true`, attempt to build the image during previews. The image will
-     * not be pushed to registries, however caches will still be populated.
+     * By default, preview behavior depends on the execution environment. If
+     * Pulumi detects the operation is running on a CI system (GitHub Actions,
+     * Travis CI, Azure Pipelines, etc.) then it will build images during
+     * previews as a safeguard. Otherwise, if not running on CI, previews will
+     * not build images.
+     *
+     * Setting this to `false` forces previews to never perform builds, and
+     * setting it to `true` will always build the image during previews.
+     *
+     * Images built during previews are never exported to registries, however
+     * cache manifests are still exported.
+     *
+     * On-disk Dockerfiles are always validated for syntactic correctness
+     * regardless of this setting.
      */
     public readonly buildOnPreview!: pulumi.Output<boolean | undefined>;
     /**
@@ -514,11 +532,15 @@ export class Image extends pulumi.CustomResource {
      *
      * Pulumi uses this to determine if an image _may_ need to be re-built.
      */
-    public /*out*/ readonly contextHash!: pulumi.Output<string | undefined>;
+    public /*out*/ readonly contextHash!: pulumi.Output<string>;
     /**
-     * A mapping of platform type to refs which were pushed to registries.
+     * A mapping of target names to the SHA256 digest of their pushed manifest.
+     *
+     * If no target was specified 'default' is used as the target name.
+     *
+     * Pushed manifests can be referenced as `<tag>@<digest>`.
      */
-    public /*out*/ readonly digests!: pulumi.Output<{[key: string]: string[]} | undefined>;
+    public /*out*/ readonly digests!: pulumi.Output<{[key: string]: string}>;
     /**
      * Dockerfile settings.
      *
@@ -540,6 +562,28 @@ export class Image extends pulumi.CustomResource {
      * Equivalent to Docker's `--label` flag.
      */
     public readonly labels!: pulumi.Output<{[key: string]: string} | undefined>;
+    /**
+     * When `true` the build will automatically include a `docker` export.
+     *
+     * Defaults to `false`.
+     *
+     * Equivalent to Docker's `--load` flag.
+     */
+    public readonly load!: pulumi.Output<boolean | undefined>;
+    /**
+     * Set the network mode for `RUN` instructions. Defaults to `default`.
+     *
+     * For custom networks, configure your builder with `--driver-opt network=...`.
+     *
+     * Equivalent to Docker's `--network` flag.
+     */
+    public readonly network!: pulumi.Output<enums.buildx.NetworkMode | undefined>;
+    /**
+     * Do not import cache manifests when building the image.
+     *
+     * Equivalent to Docker's `--no-cache` flag.
+     */
+    public readonly noCache!: pulumi.Output<boolean | undefined>;
     /**
      * Set target platform(s) for the build. Defaults to the host's platform.
      *
@@ -552,6 +596,26 @@ export class Image extends pulumi.CustomResource {
      * Equivalent to Docker's `--pull` flag.
      */
     public readonly pull!: pulumi.Output<boolean | undefined>;
+    /**
+     * When `true` the build will automatically include a `registry` export.
+     *
+     * Defaults to `false`.
+     *
+     * Equivalent to Docker's `--push` flag.
+     */
+    public readonly push!: pulumi.Output<boolean | undefined>;
+    /**
+     * If the image was pushed to any registries then this will contain a
+     * single fully-qualified tag including the build's digest.
+     *
+     * This is only for convenience and may not be appropriate for situations
+     * where multiple tags or registries are involved. In those cases this
+     * output is not guaranteed to be stable.
+     *
+     * For more control over tags consumed by downstream resources you should
+     * use the `Digests` output.
+     */
+    public /*out*/ readonly ref!: pulumi.Output<string>;
     /**
      * Registry credentials. Required if reading or exporting to private
      * repositories.
@@ -574,6 +638,12 @@ export class Image extends pulumi.CustomResource {
      * Similar to Docker's `--secret` flag.
      */
     public readonly secrets!: pulumi.Output<{[key: string]: string} | undefined>;
+    /**
+     * SSH agent socket or keys to expose to the build.
+     *
+     * Equivalent to Docker's `--ssh` flag.
+     */
+    public readonly ssh!: pulumi.Output<outputs.buildx.SSH[] | undefined>;
     /**
      * Name and optionally a tag (format: `name:tag`).
      *
@@ -603,6 +673,7 @@ export class Image extends pulumi.CustomResource {
         let resourceInputs: pulumi.Inputs = {};
         opts = opts || {};
         if (!opts.id) {
+            resourceInputs["addHosts"] = args ? args.addHosts : undefined;
             resourceInputs["buildArgs"] = args ? args.buildArgs : undefined;
             resourceInputs["buildOnPreview"] = args ? args.buildOnPreview : undefined;
             resourceInputs["builder"] = args ? args.builder : undefined;
@@ -612,15 +683,22 @@ export class Image extends pulumi.CustomResource {
             resourceInputs["dockerfile"] = args ? args.dockerfile : undefined;
             resourceInputs["exports"] = args ? args.exports : undefined;
             resourceInputs["labels"] = args ? args.labels : undefined;
+            resourceInputs["load"] = args ? args.load : undefined;
+            resourceInputs["network"] = (args ? args.network : undefined) ?? "default";
+            resourceInputs["noCache"] = args ? args.noCache : undefined;
             resourceInputs["platforms"] = args ? args.platforms : undefined;
             resourceInputs["pull"] = args ? args.pull : undefined;
+            resourceInputs["push"] = args ? args.push : undefined;
             resourceInputs["registries"] = args ? args.registries : undefined;
-            resourceInputs["secrets"] = args?.secrets ? pulumi.secret(args.secrets) : undefined;
+            resourceInputs["secrets"] = args ? args.secrets : undefined;
+            resourceInputs["ssh"] = args ? args.ssh : undefined;
             resourceInputs["tags"] = args ? args.tags : undefined;
             resourceInputs["targets"] = args ? args.targets : undefined;
             resourceInputs["contextHash"] = undefined /*out*/;
             resourceInputs["digests"] = undefined /*out*/;
+            resourceInputs["ref"] = undefined /*out*/;
         } else {
+            resourceInputs["addHosts"] = undefined /*out*/;
             resourceInputs["buildArgs"] = undefined /*out*/;
             resourceInputs["buildOnPreview"] = undefined /*out*/;
             resourceInputs["builder"] = undefined /*out*/;
@@ -632,16 +710,20 @@ export class Image extends pulumi.CustomResource {
             resourceInputs["dockerfile"] = undefined /*out*/;
             resourceInputs["exports"] = undefined /*out*/;
             resourceInputs["labels"] = undefined /*out*/;
+            resourceInputs["load"] = undefined /*out*/;
+            resourceInputs["network"] = undefined /*out*/;
+            resourceInputs["noCache"] = undefined /*out*/;
             resourceInputs["platforms"] = undefined /*out*/;
             resourceInputs["pull"] = undefined /*out*/;
+            resourceInputs["push"] = undefined /*out*/;
+            resourceInputs["ref"] = undefined /*out*/;
             resourceInputs["registries"] = undefined /*out*/;
             resourceInputs["secrets"] = undefined /*out*/;
+            resourceInputs["ssh"] = undefined /*out*/;
             resourceInputs["tags"] = undefined /*out*/;
             resourceInputs["targets"] = undefined /*out*/;
         }
         opts = pulumi.mergeOptions(utilities.resourceOptsDefaults(), opts);
-        const secretOpts = { additionalSecretOutputs: ["secrets"] };
-        opts = pulumi.mergeOptions(opts, secretOpts);
         super(Image.__pulumiType, name, resourceInputs, opts);
     }
 }
@@ -650,6 +732,12 @@ export class Image extends pulumi.CustomResource {
  * The set of arguments for constructing a Image resource.
  */
 export interface ImageArgs {
+    /**
+     * Custom `host:ip` mappings to use during the build.
+     *
+     * Equivalent to Docker's `--add-host` flag.
+     */
+    addHosts?: pulumi.Input<pulumi.Input<string>[]>;
     /**
      * `ARG` names and values to set during the build.
      *
@@ -663,8 +751,20 @@ export interface ImageArgs {
      */
     buildArgs?: pulumi.Input<{[key: string]: pulumi.Input<string>}>;
     /**
-     * When `true`, attempt to build the image during previews. The image will
-     * not be pushed to registries, however caches will still be populated.
+     * By default, preview behavior depends on the execution environment. If
+     * Pulumi detects the operation is running on a CI system (GitHub Actions,
+     * Travis CI, Azure Pipelines, etc.) then it will build images during
+     * previews as a safeguard. Otherwise, if not running on CI, previews will
+     * not build images.
+     *
+     * Setting this to `false` forces previews to never perform builds, and
+     * setting it to `true` will always build the image during previews.
+     *
+     * Images built during previews are never exported to registries, however
+     * cache manifests are still exported.
+     *
+     * On-disk Dockerfiles are always validated for syntactic correctness
+     * regardless of this setting.
      */
     buildOnPreview?: pulumi.Input<boolean>;
     /**
@@ -710,6 +810,28 @@ export interface ImageArgs {
      * Equivalent to Docker's `--label` flag.
      */
     labels?: pulumi.Input<{[key: string]: pulumi.Input<string>}>;
+    /**
+     * When `true` the build will automatically include a `docker` export.
+     *
+     * Defaults to `false`.
+     *
+     * Equivalent to Docker's `--load` flag.
+     */
+    load?: pulumi.Input<boolean>;
+    /**
+     * Set the network mode for `RUN` instructions. Defaults to `default`.
+     *
+     * For custom networks, configure your builder with `--driver-opt network=...`.
+     *
+     * Equivalent to Docker's `--network` flag.
+     */
+    network?: pulumi.Input<enums.buildx.NetworkMode>;
+    /**
+     * Do not import cache manifests when building the image.
+     *
+     * Equivalent to Docker's `--no-cache` flag.
+     */
+    noCache?: pulumi.Input<boolean>;
     /**
      * Set target platform(s) for the build. Defaults to the host's platform.
      *
@@ -722,6 +844,14 @@ export interface ImageArgs {
      * Equivalent to Docker's `--pull` flag.
      */
     pull?: pulumi.Input<boolean>;
+    /**
+     * When `true` the build will automatically include a `registry` export.
+     *
+     * Defaults to `false`.
+     *
+     * Equivalent to Docker's `--push` flag.
+     */
+    push?: pulumi.Input<boolean>;
     /**
      * Registry credentials. Required if reading or exporting to private
      * repositories.
@@ -744,6 +874,12 @@ export interface ImageArgs {
      * Similar to Docker's `--secret` flag.
      */
     secrets?: pulumi.Input<{[key: string]: pulumi.Input<string>}>;
+    /**
+     * SSH agent socket or keys to expose to the build.
+     *
+     * Equivalent to Docker's `--ssh` flag.
+     */
+    ssh?: pulumi.Input<pulumi.Input<inputs.buildx.SSH>[]>;
     /**
      * Name and optionally a tag (format: `name:tag`).
      *
diff --git a/sdk/nodejs/types/enums/buildx/index.ts b/sdk/nodejs/types/enums/buildx/index.ts
index c5215764..00c5847d 100644
--- a/sdk/nodejs/types/enums/buildx/index.ts
+++ b/sdk/nodejs/types/enums/buildx/index.ts
@@ -32,6 +32,23 @@ export const CompressionType = {
 
 export type CompressionType = (typeof CompressionType)[keyof typeof CompressionType];
 
+export const NetworkMode = {
+    /**
+     * The default sandbox network mode.
+     */
+    Default: "default",
+    /**
+     * Host network mode.
+     */
+    Host: "host",
+    /**
+     * Disable network access.
+     */
+    None: "none",
+} as const;
+
+export type NetworkMode = (typeof NetworkMode)[keyof typeof NetworkMode];
+
 export const Platform = {
     Darwin_386: "darwin/386",
     Darwin_amd64: "darwin/amd64",
diff --git a/sdk/nodejs/types/input.ts b/sdk/nodejs/types/input.ts
index 2ffc68af..58ba745b 100644
--- a/sdk/nodejs/types/input.ts
+++ b/sdk/nodejs/types/input.ts
@@ -1877,11 +1877,6 @@ export namespace buildx {
          * Export to a local directory as files and directories.
          */
         local?: pulumi.Input<inputs.buildx.ExportLocal>;
-        /**
-         * An output property populated for exporters that pushed image
-         * manifest(s) to a registry.
-         */
-        manifests?: pulumi.Input<pulumi.Input<inputs.buildx.Manifest>[]>;
         /**
          * Identical to the Docker exporter but uses OCI media types by default.
          */
@@ -2126,36 +2121,6 @@ export namespace buildx {
         dest: pulumi.Input<string>;
     }
 
-    export interface Manifest {
-        /**
-         * The SHA256 digest of the manifest.
-         */
-        digest: pulumi.Input<string>;
-        /**
-         * The manifest's platform.
-         */
-        platform: pulumi.Input<inputs.buildx.ManifestPlatform>;
-        /**
-         * The manifest's canonical ref.
-         */
-        ref: pulumi.Input<string>;
-        /**
-         * The size of the manifest in bytes.
-         */
-        size: pulumi.Input<number>;
-    }
-
-    export interface ManifestPlatform {
-        /**
-         * The manifest's architecture.
-         */
-        architecture: pulumi.Input<string>;
-        /**
-         * The manifest's operating systen.
-         */
-        os: pulumi.Input<string>;
-    }
-
     export interface RegistryAuth {
         /**
          * The registry's address (e.g. "docker.io").
@@ -2170,6 +2135,27 @@ export namespace buildx {
          */
         username?: pulumi.Input<string>;
     }
+
+    export interface SSH {
+        /**
+         * Useful for distinguishing different servers that are part of the same
+         * build.
+         *
+         * A value of `default` is appropriate if only dealing with a single host.
+         */
+        id: pulumi.Input<string>;
+        /**
+         * SSH agent socket or private keys to expose to the build under the given
+         * identifier.
+         *
+         * Defaults to `[$SSH_AUTH_SOCK]`.
+         *
+         * Note that your keys are **not** automatically added when using an
+         * agent. Run `ssh-add -l` locally to confirm which public keys are
+         * visible to the agent; these will be exposed to your build.
+         */
+        paths?: pulumi.Input<pulumi.Input<string>[]>;
+    }
 }
 
 export namespace config {
diff --git a/sdk/nodejs/types/output.ts b/sdk/nodejs/types/output.ts
index 3d322d6d..d3f8f652 100644
--- a/sdk/nodejs/types/output.ts
+++ b/sdk/nodejs/types/output.ts
@@ -1803,11 +1803,6 @@ export namespace buildx {
          * Export to a local directory as files and directories.
          */
         local?: outputs.buildx.ExportLocal;
-        /**
-         * An output property populated for exporters that pushed image
-         * manifest(s) to a registry.
-         */
-        manifests?: outputs.buildx.Manifest[];
         /**
          * Identical to the Docker exporter but uses OCI media types by default.
          */
@@ -2052,36 +2047,6 @@ export namespace buildx {
         dest: string;
     }
 
-    export interface Manifest {
-        /**
-         * The SHA256 digest of the manifest.
-         */
-        digest: string;
-        /**
-         * The manifest's platform.
-         */
-        platform: outputs.buildx.ManifestPlatform;
-        /**
-         * The manifest's canonical ref.
-         */
-        ref: string;
-        /**
-         * The size of the manifest in bytes.
-         */
-        size: number;
-    }
-
-    export interface ManifestPlatform {
-        /**
-         * The manifest's architecture.
-         */
-        architecture: string;
-        /**
-         * The manifest's operating systen.
-         */
-        os: string;
-    }
-
     export interface RegistryAuth {
         /**
          * The registry's address (e.g. "docker.io").
@@ -2097,6 +2062,27 @@ export namespace buildx {
         username?: string;
     }
 
+    export interface SSH {
+        /**
+         * Useful for distinguishing different servers that are part of the same
+         * build.
+         *
+         * A value of `default` is appropriate if only dealing with a single host.
+         */
+        id: string;
+        /**
+         * SSH agent socket or private keys to expose to the build under the given
+         * identifier.
+         *
+         * Defaults to `[$SSH_AUTH_SOCK]`.
+         *
+         * Note that your keys are **not** automatically added when using an
+         * agent. Run `ssh-add -l` locally to confirm which public keys are
+         * visible to the agent; these will be exposed to your build.
+         */
+        paths?: string[];
+    }
+
 }
 
 export namespace config {
diff --git a/sdk/python/pulumi_docker/buildx/_enums.py b/sdk/python/pulumi_docker/buildx/_enums.py
index 8bfd91af..e3281503 100644
--- a/sdk/python/pulumi_docker/buildx/_enums.py
+++ b/sdk/python/pulumi_docker/buildx/_enums.py
@@ -7,6 +7,7 @@
 __all__ = [
     'CacheMode',
     'CompressionType',
+    'NetworkMode',
     'Platform',
 ]
 
@@ -37,6 +38,21 @@ class CompressionType(str, Enum):
     """
 
 
+class NetworkMode(str, Enum):
+    DEFAULT = "default"
+    """
+    The default sandbox network mode.
+    """
+    HOST = "host"
+    """
+    Host network mode.
+    """
+    NONE = "none"
+    """
+    Disable network access.
+    """
+
+
 class Platform(str, Enum):
     DARWIN_386 = "darwin/386"
     DARWIN_AMD64 = "darwin/amd64"
diff --git a/sdk/python/pulumi_docker/buildx/_inputs.py b/sdk/python/pulumi_docker/buildx/_inputs.py
index 41e983dd..5f3e07ff 100644
--- a/sdk/python/pulumi_docker/buildx/_inputs.py
+++ b/sdk/python/pulumi_docker/buildx/_inputs.py
@@ -35,9 +35,8 @@
     'ExportOCIArgs',
     'ExportRegistryArgs',
     'ExportTarArgs',
-    'ManifestPlatformArgs',
-    'ManifestArgs',
     'RegistryAuthArgs',
+    'SSHArgs',
 ]
 
 @pulumi.input_type
@@ -1726,7 +1725,6 @@ def __init__(__self__, *,
                  docker: Optional[pulumi.Input['ExportDockerArgs']] = None,
                  image: Optional[pulumi.Input['ExportImageArgs']] = None,
                  local: Optional[pulumi.Input['ExportLocalArgs']] = None,
-                 manifests: Optional[pulumi.Input[Sequence[pulumi.Input['ManifestArgs']]]] = None,
                  oci: Optional[pulumi.Input['ExportOCIArgs']] = None,
                  raw: Optional[pulumi.Input[str]] = None,
                  registry: Optional[pulumi.Input['ExportRegistryArgs']] = None,
@@ -1736,8 +1734,6 @@ def __init__(__self__, *,
         :param pulumi.Input['ExportDockerArgs'] docker: Export as a Docker image layout.
         :param pulumi.Input['ExportImageArgs'] image: Outputs the build result into a container image format.
         :param pulumi.Input['ExportLocalArgs'] local: Export to a local directory as files and directories.
-        :param pulumi.Input[Sequence[pulumi.Input['ManifestArgs']]] manifests: An output property populated for exporters that pushed image
-               manifest(s) to a registry.
         :param pulumi.Input['ExportOCIArgs'] oci: Identical to the Docker exporter but uses OCI media types by default.
         :param pulumi.Input[str] raw: A raw string as you would provide it to the Docker CLI (e.g.,
                `type=docker`)
@@ -1752,8 +1748,6 @@ def __init__(__self__, *,
             pulumi.set(__self__, "image", image)
         if local is not None:
             pulumi.set(__self__, "local", local)
-        if manifests is not None:
-            pulumi.set(__self__, "manifests", manifests)
         if oci is not None:
             pulumi.set(__self__, "oci", oci)
         if raw is not None:
@@ -1811,19 +1805,6 @@ def local(self) -> Optional[pulumi.Input['ExportLocalArgs']]:
     def local(self, value: Optional[pulumi.Input['ExportLocalArgs']]):
         pulumi.set(self, "local", value)
 
-    @property
-    @pulumi.getter
-    def manifests(self) -> Optional[pulumi.Input[Sequence[pulumi.Input['ManifestArgs']]]]:
-        """
-        An output property populated for exporters that pushed image
-        manifest(s) to a registry.
-        """
-        return pulumi.get(self, "manifests")
-
-    @manifests.setter
-    def manifests(self, value: Optional[pulumi.Input[Sequence[pulumi.Input['ManifestArgs']]]]):
-        pulumi.set(self, "manifests", value)
-
     @property
     @pulumi.getter
     def oci(self) -> Optional[pulumi.Input['ExportOCIArgs']]:
@@ -2543,110 +2524,6 @@ def dest(self, value: pulumi.Input[str]):
         pulumi.set(self, "dest", value)
 
 
-@pulumi.input_type
-class ManifestPlatformArgs:
-    def __init__(__self__, *,
-                 architecture: pulumi.Input[str],
-                 os: pulumi.Input[str]):
-        """
-        :param pulumi.Input[str] architecture: The manifest's architecture.
-        :param pulumi.Input[str] os: The manifest's operating systen.
-        """
-        pulumi.set(__self__, "architecture", architecture)
-        pulumi.set(__self__, "os", os)
-
-    @property
-    @pulumi.getter
-    def architecture(self) -> pulumi.Input[str]:
-        """
-        The manifest's architecture.
-        """
-        return pulumi.get(self, "architecture")
-
-    @architecture.setter
-    def architecture(self, value: pulumi.Input[str]):
-        pulumi.set(self, "architecture", value)
-
-    @property
-    @pulumi.getter
-    def os(self) -> pulumi.Input[str]:
-        """
-        The manifest's operating systen.
-        """
-        return pulumi.get(self, "os")
-
-    @os.setter
-    def os(self, value: pulumi.Input[str]):
-        pulumi.set(self, "os", value)
-
-
-@pulumi.input_type
-class ManifestArgs:
-    def __init__(__self__, *,
-                 digest: pulumi.Input[str],
-                 platform: pulumi.Input['ManifestPlatformArgs'],
-                 ref: pulumi.Input[str],
-                 size: pulumi.Input[int]):
-        """
-        :param pulumi.Input[str] digest: The SHA256 digest of the manifest.
-        :param pulumi.Input['ManifestPlatformArgs'] platform: The manifest's platform.
-        :param pulumi.Input[str] ref: The manifest's canonical ref.
-        :param pulumi.Input[int] size: The size of the manifest in bytes.
-        """
-        pulumi.set(__self__, "digest", digest)
-        pulumi.set(__self__, "platform", platform)
-        pulumi.set(__self__, "ref", ref)
-        pulumi.set(__self__, "size", size)
-
-    @property
-    @pulumi.getter
-    def digest(self) -> pulumi.Input[str]:
-        """
-        The SHA256 digest of the manifest.
-        """
-        return pulumi.get(self, "digest")
-
-    @digest.setter
-    def digest(self, value: pulumi.Input[str]):
-        pulumi.set(self, "digest", value)
-
-    @property
-    @pulumi.getter
-    def platform(self) -> pulumi.Input['ManifestPlatformArgs']:
-        """
-        The manifest's platform.
-        """
-        return pulumi.get(self, "platform")
-
-    @platform.setter
-    def platform(self, value: pulumi.Input['ManifestPlatformArgs']):
-        pulumi.set(self, "platform", value)
-
-    @property
-    @pulumi.getter
-    def ref(self) -> pulumi.Input[str]:
-        """
-        The manifest's canonical ref.
-        """
-        return pulumi.get(self, "ref")
-
-    @ref.setter
-    def ref(self, value: pulumi.Input[str]):
-        pulumi.set(self, "ref", value)
-
-    @property
-    @pulumi.getter
-    def size(self) -> pulumi.Input[int]:
-        """
-        The size of the manifest in bytes.
-        """
-        return pulumi.get(self, "size")
-
-    @size.setter
-    def size(self, value: pulumi.Input[int]):
-        pulumi.set(self, "size", value)
-
-
 @pulumi.input_type
 class RegistryAuthArgs:
     def __init__(__self__, *,
@@ -2701,3 +2578,61 @@ def username(self, value: Optional[pulumi.Input[str]]):
         pulumi.set(self, "username", value)
 
 
+@pulumi.input_type
+class SSHArgs:
+    def __init__(__self__, *,
+                 id: pulumi.Input[str],
+                 paths: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None):
+        """
+        :param pulumi.Input[str] id: Useful for distinguishing different servers that are part of the same
+               build.
+               
+               A value of `default` is appropriate if only dealing with a single host.
+        :param pulumi.Input[Sequence[pulumi.Input[str]]] paths: SSH agent socket or private keys to expose to the build under the given
+               identifier.
+               
+               Defaults to `[$SSH_AUTH_SOCK]`.
+               
+               Note that your keys are **not** automatically added when using an
+               agent. Run `ssh-add -l` locally to confirm which public keys are
+               visible to the agent; these will be exposed to your build.
+        """
+        pulumi.set(__self__, "id", id)
+        if paths is not None:
+            pulumi.set(__self__, "paths", paths)
+
+    @property
+    @pulumi.getter
+    def id(self) -> pulumi.Input[str]:
+        """
+        Useful for distinguishing different servers that are part of the same
+        build.
+
+        A value of `default` is appropriate if only dealing with a single host.
+        """
+        return pulumi.get(self, "id")
+
+    @id.setter
+    def id(self, value: pulumi.Input[str]):
+        pulumi.set(self, "id", value)
+
+    @property
+    @pulumi.getter
+    def paths(self) -> Optional[pulumi.Input[Sequence[pulumi.Input[str]]]]:
+        """
+        SSH agent socket or private keys to expose to the build under the given
+        identifier.
+
+        Defaults to `[$SSH_AUTH_SOCK]`.
+
+        Note that your keys are **not** automatically added when using an
+        agent. Run `ssh-add -l` locally to confirm which public keys are
+        visible to the agent; these will be exposed to your build.
+        """
+        return pulumi.get(self, "paths")
+
+    @paths.setter
+    def paths(self, value: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]]):
+        pulumi.set(self, "paths", value)
+
+
diff --git a/sdk/python/pulumi_docker/buildx/image.py b/sdk/python/pulumi_docker/buildx/image.py
index f5e7bd5e..cfcf7a29 100644
--- a/sdk/python/pulumi_docker/buildx/image.py
+++ b/sdk/python/pulumi_docker/buildx/image.py
@@ -17,6 +17,7 @@
 @pulumi.input_type
 class ImageArgs:
     def __init__(__self__, *,
+                 add_hosts: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
                  build_args: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]] = None,
                  build_on_preview: Optional[pulumi.Input[bool]] = None,
                  builder: Optional[pulumi.Input['BuilderConfigArgs']] = None,
@@ -26,14 +27,22 @@ def __init__(__self__, *,
                  dockerfile: Optional[pulumi.Input['DockerfileArgs']] = None,
                  exports: Optional[pulumi.Input[Sequence[pulumi.Input['ExportEntryArgs']]]] = None,
                  labels: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]] = None,
+                 load: Optional[pulumi.Input[bool]] = None,
+                 network: Optional[pulumi.Input['NetworkMode']] = None,
+                 no_cache: Optional[pulumi.Input[bool]] = None,
                  platforms: Optional[pulumi.Input[Sequence[pulumi.Input['Platform']]]] = None,
                  pull: Optional[pulumi.Input[bool]] = None,
+                 push: Optional[pulumi.Input[bool]] = None,
                  registries: Optional[pulumi.Input[Sequence[pulumi.Input['RegistryAuthArgs']]]] = None,
                  secrets: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]] = None,
+                 ssh: Optional[pulumi.Input[Sequence[pulumi.Input['SSHArgs']]]] = None,
                  tags: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
                  targets: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None):
         """
         The set of arguments for constructing a Image resource.
+        :param pulumi.Input[Sequence[pulumi.Input[str]]] add_hosts: Custom `host:ip` mappings to use during the build.
+               
+               Equivalent to Docker's `--add-host` flag.
         :param pulumi.Input[Mapping[str, pulumi.Input[str]]] build_args: `ARG` names and values to set during the build.
                
                These variables are accessed like environment variables inside `RUN`
@@ -43,8 +52,20 @@ def __init__(__self__, *,
                if these arguments are sensitive.
                
                Equivalent to Docker's `--build-arg` flag.
-        :param pulumi.Input[bool] build_on_preview: When `true`, attempt to build the image during previews. The image will
-               not be pushed to registries, however caches will still be populated.
+        :param pulumi.Input[bool] build_on_preview: By default, preview behavior depends on the execution environment. If
+               Pulumi detects the operation is running on a CI system (GitHub Actions,
+               Travis CI, Azure Pipelines, etc.) then it will build images during
+               previews as a safeguard. Otherwise, if not running on CI, previews will
+               not build images.
+               
+               Setting this to `false` forces previews to never perform builds, and
+               setting it to `true` will always build the image during previews.
+               
+               Images built during previews are never exported to registries, however
+               cache manifests are still exported.
+               
+               On-disk Dockerfiles are always validated for syntactic correctness
+               regardless of this setting.
         :param pulumi.Input['BuilderConfigArgs'] builder: Builder configuration.
         :param pulumi.Input[Sequence[pulumi.Input['CacheFromEntryArgs']]] cache_from: Cache export configuration.
                
@@ -67,12 +88,30 @@ def __init__(__self__, *,
         :param pulumi.Input[Mapping[str, pulumi.Input[str]]] labels: Attach arbitrary key/value metadata to the image.
                
                Equivalent to Docker's `--label` flag.
+        :param pulumi.Input[bool] load: When `true` the build will automatically include a `docker` export.
+               
+               Defaults to `false`.
+               
+               Equivalent to Docker's `--load` flag.
+        :param pulumi.Input['NetworkMode'] network: Set the network mode for `RUN` instructions. Defaults to `default`.
+               
+               For custom networks, configure your builder with `--driver-opt network=...`.
+               
+               Equivalent to Docker's `--network` flag.
+        :param pulumi.Input[bool] no_cache: Do not import cache manifests when building the image.
+               
+               Equivalent to Docker's `--no-cache` flag.
         :param pulumi.Input[Sequence[pulumi.Input['Platform']]] platforms: Set target platform(s) for the build. Defaults to the host's platform.
                
                Equivalent to Docker's `--platform` flag.
         :param pulumi.Input[bool] pull: Always pull referenced images.
                
                Equivalent to Docker's `--pull` flag.
+        :param pulumi.Input[bool] push: When `true` the build will automatically include a `registry` export.
+               
+               Defaults to `false`.
+               
+               Equivalent to Docker's `--push` flag.
         :param pulumi.Input[Sequence[pulumi.Input['RegistryAuthArgs']]] registries: Registry credentials. Required if reading or exporting to private
                repositories.
                
@@ -89,6 +128,9 @@ def __init__(__self__, *,
                image, so you should use this for sensitive values.
                
                Similar to Docker's `--secret` flag.
+        :param pulumi.Input[Sequence[pulumi.Input['SSHArgs']]] ssh: SSH agent socket or keys to expose to the build.
+               
+               Equivalent to Docker's `--ssh` flag.
         :param pulumi.Input[Sequence[pulumi.Input[str]]] tags: Name and optionally a tag (format: `name:tag`).
                
                If exporting to a registry, the name should include the fully qualified
@@ -101,6 +143,8 @@ def __init__(__self__, *,
                
                Equivalent to Docker's `--target` flag.
         """
+        if add_hosts is not None:
+            pulumi.set(__self__, "add_hosts", add_hosts)
         if build_args is not None:
             pulumi.set(__self__, "build_args", build_args)
         if build_on_preview is not None:
@@ -119,19 +163,45 @@ def __init__(__self__, *,
             pulumi.set(__self__, "exports", exports)
         if labels is not None:
             pulumi.set(__self__, "labels", labels)
+        if load is not None:
+            pulumi.set(__self__, "load", load)
+        if network is None:
+            network = 'default'
+        if network is not None:
+            pulumi.set(__self__, "network", network)
+        if no_cache is not None:
+            pulumi.set(__self__, "no_cache", no_cache)
         if platforms is not None:
             pulumi.set(__self__, "platforms", platforms)
         if pull is not None:
             pulumi.set(__self__, "pull", pull)
+        if push is not None:
+            pulumi.set(__self__, "push", push)
         if registries is not None:
             pulumi.set(__self__, "registries", registries)
         if secrets is not None:
             pulumi.set(__self__, "secrets", secrets)
+        if ssh is not None:
+            pulumi.set(__self__, "ssh", ssh)
         if tags is not None:
             pulumi.set(__self__, "tags", tags)
         if targets is not None:
             pulumi.set(__self__, "targets", targets)
 
+    @property
+    @pulumi.getter(name="addHosts")
+    def add_hosts(self) -> Optional[pulumi.Input[Sequence[pulumi.Input[str]]]]:
+        """
+        Custom `host:ip` mappings to use during the build.
+
+        Equivalent to Docker's `--add-host` flag.
+        """
+        return pulumi.get(self, "add_hosts")
+
+    @add_hosts.setter
+    def add_hosts(self, value: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]]):
+        pulumi.set(self, "add_hosts", value)
+
     @property
     @pulumi.getter(name="buildArgs")
     def build_args(self) -> Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]]:
@@ -156,8 +226,20 @@ def build_args(self, value: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]
     @pulumi.getter(name="buildOnPreview")
     def build_on_preview(self) -> Optional[pulumi.Input[bool]]:
         """
-        When `true`, attempt to build the image during previews. The image will
-        not be pushed to registries, however caches will still be populated.
+        By default, preview behavior depends on the execution environment. If
+        Pulumi detects the operation is running on a CI system (GitHub Actions,
+        Travis CI, Azure Pipelines, etc.) then it will build images during
+        previews as a safeguard. Otherwise, if not running on CI, previews will
+        not build images.
+
+        Setting this to `false` forces previews to never perform builds, and
+        setting it to `true` will always build the image during previews.
+
+        Images built during previews are never exported to registries, however
+        cache manifests are still exported.
+
+        On-disk Dockerfiles are always validated for syntactic correctness
+        regardless of this setting.
         """
         return pulumi.get(self, "build_on_preview")
 
@@ -264,6 +346,52 @@ def labels(self) -> Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]]:
     def labels(self, value: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]]):
         pulumi.set(self, "labels", value)
 
+    @property
+    @pulumi.getter
+    def load(self) -> Optional[pulumi.Input[bool]]:
+        """
+        When `true` the build will automatically include a `docker` export.
+
+        Defaults to `false`.
+
+        Equivalent to Docker's `--load` flag.
+        """
+        return pulumi.get(self, "load")
+
+    @load.setter
+    def load(self, value: Optional[pulumi.Input[bool]]):
+        pulumi.set(self, "load", value)
+
+    @property
+    @pulumi.getter
+    def network(self) -> Optional[pulumi.Input['NetworkMode']]:
+        """
+        Set the network mode for `RUN` instructions. Defaults to `default`.
+
+        For custom networks, configure your builder with `--driver-opt network=...`.
+
+        Equivalent to Docker's `--network` flag.
+        """
+        return pulumi.get(self, "network")
+
+    @network.setter
+    def network(self, value: Optional[pulumi.Input['NetworkMode']]):
+        pulumi.set(self, "network", value)
+
+    @property
+    @pulumi.getter(name="noCache")
+    def no_cache(self) -> Optional[pulumi.Input[bool]]:
+        """
+        Do not import cache manifests when building the image.
+
+        Equivalent to Docker's `--no-cache` flag.
+        """
+        return pulumi.get(self, "no_cache")
+
+    @no_cache.setter
+    def no_cache(self, value: Optional[pulumi.Input[bool]]):
+        pulumi.set(self, "no_cache", value)
+
     @property
     @pulumi.getter
     def platforms(self) -> Optional[pulumi.Input[Sequence[pulumi.Input['Platform']]]]:
@@ -292,6 +420,22 @@ def pull(self) -> Optional[pulumi.Input[bool]]:
     def pull(self, value: Optional[pulumi.Input[bool]]):
         pulumi.set(self, "pull", value)
 
+    @property
+    @pulumi.getter
+    def push(self) -> Optional[pulumi.Input[bool]]:
+        """
+        When `true` the build will automatically include a `registry` export.
+
+        Defaults to `false`.
+
+        Equivalent to Docker's `--push` flag.
+        """
+        return pulumi.get(self, "push")
+
+    @push.setter
+    def push(self, value: Optional[pulumi.Input[bool]]):
+        pulumi.set(self, "push", value)
+
     @property
     @pulumi.getter
     def registries(self) -> Optional[pulumi.Input[Sequence[pulumi.Input['RegistryAuthArgs']]]]:
@@ -330,6 +474,20 @@ def secrets(self) -> Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]]:
     def secrets(self, value: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]]):
         pulumi.set(self, "secrets", value)
 
+    @property
+    @pulumi.getter
+    def ssh(self) -> Optional[pulumi.Input[Sequence[pulumi.Input['SSHArgs']]]]:
+        """
+        SSH agent socket or keys to expose to the build.
+
+        Equivalent to Docker's `--ssh` flag.
+        """
+        return pulumi.get(self, "ssh")
+
+    @ssh.setter
+    def ssh(self, value: Optional[pulumi.Input[Sequence[pulumi.Input['SSHArgs']]]]):
+        pulumi.set(self, "ssh", value)
+
     @property
     @pulumi.getter
     def tags(self) -> Optional[pulumi.Input[Sequence[pulumi.Input[str]]]]:
@@ -369,6 +527,7 @@ class Image(pulumi.CustomResource):
     def __init__(__self__,
                  resource_name: str,
                  opts: Optional[pulumi.ResourceOptions] = None,
+                 add_hosts: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
                  build_args: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]] = None,
                  build_on_preview: Optional[pulumi.Input[bool]] = None,
                  builder: Optional[pulumi.Input[pulumi.InputType['BuilderConfigArgs']]] = None,
@@ -378,10 +537,15 @@ def __init__(__self__,
                  dockerfile: Optional[pulumi.Input[pulumi.InputType['DockerfileArgs']]] = None,
                  exports: Optional[pulumi.Input[Sequence[pulumi.Input[pulumi.InputType['ExportEntryArgs']]]]] = None,
                  labels: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]] = None,
+                 load: Optional[pulumi.Input[bool]] = None,
+                 network: Optional[pulumi.Input['NetworkMode']] = None,
+                 no_cache: Optional[pulumi.Input[bool]] = None,
                  platforms: Optional[pulumi.Input[Sequence[pulumi.Input['Platform']]]] = None,
                  pull: Optional[pulumi.Input[bool]] = None,
+                 push: Optional[pulumi.Input[bool]] = None,
                  registries: Optional[pulumi.Input[Sequence[pulumi.Input[pulumi.InputType['RegistryAuthArgs']]]]] = None,
                  secrets: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]] = None,
+                 ssh: Optional[pulumi.Input[Sequence[pulumi.Input[pulumi.InputType['SSHArgs']]]]] = None,
                  tags: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
                  targets: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
                  __props__=None):
@@ -672,6 +836,9 @@ def __init__(__self__,
 
         :param str resource_name: The name of the resource.
         :param pulumi.ResourceOptions opts: Options for the resource.
+        :param pulumi.Input[Sequence[pulumi.Input[str]]] add_hosts: Custom `host:ip` mappings to use during the build.
+               
+               Equivalent to Docker's `--add-host` flag.
         :param pulumi.Input[Mapping[str, pulumi.Input[str]]] build_args: `ARG` names and values to set during the build.
                
                These variables are accessed like environment variables inside `RUN`
@@ -681,8 +848,20 @@ def __init__(__self__,
                if these arguments are sensitive.
                
                Equivalent to Docker's `--build-arg` flag.
-        :param pulumi.Input[bool] build_on_preview: When `true`, attempt to build the image during previews. The image will
-               not be pushed to registries, however caches will still be populated.
+        :param pulumi.Input[bool] build_on_preview: By default, preview behavior depends on the execution environment. If
+               Pulumi detects the operation is running on a CI system (GitHub Actions,
+               Travis CI, Azure Pipelines, etc.) then it will build images during
+               previews as a safeguard. Otherwise, if not running on CI, previews will
+               not build images.
+               
+               Setting this to `false` forces previews to never perform builds, and
+               setting it to `true` will always build the image during previews.
+               
+               Images built during previews are never exported to registries, however
+               cache manifests are still exported.
+               
+               On-disk Dockerfiles are always validated for syntactic correctness
+               regardless of this setting.
         :param pulumi.Input[pulumi.InputType['BuilderConfigArgs']] builder: Builder configuration.
         :param pulumi.Input[Sequence[pulumi.Input[pulumi.InputType['CacheFromEntryArgs']]]] cache_from: Cache export configuration.
                
@@ -705,12 +884,30 @@ def __init__(__self__,
         :param pulumi.Input[Mapping[str, pulumi.Input[str]]] labels: Attach arbitrary key/value metadata to the image.
                
                Equivalent to Docker's `--label` flag.
+        :param pulumi.Input[bool] load: When `true` the build will automatically include a `docker` export.
+               
+               Defaults to `false`.
+               
+               Equivalent to Docker's `--load` flag.
+        :param pulumi.Input['NetworkMode'] network: Set the network mode for `RUN` instructions. Defaults to `default`.
+               
+               For custom networks, configure your builder with `--driver-opt network=...`.
+               
+               Equivalent to Docker's `--network` flag.
+        :param pulumi.Input[bool] no_cache: Do not import cache manifests when building the image.
+               
+               Equivalent to Docker's `--no-cache` flag.
         :param pulumi.Input[Sequence[pulumi.Input['Platform']]] platforms: Set target platform(s) for the build. Defaults to the host's platform.
                
                Equivalent to Docker's `--platform` flag.
         :param pulumi.Input[bool] pull: Always pull referenced images.
                
                Equivalent to Docker's `--pull` flag.
+        :param pulumi.Input[bool] push: When `true` the build will automatically include a `registry` export.
+               
+               Defaults to `false`.
+               
+               Equivalent to Docker's `--push` flag.
         :param pulumi.Input[Sequence[pulumi.Input[pulumi.InputType['RegistryAuthArgs']]]] registries: Registry credentials. Required if reading or exporting to private
                repositories.
                
@@ -727,6 +924,9 @@ def __init__(__self__,
                image, so you should use this for sensitive values.
                
                Similar to Docker's `--secret` flag.
+        :param pulumi.Input[Sequence[pulumi.Input[pulumi.InputType['SSHArgs']]]] ssh: SSH agent socket or keys to expose to the build.
+               
+               Equivalent to Docker's `--ssh` flag.
         :param pulumi.Input[Sequence[pulumi.Input[str]]] tags: Name and optionally a tag (format: `name:tag`).
                
                If exporting to a registry, the name should include the fully qualified
@@ -1045,6 +1245,7 @@ def __init__(__self__, resource_name: str, *args, **kwargs):
     def _internal_init(__self__,
                  resource_name: str,
                  opts: Optional[pulumi.ResourceOptions] = None,
+                 add_hosts: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
                  build_args: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]] = None,
                  build_on_preview: Optional[pulumi.Input[bool]] = None,
                  builder: Optional[pulumi.Input[pulumi.InputType['BuilderConfigArgs']]] = None,
@@ -1054,10 +1255,15 @@ def _internal_init(__self__,
                  dockerfile: Optional[pulumi.Input[pulumi.InputType['DockerfileArgs']]] = None,
                  exports: Optional[pulumi.Input[Sequence[pulumi.Input[pulumi.InputType['ExportEntryArgs']]]]] = None,
                  labels: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]] = None,
+                 load: Optional[pulumi.Input[bool]] = None,
+                 network: Optional[pulumi.Input['NetworkMode']] = None,
+                 no_cache: Optional[pulumi.Input[bool]] = None,
                  platforms: Optional[pulumi.Input[Sequence[pulumi.Input['Platform']]]] = None,
                  pull: Optional[pulumi.Input[bool]] = None,
+                 push: Optional[pulumi.Input[bool]] = None,
                  registries: Optional[pulumi.Input[Sequence[pulumi.Input[pulumi.InputType['RegistryAuthArgs']]]]] = None,
                  secrets: Optional[pulumi.Input[Mapping[str, pulumi.Input[str]]]] = None,
+                 ssh: Optional[pulumi.Input[Sequence[pulumi.Input[pulumi.InputType['SSHArgs']]]]] = None,
                  tags: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
                  targets: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
                  __props__=None):
@@ -1069,6 +1275,7 @@ def _internal_init(__self__,
                 raise TypeError('__props__ is only valid when passed in combination with a valid opts.id to get an existing resource')
             __props__ = ImageArgs.__new__(ImageArgs)
 
+            __props__.__dict__["add_hosts"] = add_hosts
             __props__.__dict__["build_args"] = build_args
             __props__.__dict__["build_on_preview"] = build_on_preview
             __props__.__dict__["builder"] = builder
@@ -1078,16 +1285,22 @@ def _internal_init(__self__,
             __props__.__dict__["dockerfile"] = dockerfile
             __props__.__dict__["exports"] = exports
             __props__.__dict__["labels"] = labels
+            __props__.__dict__["load"] = load
+            if network is None:
+                network = 'default'
+            __props__.__dict__["network"] = network
+            __props__.__dict__["no_cache"] = no_cache
             __props__.__dict__["platforms"] = platforms
             __props__.__dict__["pull"] = pull
+            __props__.__dict__["push"] = push
             __props__.__dict__["registries"] = registries
-            __props__.__dict__["secrets"] = None if secrets is None else pulumi.Output.secret(secrets)
+            __props__.__dict__["secrets"] = secrets
+            __props__.__dict__["ssh"] = ssh
             __props__.__dict__["tags"] = tags
             __props__.__dict__["targets"] = targets
             __props__.__dict__["context_hash"] = None
             __props__.__dict__["digests"] = None
-        secret_opts = pulumi.ResourceOptions(additional_secret_outputs=["secrets"])
-        opts = pulumi.ResourceOptions.merge(opts, secret_opts)
+            __props__.__dict__["ref"] = None
         super(Image, __self__).__init__(
             'docker:buildx/image:Image',
             resource_name,
@@ -1110,6 +1323,7 @@ def get(resource_name: str,
 
         __props__ = ImageArgs.__new__(ImageArgs)
 
+        __props__.__dict__["add_hosts"] = None
         __props__.__dict__["build_args"] = None
         __props__.__dict__["build_on_preview"] = None
         __props__.__dict__["builder"] = None
@@ -1121,14 +1335,30 @@ def get(resource_name: str,
         __props__.__dict__["dockerfile"] = None
         __props__.__dict__["exports"] = None
         __props__.__dict__["labels"] = None
+        __props__.__dict__["load"] = None
+        __props__.__dict__["network"] = None
+        __props__.__dict__["no_cache"] = None
         __props__.__dict__["platforms"] = None
         __props__.__dict__["pull"] = None
+        __props__.__dict__["push"] = None
+        __props__.__dict__["ref"] = None
         __props__.__dict__["registries"] = None
         __props__.__dict__["secrets"] = None
+        __props__.__dict__["ssh"] = None
         __props__.__dict__["tags"] = None
         __props__.__dict__["targets"] = None
         return Image(resource_name, opts=opts, __props__=__props__)
 
+    @property
+    @pulumi.getter(name="addHosts")
+    def add_hosts(self) -> pulumi.Output[Optional[Sequence[str]]]:
+        """
+        Custom `host:ip` mappings to use during the build.
+
+        Equivalent to Docker's `--add-host` flag.
+        """
+        return pulumi.get(self, "add_hosts")
+
     @property
     @pulumi.getter(name="buildArgs")
     def build_args(self) -> pulumi.Output[Optional[Mapping[str, str]]]:
@@ -1149,8 +1379,20 @@ def build_args(self) -> pulumi.Output[Optional[Mapping[str, str]]]:
     @pulumi.getter(name="buildOnPreview")
     def build_on_preview(self) -> pulumi.Output[Optional[bool]]:
         """
-        When `true`, attempt to build the image during previews. The image will
-        not be pushed to registries, however caches will still be populated.
+        By default, preview behavior depends on the execution environment. If
+        Pulumi detects the operation is running on a CI system (GitHub Actions,
+        Travis CI, Azure Pipelines, etc.) then it will build images during
+        previews as a safeguard. Otherwise, if not running on CI, previews will
+        not build images.
+
+        Setting this to `false` forces previews to never perform builds, and
+        setting it to `true` will always build the image during previews.
+
+        Images built during previews are never exported to registries, however
+        cache manifests are still exported.
+
+        On-disk Dockerfiles are always validated for syntactic correctness
+        regardless of this setting.
         """
         return pulumi.get(self, "build_on_preview")
 
@@ -1194,7 +1436,7 @@ def context(self) -> pulumi.Output[Optional['outputs.BuildContext']]:
 
     @property
     @pulumi.getter(name="contextHash")
-    def context_hash(self) -> pulumi.Output[Optional[str]]:
+    def context_hash(self) -> pulumi.Output[str]:
         """
         A preliminary hash of the image's build context.
 
@@ -1204,9 +1446,13 @@ def context_hash(self) -> pulumi.Output[Optional[str]]:
 
     @property
     @pulumi.getter
-    def digests(self) -> pulumi.Output[Optional[Mapping[str, Sequence[str]]]]:
+    def digests(self) -> pulumi.Output[Mapping[str, str]]:
         """
-        A mapping of platform type to refs which were pushed to registries.
+        A mapping of target names to the SHA256 digest of their pushed manifest.
+
+        If no target was specified 'default' is used as the target name.
+
+        Pushed manifests can be referenced as `<tag>@<digest>`.
         """
         return pulumi.get(self, "digests")
 
@@ -1243,6 +1489,40 @@ def labels(self) -> pulumi.Output[Optional[Mapping[str, str]]]:
         """
         return pulumi.get(self, "labels")
 
+    @property
+    @pulumi.getter
+    def load(self) -> pulumi.Output[Optional[bool]]:
+        """
+        When `true` the build will automatically include a `docker` export.
+
+        Defaults to `false`.
+
+        Equivalent to Docker's `--load` flag.
+        """
+        return pulumi.get(self, "load")
+
+    @property
+    @pulumi.getter
+    def network(self) -> pulumi.Output[Optional['NetworkMode']]:
+        """
+        Set the network mode for `RUN` instructions. Defaults to `default`.
+
+        For custom networks, configure your builder with `--driver-opt network=...`.
+
+        Equivalent to Docker's `--network` flag.
+        """
+        return pulumi.get(self, "network")
+
+    @property
+    @pulumi.getter(name="noCache")
+    def no_cache(self) -> pulumi.Output[Optional[bool]]:
+        """
+        Do not import cache manifests when building the image.
+
+        Equivalent to Docker's `--no-cache` flag.
+        """
+        return pulumi.get(self, "no_cache")
+
     @property
     @pulumi.getter
     def platforms(self) -> pulumi.Output[Optional[Sequence['Platform']]]:
@@ -1263,6 +1543,34 @@ def pull(self) -> pulumi.Output[Optional[bool]]:
         """
         return pulumi.get(self, "pull")
 
+    @property
+    @pulumi.getter
+    def push(self) -> pulumi.Output[Optional[bool]]:
+        """
+        When `true` the build will automatically include a `registry` export.
+
+        Defaults to `false`.
+
+        Equivalent to Docker's `--push` flag.
+        """
+        return pulumi.get(self, "push")
+
+    @property
+    @pulumi.getter
+    def ref(self) -> pulumi.Output[str]:
+        """
+        If the image was pushed to any registries then this will contain a
+        single fully-qualified tag including the build's digest.
+
+        This is only for convenience and may not be appropriate for situations
+        where multiple tags or registries are involved. In those cases this
+        output is not guaranteed to be stable.
+
+        For more control over tags consumed by downstream resources you should
+        use the `Digests` output.
+        """
+        return pulumi.get(self, "ref")
+
     @property
     @pulumi.getter
     def registries(self) -> pulumi.Output[Optional[Sequence['outputs.RegistryAuth']]]:
@@ -1293,6 +1601,16 @@ def secrets(self) -> pulumi.Output[Optional[Mapping[str, str]]]:
         """
         return pulumi.get(self, "secrets")
 
+    @property
+    @pulumi.getter
+    def ssh(self) -> pulumi.Output[Optional[Sequence['outputs.SSH']]]:
+        """
+        SSH agent socket or keys to expose to the build.
+
+        Equivalent to Docker's `--ssh` flag.
+        """
+        return pulumi.get(self, "ssh")
+
     @property
     @pulumi.getter
     def tags(self) -> pulumi.Output[Optional[Sequence[str]]]:
diff --git a/sdk/python/pulumi_docker/buildx/outputs.py b/sdk/python/pulumi_docker/buildx/outputs.py
index d695c496..4fdd5105 100644
--- a/sdk/python/pulumi_docker/buildx/outputs.py
+++ b/sdk/python/pulumi_docker/buildx/outputs.py
@@ -36,9 +36,8 @@
     'ExportOCI',
     'ExportRegistry',
     'ExportTar',
-    'Manifest',
-    'ManifestPlatform',
     'RegistryAuth',
+    'SSH',
 ]
 
 @pulumi.output_type
@@ -1575,7 +1574,6 @@ def __init__(__self__, *,
                  docker: Optional['outputs.ExportDocker'] = None,
                  image: Optional['outputs.ExportImage'] = None,
                  local: Optional['outputs.ExportLocal'] = None,
-                 manifests: Optional[Sequence['outputs.Manifest']] = None,
                  oci: Optional['outputs.ExportOCI'] = None,
                  raw: Optional[str] = None,
                  registry: Optional['outputs.ExportRegistry'] = None,
@@ -1585,8 +1583,6 @@ def __init__(__self__, *,
         :param 'ExportDockerArgs' docker: Export as a Docker image layout.
         :param 'ExportImageArgs' image: Outputs the build result into a container image format.
         :param 'ExportLocalArgs' local: Export to a local directory as files and directories.
-        :param Sequence['ManifestArgs'] manifests: An output property populated for exporters that pushed image
-               manifest(s) to a registry.
         :param 'ExportOCIArgs' oci: Identical to the Docker exporter but uses OCI media types by default.
         :param str raw: A raw string as you would provide it to the Docker CLI (e.g.,
                `type=docker`)
@@ -1601,8 +1597,6 @@ def __init__(__self__, *,
             pulumi.set(__self__, "image", image)
         if local is not None:
             pulumi.set(__self__, "local", local)
-        if manifests is not None:
-            pulumi.set(__self__, "manifests", manifests)
         if oci is not None:
             pulumi.set(__self__, "oci", oci)
         if raw is not None:
@@ -1644,15 +1638,6 @@ def local(self) -> Optional['outputs.ExportLocal']:
         """
         return pulumi.get(self, "local")
 
-    @property
-    @pulumi.getter
-    def manifests(self) -> Optional[Sequence['outputs.Manifest']]:
-        """
-        An output property populated for exporters that pushed image
-        manifest(s) to a registry.
-        """
-        return pulumi.get(self, "manifests")
-
     @property
     @pulumi.getter
     def oci(self) -> Optional['outputs.ExportOCI']:
@@ -2287,86 +2272,6 @@ def dest(self) -> str:
         return pulumi.get(self, "dest")
 
 
-@pulumi.output_type
-class Manifest(dict):
-    def __init__(__self__, *,
-                 digest: str,
-                 platform: 'outputs.ManifestPlatform',
-                 ref: str,
-                 size: int):
-        """
-        :param str digest: The SHA256 digest of the manifest.
-        :param 'ManifestPlatformArgs' platform: The manifest's platform.
-        :param str ref: The manifest's canonical ref.
-        :param int size: The size of the manifest in bytes.
-        """
-        pulumi.set(__self__, "digest", digest)
-        pulumi.set(__self__, "platform", platform)
-        pulumi.set(__self__, "ref", ref)
-        pulumi.set(__self__, "size", size)
-
-    @property
-    @pulumi.getter
-    def digest(self) -> str:
-        """
-        The SHA256 digest of the manifest.
-        """
-        return pulumi.get(self, "digest")
-
-    @property
-    @pulumi.getter
-    def platform(self) -> 'outputs.ManifestPlatform':
-        """
-        The manifest's platform.
-        """
-        return pulumi.get(self, "platform")
-
-    @property
-    @pulumi.getter
-    def ref(self) -> str:
-        """
-        The manifest's canonical ref.
-        """
-        return pulumi.get(self, "ref")
-
-    @property
-    @pulumi.getter
-    def size(self) -> int:
-        """
-        The size of the manifest in bytes.
-        """
-        return pulumi.get(self, "size")
-
-
-@pulumi.output_type
-class ManifestPlatform(dict):
-    def __init__(__self__, *,
-                 architecture: str,
-                 os: str):
-        """
-        :param str architecture: The manifest's architecture.
-        :param str os: The manifest's operating systen.
-        """
-        pulumi.set(__self__, "architecture", architecture)
-        pulumi.set(__self__, "os", os)
-
-    @property
-    @pulumi.getter
-    def architecture(self) -> str:
-        """
-        The manifest's architecture.
-        """
-        return pulumi.get(self, "architecture")
-
-    @property
-    @pulumi.getter
-    def os(self) -> str:
-        """
-        The manifest's operating systen.
-        """
-        return pulumi.get(self, "os")
-
-
 @pulumi.output_type
 class RegistryAuth(dict):
     def __init__(__self__, *,
@@ -2409,3 +2314,53 @@ def username(self) -> Optional[str]:
         return pulumi.get(self, "username")
 
 
+@pulumi.output_type
+class SSH(dict):
+    def __init__(__self__, *,
+                 id: str,
+                 paths: Optional[Sequence[str]] = None):
+        """
+        :param str id: Useful for distinguishing different servers that are part of the same
+               build.
+               
+               A value of `default` is appropriate if only dealing with a single host.
+        :param Sequence[str] paths: SSH agent socket or private keys to expose to the build under the given
+               identifier.
+               
+               Defaults to `[$SSH_AUTH_SOCK]`.
+               
+               Note that your keys are **not** automatically added when using an
+               agent. Run `ssh-add -l` locally to confirm which public keys are
+               visible to the agent; these will be exposed to your build.
+        """
+        pulumi.set(__self__, "id", id)
+        if paths is not None:
+            pulumi.set(__self__, "paths", paths)
+
+    @property
+    @pulumi.getter
+    def id(self) -> str:
+        """
+        Useful for distinguishing different servers that are part of the same
+        build.
+
+        A value of `default` is appropriate if only dealing with a single host.
+        """
+        return pulumi.get(self, "id")
+
+    @property
+    @pulumi.getter
+    def paths(self) -> Optional[Sequence[str]]:
+        """
+        SSH agent socket or private keys to expose to the build under the given
+        identifier.
+
+        Defaults to `[$SSH_AUTH_SOCK]`.
+
+        Note that your keys are **not** automatically added when using an
+        agent. Run `ssh-add -l` locally to confirm which public keys are
+        visible to the agent; these will be exposed to your build.
+        """
+        return pulumi.get(self, "paths")
+
+