Skip to content

Proxy environment is not propagated to subsequent gateway container processes #6994

Description

@gmarmstrong

Contributing guidelines and issue reporting guide

Well-formed report checklist

  • I have found a bug that the documentation does not mention anything about my problem
  • I have found a bug that there are no open or closed issues that are related to my problem
  • I have provided version/information about my environment and done my best to provide a reproducer

Bug description

Gateway containers using SolveOpt.ProxyNetwork receive BuildKit’s generated proxy environment in the initial process, but not in subsequent processes started with Container.Start.

The first process started in the container receives BuildKit's generated HTTP_PROXY, HTTPS_PROXY, and NO_PROXY variables. Processes started later with Container.Start do not receive them, although unrelated variables supplied in StartRequest.Env are preserved.

BuildKit should add these proxy variables to every process started with Container.Start, not just the first.

Reproduction

  1. Check out BuildKit at f5d08d5a04381687203ced27ef877e0c417fd122.
  2. Save the program below as hack/repro-proxy-env-gateway/main.go:
hack/repro-proxy-env-gateway/main.go
package main

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"

	bkclient "github.com/moby/buildkit/client"
	_ "github.com/moby/buildkit/client/connhelper/dockercontainer"
	"github.com/moby/buildkit/client/llb"
	gateway "github.com/moby/buildkit/frontend/gateway/client"
	"github.com/moby/buildkit/solver/pb"
	ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
)

type writeCloser struct{ io.Writer }

func (writeCloser) Close() error { return nil }

func main() {
	ctx := context.Background()
	c, err := bkclient.New(ctx, os.Getenv("BUILDKIT_HOST"))
	check(err)
	defer c.Close()

	var output bytes.Buffer
	_, err = c.Build(ctx, bkclient.SolveOpt{ProxyNetwork: true}, "proxy-env-gateway-repro", func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
		def, err := llb.Image("busybox:latest", llb.Platform(ocispecs.Platform{
			OS:           "linux",
			Architecture: runtime.GOARCH,
		})).Marshal(ctx)
		if err != nil {
			return nil, err
		}
		res, err := c.Solve(ctx, gateway.SolveRequest{Definition: def.ToPB()})
		if err != nil {
			return nil, err
		}
		ctr, err := c.NewContainer(ctx, gateway.NewContainerRequest{Mounts: []gateway.Mount{{
			Dest:      "/",
			MountType: pb.MountType_BIND,
			Ref:       res.Ref,
		}}})
		if err != nil {
			return nil, err
		}
		init, err := ctr.Start(ctx, gateway.StartRequest{
			Args: []string{"sh", "-c", "env > /tmp/init.env; exec sleep 30"},
		})
		if err != nil {
			_ = ctr.Release(context.WithoutCancel(ctx))
			return nil, err
		}
		defer func() {
			_ = ctr.Release(context.WithoutCancel(ctx))
			_ = init.Wait()
		}()

		exec, err := ctr.Start(ctx, gateway.StartRequest{
			Args:   []string{"sh", "-c", "while [ ! -s /tmp/init.env ]; do :; done; echo '--- initial process ---'; cat /tmp/init.env; echo '--- exec process ---'; env"},
			Env:    []string{"CHILD_ENV=preserved"},
			Stdout: writeCloser{Writer: &output},
		})
		if err != nil {
			return nil, err
		}
		if err := exec.Wait(); err != nil {
			return nil, err
		}
		return gateway.NewResult(), nil
	}, nil)
	check(err)

	fmt.Print(output.String())
	execEnv := strings.SplitN(output.String(), "--- exec process ---\n", 2)
	if len(execEnv) != 2 || !strings.Contains(execEnv[1], "HTTP_PROXY=") {
		fmt.Fprintln(os.Stderr, "\nBUG: HTTP_PROXY is missing from the gateway exec process")
		os.Exit(1)
	}
}

func check(err error) {
	if err != nil {
		panic(err)
	}
}
  1. Run:
$ docker buildx build --load -t moby/buildkit:proxy-env-repro --build-arg BUILDKIT_CONTEXT_KEEP_GIT_DIR=1 .
$ docker run --rm -d --name buildkit-proxy-env-repro --privileged moby/buildkit:proxy-env-repro
$ BUILDKIT_HOST=docker-container://buildkit-proxy-env-repro go run ./hack/repro-proxy-env-gateway
$ docker rm -f buildkit-proxy-env-repro

Observed output:

--- initial process ---
HTTP_PROXY=http://<internal-proxy-ip>:<port>
HTTPS_PROXY=http://<internal-proxy-ip>:<port>
http_proxy=http://<internal-proxy-ip>:<port>
https_proxy=http://<internal-proxy-ip>:<port>
NO_PROXY=127.0.0.1,localhost,::1
no_proxy=127.0.0.1,localhost,::1
...
--- exec process ---
CHILD_ENV=preserved
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/root

BUG: HTTP_PROXY is missing from the gateway exec process
exit status 1

Version information

$ git rev-parse HEAD
f5d08d5a04381687203ced27ef877e0c417fd122

$ go version
go version go1.26.3 darwin/arm64

$ docker --version
Docker version 27.5.1, build v27.5.1

$ docker buildx version
github.com/docker/buildx v0.23.0

$ colima version
colima version 0.8.1
git commit: 96598cc

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions