Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/.test-bake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ jobs:
const builderOutputs = JSON.parse(core.getInput('builder-outputs'));
core.info(JSON.stringify(builderOutputs, null, 2));

bake-proxy-network:
uses: ./.github/workflows/bake.yml
permissions:
contents: read
with:
cache: true
cache-scope: bake-proxynettest
context: test
output: local
target: proxy-network
buildkit-proxy-network: true

bake-ecr-public:
uses: ./.github/workflows/bake.yml
if: ${{ github.event_name != 'pull_request' }}
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/.test-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ jobs:
const builderOutputs = JSON.parse(core.getInput('builder-outputs'));
core.info(JSON.stringify(builderOutputs, null, 2));

build-proxy-network:
uses: ./.github/workflows/build.yml
permissions:
contents: read
with:
cache: true
cache-scope: build-proxynettest
file: test/proxy-network.Dockerfile
output: local
buildkit-proxy-network: true

build-ecr-public:
uses: ./.github/workflows/build.yml
if: ${{ github.event_name != 'pull_request' }}
Expand Down
27 changes: 24 additions & 3 deletions .github/workflows/bake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ on:
type: string
description: "Bake target name for metadata (defaults to docker-metadata-action)"
required: false
# buildkit config
buildkit-proxy-network:
type: boolean
description: "Enable BuildKit proxy network mode"
required: false
default: false
secrets:
registry-auths:
description: "Raw authentication to registries, defined as YAML objects (for image output)"
Expand Down Expand Up @@ -210,6 +216,7 @@ jobs:
sign: ${{ steps.set.outputs.sign }}
privateRepo: ${{ steps.set.outputs.privateRepo }}
ghaCacheSign: ${{ steps.set.outputs.ghaCacheSign }}
proxyNetwork: ${{ steps.set.outputs.proxyNetwork }}
steps:
-
name: Install dependencies
Expand Down Expand Up @@ -315,6 +322,7 @@ jobs:
INPUT_TARGET: ${{ inputs.target }}
INPUT_VARS: ${{ inputs.vars }}
INPUT_GITHUB-TOKEN: ${{ secrets.github-token || github.token }}
INPUT_BUILDKIT-PROXY-NETWORK: ${{ inputs.buildkit-proxy-network }}
with:
script: |
const os = require('os');
Expand Down Expand Up @@ -342,6 +350,7 @@ jobs:
const inpSign = core.getInput('sign');
const inpTarget = core.getInput('target');
const inpGitHubToken = core.getInput('github-token');
const inpProxyNetwork = core.getBooleanInput('buildkit-proxy-network');

const parseRunnerConfig = value => {
const lines = value.map(line => line.trim()).filter(line => line.length > 0);
Expand Down Expand Up @@ -564,6 +573,12 @@ jobs:
core.info(`privateRepo: ${privateRepo}`);
core.setOutput('privateRepo', privateRepo);
});

await core.group(`Set proxyNetwork output`, async () => {
const proxyNetwork = inpProxyNetwork ? 'true' : 'false';
core.info(`proxyNetwork: ${proxyNetwork}`);
core.setOutput('proxyNetwork', proxyNetwork);
});

