Compare commits

...

15 Commits

Author SHA1 Message Date
Raghav d10b5ea8b8 feat: [CI-23743]: Add HARNESS_CA_PATH support for egress-proxy CA trust (#517)
The plugin now reads a HARNESS_CA_PATH environment variable pointing to a PEM CA file and installs it into the host system trust store before starting the Docker daemon. This solves x509 errors when builds run behind TLS-intercepting egress proxies that re-sign upstream TLS with their own CA.

- Linux: installs into distro anchor directory (/usr/local/share/ca-certificates or /etc/pki/ca-trust/source/anchors) and refreshes system bundle via update-ca-certificates/update-ca-trust, with direct bundle append fallback
- Windows: imports via certutil -addstore Root
- macOS: logged no-op (not currently supported)
- Best-effort, idempotent, documented in README.md with usage examples
- New platform-specific source files: ca_linux.go, ca_windows.go, ca_other.go
- Comprehensive tests added: ca_test.go, ca_linux_test.go

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

AI-Session-Id: fe2aa5fe-1bf5-4257-ab76-2c862c5637fe
AI-Tool: claude-code
AI-Model: unknown
2026-07-14 20:02:58 +05:30
Tapan Karangiya 8371ac46ae Update pipeline drone-docker-harness 2026-07-09 11:06:22 +05:30
Tapan Karangiya a4a38753ce Update pipeline drone-docker-harness 2026-07-09 11:03:56 +05:30
Tapan Karangiya 1ade22dbc0 Update pipeline drone-docker-harness 2026-07-09 10:59:12 +05:30
Raghav 65a576e26b Merge pull request #514 from drone-plugins/CI-23609
feat: [CI-23609]: docker files for windows 2025
2026-07-08 17:52:36 +05:30
tapankarangiya 994fe7a8e4 feat: [CI-23609]: docker files for windows 2025 2026-07-08 16:16:19 +05:30
tapankarangiya 35365e35c8 feat: [CI-23609]: docker files for windows 2025 2026-07-07 18:06:11 +05:30
tapankarangiya 3070ebd7da feat: [CI-23609]: docker files for windows 2025 2026-07-07 13:40:18 +05:30
Maanav Shah f6164cf702 Merge pull request #511 from drone-plugins/CI-21939-fix
feat: [CI-21939]: reverting the changes in docker version
2026-06-04 11:39:54 +05:30
Chirag S f946dac9ae feat: [CI-21939]: reverting changes in the docker version 2026-06-03 10:22:02 +05:30
Maanav Shah 801ca62c15 Merge pull request #509 from maxknee/mk/update-docker
update docker version
2026-05-20 11:12:47 +05:30
dhiraj.chhawchharia@harness.io 95df76b75d Update pipeline drone-docker-harness 2026-05-05 12:23:39 +05:30
dhiraj.chhawchharia@harness.io d9b3767c94 Update pipeline drone-docker-harness 2026-05-05 12:08:01 +05:30
raghav.gupta@harness.io 1482f4d794 Update pipeline drone-docker-harness 2026-05-05 11:27:32 +05:30
Max Knee 19d0d55c04 update docker version
Signed-off-by: Max Knee <max.knee@nytimes.com>
2026-04-07 13:40:36 -04:00
18 changed files with 610 additions and 12 deletions
+69 -5
View File
@@ -674,12 +674,11 @@ pipeline:
auto_tag_suffix: windows-1809-amd64
when:
stageStatus: Success
condition: <+codebase.build.type> == "tag"
condition: <+codebase.build.type> == "branch"
strategy:
matrix:
repo:
- docker
- gcr
- gar
- ecr
- acr
@@ -701,7 +700,6 @@ pipeline:
matrix:
repo:
- docker
- gcr
- gar
- ecr
- acr
@@ -780,7 +778,6 @@ pipeline:
matrix:
repo:
- docker
- gcr
- gar
- ecr
- acr
@@ -802,12 +799,79 @@ pipeline:
matrix:
repo:
- docker
- gcr
- gar
- ecr
- acr
buildIntelligence:
enabled: false
- stage:
name: win-ltsc-2025-amd64
identifier: winltsc2025amd64
description: ""
type: CI
spec:
cloneCodebase: true
caching:
enabled: false
override: false
paths: []
buildIntelligence:
enabled: false
infrastructure:
type: VM
spec:
type: Pool
spec:
poolName: windows-2025
os: Windows
execution:
steps:
- step:
type: Run
name: Build Binary 2025
identifier: Build_Binary_2025
spec:
connectorRef: Plugins_Docker_Hub_Connector
image: golang:1.23.0
shell: Sh
command: |-
# disable cgo
export CGO_ENABLED=0
go build -o release/windows/amd64/drone-<+matrix.repo>.exe ./cmd/drone-<+matrix.repo>
strategy:
matrix:
repo:
- docker
- gcr
- gar
- ecr
- acr
- step:
type: Plugin
name: Plugin_1
identifier: Plugin_1
spec:
connectorRef: Plugins_Docker_Hub_Connector
image: plugins/docker:windows-ltsc2025-amd64
settings:
username: drone
password: <+secrets.getValue("Plugins_Docker_Hub_Pat")>
repo: plugins/<+matrix.repo>
dockerfile: docker/<+matrix.repo>/Dockerfile.windows.amd64.ltsc2025
auto_tag: "true"
auto_tag_suffix: windows-ltsc2025-amd64
strategy:
matrix:
repo:
- docker
- gcr
- gar
- ecr
- acr
when:
stageStatus: Success
condition: <+codebase.build.type> == "tag"
- stage:
name: Manifest and Release
identifier: Manifest
+48
View File
@@ -114,6 +114,54 @@ COOL BANANAS
```
### Trusting a custom / egress-proxy CA (`HARNESS_CA_PATH`)
When builds run behind a TLS-intercepting egress proxy (e.g. Harness egress
control), the proxy re-signs upstream TLS with its own CA. The Docker daemon and
its embedded BuildKit verify registry TLS against the **host system trust
store**, so base-image pulls fail with
`x509: certificate signed by unknown authority` unless that CA is trusted.
Set the `HARNESS_CA_PATH` environment variable to a PEM CA (bundle) file and the
plugin installs it into the host trust store **before starting the Docker
daemon**:
```yaml
steps:
- name: build and push
image: plugins/docker
pull: never
environment:
HARNESS_CA_PATH: /etc/harness-certs/ca.crt
settings:
repo: octocat/hello-world
tags: latest
```
Behavior:
- **Linux** — installs into the distro anchor dir
(`/usr/local/share/ca-certificates` on Debian/Ubuntu/Alpine,
`/etc/pki/ca-trust/source/anchors` on RHEL/CentOS/Fedora) and runs
`update-ca-certificates` / `update-ca-trust`. It also appends the CA directly
to the consolidated bundle (`/etc/ssl/certs/ca-certificates.crt` or the RHEL
equivalent) so trust holds even on minimal images without a refresh tool.
- **Windows** — imports the CA into the machine trust store via
`certutil -addstore -f Root`.
- **macOS / other** — logged no-op (not currently supported).
Notes:
- It is **best-effort and idempotent**: when `HARNESS_CA_PATH` is unset, the file
is missing, or the file is empty, the plugin logs and continues. Re-running the
step will not duplicate the CA in the bundle.
- The CA is trusted for the daemon's own registry TLS (base-image pulls, cache
endpoints). To make the CA available to `RUN` steps inside the build, also pass
it as needed via the Dockerfile / build args.
- This is separate from the proxy build args
(`http_proxy`/`https_proxy`/`no_proxy`), which the plugin already injects from
the environment (including `HARNESS_`-prefixed variants).
### Running from the CLI
```console
+110
View File
@@ -0,0 +1,110 @@
//go:build linux
// +build linux
package docker
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
)
// anchorCandidate is a distro CA anchor directory plus the tool that refreshes
// the consolidated bundle from it.
type anchorCandidate struct {
dir string
refresh []string
}
// linuxAnchorCandidates and linuxBundleCandidates are package vars (not consts)
// so tests can point them at a temp trust store. Order matters: the first
// existing entry wins for the anchor install.
var linuxAnchorCandidates = []anchorCandidate{
{"/usr/local/share/ca-certificates", []string{"update-ca-certificates"}}, // Debian/Ubuntu/Alpine
{"/etc/pki/ca-trust/source/anchors", []string{"update-ca-trust", "extract"}}, // RHEL/CentOS/Fedora
}
var linuxBundleCandidates = []string{
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Alpine
"/etc/pki/tls/certs/ca-bundle.crt", // RHEL/CentOS
}
// installHarnessCA drops the CA into the distro anchor directory and refreshes
// the system bundle. It also appends directly to the consolidated bundle so
// trust is effective even on images that lack update-ca-certificates (e.g.
// minimal distros); the Docker daemon and Go's crypto/x509 read from that
// bundle. Best-effort: failures are logged, never fatal.
func installHarnessCA(caPEM []byte) {
anchorCandidates := linuxAnchorCandidates
installedViaAnchor := false
for _, c := range anchorCandidates {
if _, err := os.Stat(c.dir); err != nil {
continue
}
dst := filepath.Join(c.dir, "harness-egress-ca.crt")
if err := os.WriteFile(dst, caPEM, 0644); err != nil {
fmt.Printf("Could not write Harness CA to %s: %s\n", dst, err)
continue
}
if _, err := exec.LookPath(c.refresh[0]); err != nil {
continue
}
cmd := exec.Command(c.refresh[0], c.refresh[1:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Printf("Warning: %s failed: %s\n", c.refresh[0], err)
continue
}
fmt.Printf("Installed Harness egress CA into %s and refreshed system trust store.\n", c.dir)
installedViaAnchor = true
break
}
// Belt-and-suspenders: append to the consolidated bundle(s) directly so the
// CA is trusted even when no refresh tool exists or the anchor step failed.
bundleCandidates := linuxBundleCandidates
appended := false
for _, bundle := range bundleCandidates {
if _, err := os.Stat(bundle); err != nil {
continue
}
if bundleContainsCA(bundle, caPEM) {
appended = true
continue
}
f, err := os.OpenFile(bundle, os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
fmt.Printf("Could not append Harness CA to %s: %s\n", bundle, err)
continue
}
payload := caPEM
if !bytes.HasPrefix(payload, []byte("\n")) {
payload = append([]byte("\n"), payload...)
}
if _, err := f.Write(payload); err != nil {
fmt.Printf("Could not append Harness CA to %s: %s\n", bundle, err)
} else {
fmt.Printf("Appended Harness egress CA to %s.\n", bundle)
appended = true
}
f.Close()
}
if !installedViaAnchor && !appended {
fmt.Println("Warning: could not install the Harness egress CA into any known trust store location; base-image pulls through the egress proxy may fail with x509 errors.")
}
}
// bundleContainsCA reports whether the CA bytes are already present in the
// bundle, to keep the step idempotent across retries.
func bundleContainsCA(bundle string, caPEM []byte) bool {
existing, err := os.ReadFile(bundle)
if err != nil {
return false
}
return bytes.Contains(existing, bytes.TrimSpace(caPEM))
}
+82
View File
@@ -0,0 +1,82 @@
//go:build linux
// +build linux
package docker
import (
"os"
"path/filepath"
"strings"
"testing"
)
// withTempTrustStore points the Linux anchor/bundle candidates at a temp dir so
// installHarnessCA can be exercised without touching the real system store.
func withTempTrustStore(t *testing.T) (anchorDir, bundlePath string) {
t.Helper()
dir := t.TempDir()
anchorDir = filepath.Join(dir, "anchors")
bundlePath = filepath.Join(dir, "ca-certificates.crt")
if err := os.MkdirAll(anchorDir, 0755); err != nil {
t.Fatal(err)
}
// Seed an existing bundle so the append path is exercised.
if err := os.WriteFile(bundlePath, []byte("# existing roots\n"), 0644); err != nil {
t.Fatal(err)
}
origAnchors := linuxAnchorCandidates
origBundles := linuxBundleCandidates
// No refresh tool on the anchor entry so the test doesn't shell out.
linuxAnchorCandidates = []anchorCandidate{{dir: anchorDir, refresh: []string{"harness-nonexistent-refresh-tool"}}}
linuxBundleCandidates = []string{bundlePath}
t.Cleanup(func() {
linuxAnchorCandidates = origAnchors
linuxBundleCandidates = origBundles
})
return anchorDir, bundlePath
}
func TestInstallHarnessCA_Linux(t *testing.T) {
anchorDir, bundlePath := withTempTrustStore(t)
installHarnessCA([]byte(testCAPEM))
// Anchor file should be written.
anchorFile := filepath.Join(anchorDir, "harness-egress-ca.crt")
got, err := os.ReadFile(anchorFile)
if err != nil {
t.Fatalf("expected anchor file at %s: %s", anchorFile, err)
}
if string(got) != testCAPEM {
t.Fatalf("anchor file = %q, want %q", string(got), testCAPEM)
}
// Bundle should have the CA appended (refresh tool is absent, so the
// direct-append fallback is what provides trust here).
bundle, err := os.ReadFile(bundlePath)
if err != nil {
t.Fatal(err)
}
if !strings.Contains(string(bundle), strings.TrimSpace(testCAPEM)) {
t.Fatalf("bundle %q does not contain appended CA", string(bundle))
}
if !strings.HasPrefix(string(bundle), "# existing roots") {
t.Fatalf("bundle append clobbered existing roots: %q", string(bundle))
}
}
func TestInstallHarnessCA_Linux_Idempotent(t *testing.T) {
_, bundlePath := withTempTrustStore(t)
installHarnessCA([]byte(testCAPEM))
installHarnessCA([]byte(testCAPEM))
bundle, err := os.ReadFile(bundlePath)
if err != nil {
t.Fatal(err)
}
if n := strings.Count(string(bundle), strings.TrimSpace(testCAPEM)); n != 1 {
t.Fatalf("expected CA to appear exactly once after two installs, got %d", n)
}
}
+12
View File
@@ -0,0 +1,12 @@
//go:build !linux && !windows
// +build !linux,!windows
package docker
import "fmt"
// installHarnessCA is a no-op on platforms where egress control is not yet
// supported (e.g. macOS). HARNESS_CA_PATH is honored on Linux and Windows.
func installHarnessCA(caPEM []byte) {
fmt.Println("HARNESS_CA_PATH is set but egress-proxy CA trust injection is not supported on this platform; skipping.")
}
+87
View File
@@ -0,0 +1,87 @@
package docker
import (
"os"
"path/filepath"
"testing"
)
const testCAPEM = `-----BEGIN CERTIFICATE-----
MIIBAg==
-----END CERTIFICATE-----
`
// withStubbedInstall replaces the platform installer with a capturing stub for
// the duration of a test, returning a pointer to the captured CA bytes and a
// pointer to a call counter.
func withStubbedInstall(t *testing.T) (captured *[]byte, calls *int) {
t.Helper()
captured = new([]byte)
calls = new(int)
orig := installHarnessCAFn
installHarnessCAFn = func(caPEM []byte) {
*calls++
*captured = append([]byte(nil), caPEM...)
}
t.Cleanup(func() { installHarnessCAFn = orig })
return captured, calls
}
func TestTrustHarnessCA_Unset(t *testing.T) {
os.Unsetenv("HARNESS_CA_PATH")
_, calls := withStubbedInstall(t)
trustHarnessCA()
if *calls != 0 {
t.Fatalf("expected installer not to be called when HARNESS_CA_PATH is unset, got %d calls", *calls)
}
}
func TestTrustHarnessCA_MissingFile(t *testing.T) {
missing := filepath.Join(t.TempDir(), "does-not-exist.crt")
os.Setenv("HARNESS_CA_PATH", missing)
defer os.Unsetenv("HARNESS_CA_PATH")
_, calls := withStubbedInstall(t)
trustHarnessCA()
if *calls != 0 {
t.Fatalf("expected installer not to be called when CA file is missing, got %d calls", *calls)
}
}
func TestTrustHarnessCA_EmptyFile(t *testing.T) {
empty := filepath.Join(t.TempDir(), "empty.crt")
if err := os.WriteFile(empty, []byte(" \n\t"), 0644); err != nil {
t.Fatal(err)
}
os.Setenv("HARNESS_CA_PATH", empty)
defer os.Unsetenv("HARNESS_CA_PATH")
_, calls := withStubbedInstall(t)
trustHarnessCA()
if *calls != 0 {
t.Fatalf("expected installer not to be called for whitespace-only CA, got %d calls", *calls)
}
}
func TestTrustHarnessCA_ValidFile(t *testing.T) {
valid := filepath.Join(t.TempDir(), "ca.crt")
if err := os.WriteFile(valid, []byte(testCAPEM), 0644); err != nil {
t.Fatal(err)
}
os.Setenv("HARNESS_CA_PATH", valid)
defer os.Unsetenv("HARNESS_CA_PATH")
captured, calls := withStubbedInstall(t)
trustHarnessCA()
if *calls != 1 {
t.Fatalf("expected installer to be called once for a valid CA, got %d calls", *calls)
}
if string(*captured) != testCAPEM {
t.Fatalf("installer received %q, want %q", string(*captured), testCAPEM)
}
}
+51
View File
@@ -0,0 +1,51 @@
//go:build windows
// +build windows
package docker
import (
"fmt"
"os"
"os/exec"
)
// installHarnessCA imports the Harness egress-proxy CA into the Windows
// certificate store under LocalMachine\Root (the machine-wide trusted roots the
// Docker daemon and Go's crypto/x509 consult). Best-effort: failures are logged,
// never fatal.
//
// certutil needs a file path, so the (already-validated) CA bytes are written to
// a temp .crt first, then added with `certutil -addstore -f Root <file>`.
func installHarnessCA(caPEM []byte) {
tmp, err := os.CreateTemp("", "harness-egress-ca-*.crt")
if err != nil {
fmt.Printf("Could not create temp file for Harness CA: %s\n", err)
return
}
tmpPath := tmp.Name()
defer os.Remove(tmpPath)
if _, err := tmp.Write(caPEM); err != nil {
tmp.Close()
fmt.Printf("Could not write temp Harness CA: %s\n", err)
return
}
tmp.Close()
if _, err := exec.LookPath("certutil"); err != nil {
fmt.Printf("certutil not found on PATH; cannot install Harness egress CA: %s\n", err)
fmt.Println("Base-image pulls through the egress proxy may fail with x509 errors.")
return
}
// -f overwrites an existing entry, keeping the step idempotent across retries.
cmd := exec.Command("certutil", "-addstore", "-f", "Root", tmpPath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Printf("Warning: certutil -addstore Root failed: %s\n", err)
fmt.Println("Base-image pulls through the egress proxy may fail with x509 errors.")
return
}
fmt.Println("Installed Harness egress CA into the Windows LocalMachine\\Root store.")
}
+45 -7
View File
@@ -1,6 +1,7 @@
package docker
import (
"bytes"
"errors"
"fmt"
"os"
@@ -131,6 +132,14 @@ type (
// Exec executes the plugin step
func (p Plugin) Exec() error {
// Trust the Harness egress-proxy CA (if HARNESS_CA_PATH is set) BEFORE the
// daemon starts. The Docker daemon and its embedded BuildKit verify registry
// TLS against the host system trust store; when traffic goes through the
// TLS-intercepting egress proxy, the presented cert is signed by the Harness
// CA and must be trusted here or base-image pulls fail with an x509
// "unknown authority" error.
trustHarnessCA()
// start the Docker daemon server
if !p.Daemon.Disabled {
p.startDaemon()
@@ -331,7 +340,7 @@ func (p Plugin) Exec() error {
if digest, err := getDigest(p.Build.TempTag); err == nil {
fmt.Printf("🔐 Found image digest: %s\n", digest)
// Sign with digest reference
imageRef := fmt.Sprintf("%s@%s", p.Build.Repo, digest)
cosignCmd := createCosignCommand(imageRef, p.Cosign)
@@ -339,7 +348,7 @@ func (p Plugin) Exec() error {
} else {
fmt.Printf("⚠️ WARNING: Could not get image digest for cosign signing: %s\n", err)
fmt.Printf(" Falling back to tag-based signing\n")
// Fall back to tag-based signing for each tag
for _, tag := range p.Build.Tags {
imageRef := fmt.Sprintf("%s:%s", p.Build.Repo, tag)
@@ -574,6 +583,35 @@ func getSecretCmdArg(kvp string, file bool) (string, error) {
return fmt.Sprintf("id=%s,env=%s", key, value), nil
}
// trustHarnessCA installs the Harness egress-proxy CA into the host trust store
// so the Docker daemon / embedded BuildKit trust the TLS-intercepting proxy when
// pulling base images. It is driven by HARNESS_CA_PATH (path to a PEM CA bundle)
// and is a best-effort no-op when the var is unset, the file is missing, or the
// platform isn't supported — build failures are surfaced later by docker itself.
// The platform-specific installation is provided by installHarnessCA (see
// ca_linux.go / ca_windows.go / ca_other.go); it is indirected through
// installHarnessCAFn so tests can stub the actual system-trust write.
var installHarnessCAFn = installHarnessCA
func trustHarnessCA() {
caPath := os.Getenv("HARNESS_CA_PATH")
if caPath == "" {
return
}
caPEM, err := os.ReadFile(caPath)
if err != nil {
fmt.Printf("HARNESS_CA_PATH is set to %q but the CA could not be read: %s. Skipping CA trust.\n", caPath, err)
return
}
if len(bytes.TrimSpace(caPEM)) == 0 {
fmt.Printf("HARNESS_CA_PATH %q is empty. Skipping CA trust.\n", caPath)
return
}
installHarnessCAFn(caPEM)
}
// helper function to add proxy values from the environment
func addProxyBuildArgs(build *Build) {
addProxyValue(build, "http_proxy")
@@ -853,7 +891,7 @@ func isValidPEMKey(pemContent string) bool {
// createCosignCommand creates a cosign sign command with the given image reference
func createCosignCommand(imageRef string, cosign CosignConfig) *exec.Cmd {
args := []string{"sign", "--yes"}
// Handle private key (content vs file path)
if strings.HasPrefix(cosign.PrivateKey, "-----BEGIN") {
args = append(args, "--key", "env://COSIGN_PRIVATE_KEY")
@@ -861,21 +899,21 @@ func createCosignCommand(imageRef string, cosign CosignConfig) *exec.Cmd {
} else {
args = append(args, "--key", cosign.PrivateKey)
}
// Set password if provided
if cosign.Password != "" {
os.Setenv("COSIGN_PASSWORD", cosign.Password)
}
// Add any extra parameters
if cosign.Params != "" {
extraArgs := strings.Fields(cosign.Params)
args = append(args, extraArgs...)
}
// Add the image reference to sign
args = append(args, imageRef)
return exec.Command(cosignExe, args...)
}
@@ -0,0 +1,10 @@
# escape=`
FROM plugins/docker:windows-ltsc2025-amd64
LABEL maintainer="Drone.IO Community <drone-dev@googlegroups.com>" `
org.label-schema.name="Drone ACR" `
org.label-schema.vendor="Drone.IO Community" `
org.label-schema.schema-version="1.0"
ADD release/windows/amd64/drone-acr.exe C:/bin/drone-acr.exe
ENTRYPOINT [ "C:\\bin\\drone-acr.exe" ]
+6
View File
@@ -29,3 +29,9 @@ manifests:
architecture: amd64
os: windows
version: ltsc2022
-
image: plugins/acr:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-ltsc2025-amd64
platform:
architecture: amd64
os: windows
version: ltsc2025
@@ -0,0 +1,36 @@
# escape=`
FROM mcr.microsoft.com/windows/servercore:ltsc2025 as download
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
# Modernized for ltsc2025: fetch the standalone Docker CLI matching the daemon
# generation used on Windows Server 2025 hosts (28.x). Replaces the 1809/ltsc2022
# pattern of extracting docker.exe from DockerToolbox 19.03.1 via innoextract.
ENV DOCKER_VERSION 28.4.0
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; `
Invoke-WebRequest -UseBasicParsing `
$('https://download.docker.com/win/static/stable/x86_64/docker-{0}.zip' -f $env:DOCKER_VERSION) `
-OutFile docker.zip ; `
Expand-Archive docker.zip -DestinationPath C:\ ; `
Remove-Item docker.zip
FROM mcr.microsoft.com/windows/nanoserver:ltsc2025
USER ContainerAdministrator
LABEL maintainer="Drone.IO Community <drone-dev@googlegroups.com>" `
org.label-schema.name="Drone Docker" `
org.label-schema.vendor="Drone.IO Community" `
org.label-schema.schema-version="1.0"
RUN mkdir C:\bin
# Install cosign for container image signing
ADD https://github.com/sigstore/cosign/releases/download/v2.5.3/cosign-windows-amd64.exe C:/bin/cosign.exe
# nanoserver:ltsc2025 ships netapi32.dll natively (unlike 1809/ltsc2022 where we
# had to copy it in from servercore). Overwriting the ltsc2025 copy fails with
# "Access is denied" because system32 files are locked, so we skip that COPY.
COPY --from=download /docker/docker.exe C:/bin/docker.exe
ADD release/windows/amd64/drone-docker.exe C:/bin/drone-docker.exe
ENTRYPOINT [ "C:\\bin\\drone-docker.exe" ]
+6
View File
@@ -29,3 +29,9 @@ manifests:
architecture: amd64
os: windows
version: ltsc2022
-
image: plugins/docker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-ltsc2025-amd64
platform:
architecture: amd64
os: windows
version: ltsc2025
@@ -0,0 +1,10 @@
# escape=`
FROM plugins/docker:windows-ltsc2025-amd64
LABEL maintainer="Drone.IO Community <drone-dev@googlegroups.com>" `
org.label-schema.name="Drone ECR" `
org.label-schema.vendor="Drone.IO Community" `
org.label-schema.schema-version="1.0"
ADD release/windows/amd64/drone-ecr.exe C:/bin/drone-ecr.exe
ENTRYPOINT [ "C:\\bin\\drone-ecr.exe" ]
+6
View File
@@ -29,3 +29,9 @@ manifests:
architecture: amd64
os: windows
version: ltsc2022
-
image: plugins/ecr:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-ltsc2025-amd64
platform:
architecture: amd64
os: windows
version: ltsc2025
@@ -0,0 +1,10 @@
# escape=`
FROM plugins/docker:windows-ltsc2025-amd64
LABEL maintainer="Drone.IO Community <drone-dev@googlegroups.com>" `
org.label-schema.name="Drone GAR" `
org.label-schema.vendor="Drone.IO Community" `
org.label-schema.schema-version="1.0"
ADD release/windows/amd64/drone-gar.exe C:/bin/drone-gar.exe
ENTRYPOINT [ "C:\\bin\\drone-gar.exe" ]
+6
View File
@@ -29,3 +29,9 @@ manifests:
architecture: amd64
os: windows
version: ltsc2022
-
image: plugins/gar:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-ltsc2025-amd64
platform:
architecture: amd64
os: windows
version: ltsc2025
@@ -0,0 +1,10 @@
# escape=`
FROM plugins/docker:windows-ltsc2025-amd64
LABEL maintainer="Drone.IO Community <drone-dev@googlegroups.com>" `
org.label-schema.name="Drone GCR" `
org.label-schema.vendor="Drone.IO Community" `
org.label-schema.schema-version="1.0"
ADD release/windows/amd64/drone-gcr.exe C:/bin/drone-gcr.exe
ENTRYPOINT [ "C:\\bin\\drone-gcr.exe" ]
+6
View File
@@ -29,3 +29,9 @@ manifests:
architecture: amd64
os: windows
version: ltsc2022
-
image: plugins/gcr:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-ltsc2025-amd64
platform:
architecture: amd64
os: windows
version: ltsc2025