await core.group(`Set includes output`, async () => {
const withJobNamePrefix = include => {
Expand Down Expand Up @@ -719,6 +734,8 @@ jobs:
env.ACTIONS_ID_TOKEN_REQUEST_TOKEN=${{ steps.github-runtime.outputs.actions-id-token-request-token }}
env.ACTIONS_ID_TOKEN_REQUEST_URL=${{ steps.github-runtime.outputs.actions-id-token-request-url }}
buildkitd-config-inline: |
proxyNetwork = ${{ needs.prepare.outputs.proxyNetwork }}

[cache]
[cache.gha]
[cache.gha.sign]
Expand Down Expand Up @@ -849,6 +866,7 @@ jobs:
INPUT_BAKE-FILE-ANNOTATIONS: ${{ steps.meta.outputs.bake-file-annotations }}
INPUT_BAKE-FILE-LABELS: ${{ steps.meta.outputs.bake-file-labels }}
INPUT_GITHUB-TOKEN: ${{ secrets.github-token || github.token }}
INPUT_BUILDKIT-PROXY-NETWORK: ${{ inputs.buildkit-proxy-network }}
with:
script: |
const os = require('os');
Expand All @@ -874,6 +892,9 @@ jobs:
const inpSet = Util.getInputList('set', {ignoreComma: true, quote: false});
const inpTarget = core.getInput('target');
const inpVars = Util.getInputList('vars');
const inpGitHubToken = core.getInput('github-token');
const inpBuildkitProxyNetwork = core.getBooleanInput('buildkit-proxy-network');

const inpMetaImages = core.getMultilineInput('meta-images');
const inpMetaVersion = core.getInput('meta-version');
const inpMetaTags = core.getMultilineInput('meta-tags');
Expand All @@ -882,7 +903,6 @@ jobs:
const inpBakeFileTags = core.getInput('bake-file-tags');
const inpBakeFileAnnotations = core.getInput('bake-file-annotations');
const inpBakeFileLabels = core.getInput('bake-file-labels');
const inpGitHubToken = core.getInput('github-token');

const meta = {
version: inpMetaVersion,
Expand Down Expand Up @@ -982,8 +1002,9 @@ jobs:
bakeOverrides.push(`*.platform=${inpPlatform}`);
}
if (inpCache) {
bakeOverrides.push(`*.cache-from=type=gha,scope=${inpCacheScope || inpTarget}${platformPairSuffix}`);
bakeOverrides.push(`*.cache-to=type=gha,ignore-error=true,scope=${inpCacheScope || inpTarget}${platformPairSuffix},mode=${inpCacheMode}`);
const proxyNetworkSuffix = inpBuildkitProxyNetwork ? '-proxy-network' : '';
bakeOverrides.push(`*.cache-from=type=gha,scope=${inpCacheScope || inpTarget}${platformPairSuffix}${proxyNetworkSuffix}`);
bakeOverrides.push(`*.cache-to=type=gha,ignore-error=true,scope=${inpCacheScope || inpTarget}${platformPairSuffix}${proxyNetworkSuffix},mode=${inpCacheMode}`);
}
core.info(JSON.stringify(bakeOverrides, null, 2));
core.setOutput('overrides', bakeOverrides.join(os.EOL));
Expand Down
27 changes: 23 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ on:
type: string
description: "Flavor defines a global behavior for meta-tags"
required: false
# buildkit config
buildkit-proxy-network:
type: boolean
description: "Enable BuildKit proxy network mode"
required: false
default: false
secrets:
registry-auths:
description: "Raw authentication to registries, defined as YAML objects (for image output)"
Expand Down Expand Up @@ -221,6 +227,7 @@ jobs:
sign: ${{ steps.set.outputs.sign }}
privateRepo: ${{ steps.set.outputs.privateRepo }}
ghaCacheSign: ${{ steps.set.outputs.ghaCacheSign }}
proxyNetwork: ${{ steps.set.outputs.proxyNetwork }}
steps:
-
name: Install dependencies
Expand Down Expand Up @@ -311,6 +318,7 @@ jobs:
INPUT_PLATFORMS: ${{ inputs.platforms }}
INPUT_PUSH: ${{ inputs.push }}
INPUT_SIGN: ${{ inputs.sign }}
INPUT_BUILDKIT-PROXY-NETWORK: ${{ inputs.buildkit-proxy-network }}
with:
script: |
const { GitHub } = require('@docker/github-builder-runtime/lib/github/github');
Expand All @@ -328,6 +336,7 @@ jobs:
const inpOutput = core.getInput('output');
const inpPush = core.getBooleanInput('push');
const inpSign = core.getInput('sign');
const inpProxyNetwork = core.getBooleanInput('buildkit-proxy-network');

const parseRunnerConfig = value => {
const lines = value.map(line => line.trim()).filter(line => line.length > 0);
Expand Down Expand Up @@ -458,6 +467,12 @@ jobs:
core.setOutput('privateRepo', privateRepo);
});

await core.group(`Set proxyNetwork output`, async () => {
const proxyNetwork = inpProxyNetwork ? 'true' : 'false';
core.info(`proxyNetwork: ${proxyNetwork}`);
core.setOutput('proxyNetwork', proxyNetwork);
});

const metaImages = inpMetaImages.map(image => image.toLowerCase());
await core.group(`Set metaImages output`, async () => {
core.info(JSON.stringify(metaImages, null, 2));
Expand Down Expand Up @@ -617,6 +632,8 @@ jobs:
env.ACTIONS_ID_TOKEN_REQUEST_TOKEN=${{ steps.github-runtime.outputs.actions-id-token-request-token }}
env.ACTIONS_ID_TOKEN_REQUEST_URL=${{ steps.github-runtime.outputs.actions-id-token-request-url }}
buildkitd-config-inline: |
proxyNetwork = ${{ needs.prepare.outputs.proxyNetwork }}

[cache]
[cache.gha]
[cache.gha.sign]
Expand Down Expand Up @@ -733,6 +750,7 @@ jobs:
INPUT_CACHE: ${{ inputs.cache }}
INPUT_CACHE-SCOPE: ${{ inputs.cache-scope }}
INPUT_CACHE-MODE: ${{ inputs.cache-mode }}
INPUT_BUILDKIT-PROXY-NETWORK: ${{ inputs.buildkit-proxy-network }}
INPUT_LABELS: ${{ inputs.labels }}
INPUT_CONTEXT: ${{ inputs.context }}
INPUT_OUTPUT: ${{ inputs.output }}
Expand Down Expand Up @@ -773,6 +791,7 @@ jobs:
const inpPush = core.getBooleanInput('push');
const inpSbom = core.getBooleanInput('sbom');
const inpTarget = core.getInput('target');
const inpBuildkitProxyNetwork = core.getBooleanInput('buildkit-proxy-network');

const inpMetaImages = core.getMultilineInput('meta-images');
const inpMetaVersion = core.getInput('meta-version');
Expand All @@ -786,9 +805,7 @@ jobs:
version: inpMetaVersion,
tags: inpMetaTags
};

const renderTemplate = value => Util.compileHandlebars(value, {noEscape: true}, {meta});
const toMultilineInput = value => value.split(/\r?\n/).map(line => line.trim()).filter(Boolean);

const gitContextAttrs = GitHub.context.ref.startsWith('refs/tags/') ? {checksum: GitHub.context.sha} : {'fetch-by-commit': 'true'};
const buildContext = await new Build().gitContext({subdir: inpContext, attrs: gitContextAttrs});
Expand Down Expand Up @@ -819,14 +836,16 @@ jobs:
core.setOutput('sbom', inpSbom ? `generator=${inpSbomImage}` : 'false');

if (inpCache) {
core.setOutput('cache-from', `type=gha,scope=${inpCacheScope || inpTarget || 'buildkit'}${platformPairSuffix}`);
core.setOutput('cache-to', `type=gha,ignore-error=true,scope=${inpCacheScope || inpTarget || 'buildkit'}${platformPairSuffix},mode=${inpCacheMode}`);
const proxyNetworkSuffix = inpBuildkitProxyNetwork ? '-proxy-network' : '';
core.setOutput('cache-from', `type=gha,scope=${inpCacheScope || inpTarget || 'buildkit'}${platformPairSuffix}${proxyNetworkSuffix}`);
core.setOutput('cache-to', `type=gha,ignore-error=true,scope=${inpCacheScope || inpTarget || 'buildkit'}${platformPairSuffix}${proxyNetworkSuffix},mode=${inpCacheMode}`);
}

let annotations;
let labels;
let buildArgs;
try {
const toMultilineInput = value => value.split(/\r?\n/).map(line => line.trim()).filter(Boolean);
annotations = toMultilineInput(renderTemplate(inpAnnotations));
labels = toMultilineInput(renderTemplate(inpLabels));
buildArgs = renderTemplate(inpBuildArgs);
Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ ___
* [Secrets](#secrets-1)
* [Outputs](#outputs-1)
* [Notes](#notes)
* [BuildKit proxy network](#buildkit-proxy-network)
* [Signed GitHub Actions cache](#signed-github-actions-cache)
* [Registry identities](#registry-identities)
* [Docker Hub OIDC](#docker-hub-oidc)
Expand Down Expand Up @@ -252,6 +253,7 @@ jobs:
| `meta-labels` | List | | [List of custom labels](https://github.com/docker/metadata-action?tab=readme-ov-file#overwrite-labels-and-annotations) |
| `meta-annotations` | List | | [List of custom annotations](https://github.com/docker/metadata-action?tab=readme-ov-file#overwrite-labels-and-annotations) |
| `meta-flavor` | List | | [Flavor](https://github.com/docker/metadata-action?tab=readme-ov-file#flavor-input) defines a global behavior for `meta-tags` |
| `buildkit-proxy-network` | Bool | `false` | Enable BuildKit proxy network mode for default Dockerfile `RUN` networking. See [BuildKit proxy network](#buildkit-proxy-network). |

### Secrets

Expand Down Expand Up @@ -364,6 +366,7 @@ jobs:
| `meta-labels` | List | | [List of custom labels](https://github.com/docker/metadata-action?tab=readme-ov-file#overwrite-labels-and-annotations) |
| `meta-annotations` | List | | [List of custom annotations](https://github.com/docker/metadata-action?tab=readme-ov-file#overwrite-labels-and-annotations) |
| `meta-flavor` | List | | [Flavor](https://github.com/docker/metadata-action?tab=readme-ov-file#flavor-input) defines a global behavior for `meta-tags` |
| `buildkit-proxy-network` | Bool | `false` | Enable BuildKit proxy network mode for default Dockerfile `RUN` networking. See [BuildKit proxy network](#buildkit-proxy-network). |

### Secrets

Expand All @@ -390,6 +393,36 @@ with `builder-outputs: ${{ toJSON(needs.<job_id>.outputs) }}`.

## Notes

### BuildKit proxy network

The `buildkit-proxy-network` input enables BuildKit proxy network mode for
Dockerfile `RUN` steps with network access. `RUN --network=none` stays offline,
but default-network `RUN` steps are routed through BuildKit's internal HTTP(S)
proxy.

When enabled, BuildKit rewrites `HTTP_PROXY`, `HTTPS_PROXY`, `http_proxy`, and
`https_proxy` inside affected `RUN` operations to point at that internal proxy.
It also injects a generated CA certificate into common Linux system trust bundle
locations for the duration of the operation. HTTPS clients that use separate or
embedded trust stores may fail TLS verification, and applications that ignore
proxy environment variables or open raw TCP connections cannot bypass the proxy.
Direct DNS and non-HTTP(S) protocols, such as Git-over-SSH, are not available
through this mode.

BuildKit logs proxy network requests. Successful GET responses can be captured
as build materials and included in provenance dependency metadata when
provenance is requested. When `cache` is enabled, these workflows append
`-proxy-network` to the GitHub Actions cache scope while proxy network mode is
enabled, so unproxied cache entries are not imported into a proxied build. A
cache hit that was originally produced under proxy mode still does not execute
the network step again, so it does not emit a fresh request log or add new
provenance material.

BuildKit does not chain the internal proxy through a caller-provided upstream
proxy. Enabling `buildkit-proxy-network` replaces Docker's predefined proxy
build arguments for affected `RUN` operations and can bypass an application-level
organizational proxy. See BuildKit's [proxy network documentation](https://github.com/moby/buildkit/blob/master/docs/proxy.md).

### Signed GitHub Actions cache

When the workflow has GitHub OIDC available through `id-token: write`, BuildKit
Expand Down
4 changes: 4 additions & 0 deletions test/docker-bake.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ target "hello-cross" {
platforms = ["linux/amd64", "linux/arm64"]
}

target "proxy-network" {
dockerfile = "proxy-network.Dockerfile"
}

target "go-cross-with-contexts" {
inherits = ["go-cross"]
contexts = {
Expand Down
9 changes: 9 additions & 0 deletions test/proxy-network.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# syntax=docker/dockerfile:1

FROM alpine AS check
RUN wget -qO- https://checkip.amazonaws.com/ | grep -Eq "^[0-9a-fA-F:.]+$"
RUN grep -q "buildkit proxy CA begin" /etc/ssl/certs/ca-certificates.crt
RUN --network=none ! grep -q "buildkit proxy CA begin" /etc/ssl/certs/ca-certificates.crt

FROM scratch
COPY --from=check /etc/alpine-release /alpine-release
Loading