✦ For everyone, free.

Practical knowledge for real and everyday life

Home

16.1.2.3 Build Network Failure

A focused guide to Build Network Failure, connecting core concepts with practical Docker and container operations.

Build network failure refers specifically to problems with the network namespace and connectivity available to instructions running during a Docker build, a distinct layer from whether a specific remote repository or registry is reachable, since a RUN instruction executes inside its own isolated network context that can be configured, restricted, or misconfigured independently of the host's own otherwise-working network connectivity.

The default build network mode

By default, RUN instructions execute with network access through a mechanism similar to a container's default bridge networking, which is generally sufficient for typical build needs like fetching dependencies, but can behave differently from what a developer's own host networking setup might lead them to expect:

RUN curl -sf https://example.com/file.tar.gz -o file.tar.gz
docker build -t my-api .

If this fails specifically inside the build but the same curl command succeeds when run directly on the host, the difference points toward something specific to the build's own network context, isolation, DNS configuration, or proxy settings, rather than a genuine inability of the host itself to reach the target.

Explicitly setting the build network mode

The --network flag controls what networking a RUN instruction has access to during the build, and explicitly setting it can both resolve and help diagnose build-specific connectivity issues:

docker build --network=host -t my-api .
docker build --network=none -t my-api .

--network=host gives build instructions direct access to the host's own network namespace, which can resolve connectivity issues specific to the isolated build network, particularly in environments with unusual network configurations like certain VPN setups; --network=none deliberately removes network access entirely, useful for confirming that a specific build step genuinely does not require network access, or for testing that a build remains reproducible without depending on any external fetch.

DNS resolution specific to the build environment

A build's isolated network context can have different DNS resolution behavior than the host itself, particularly relevant in corporate environments where the host's own DNS configuration includes internal resolvers that are not automatically inherited by the build's network namespace:

docker build --dns=10.0.0.53 -t my-api .
{
  "dns": ["10.0.0.53", "8.8.8.8"]
}

Configuring DNS explicitly, either per-build or as a daemon-wide default in daemon.json, addresses cases where internal hostnames resolve correctly on the host but fail to resolve inside the build's own network context using whatever DNS configuration it inherited by default.

Proxy configuration for builds behind a corporate firewall

In environments where outbound internet access is only available through an HTTP or HTTPS proxy, build instructions need that proxy configuration explicitly passed through, since it is not automatically inherited from the host's own environment variables unless specifically configured to do so:

docker build --build-arg HTTP_PROXY=http://proxy.internal:8080 \
             --build-arg HTTPS_PROXY=http://proxy.internal:8080 \
             --build-arg NO_PROXY=localhost,127.0.0.1 \
             -t my-api .
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY

Declaring these as ARG instructions in the Dockerfile, in addition to passing them on the build command line, is necessary for the values to actually be available as environment variables to the build instructions; without the corresponding ARG declarations, the --build-arg values passed on the command line have no effect inside the build at all.

BuildKit's network isolation differences

BuildKit, the modern build backend used by default in current Docker versions, has somewhat different default networking behavior and isolation characteristics compared to the legacy builder, which is worth being aware of specifically when migrating a Dockerfile or build pipeline that was originally written and tested against the older builder:

DOCKER_BUILDKIT=0 docker build -t my-api .

Temporarily building with the legacy builder disabled, or explicitly enabled, can help isolate whether a specific networking behavior difference is attributable to which build backend is actually being used, particularly for unusual or edge-case network configurations that behave differently between the two.

Corporate VPN interactions

A host connected to a corporate VPN can experience routing conflicts between the VPN's own network configuration and Docker's bridge networking, particularly when both use overlapping private IP address ranges, which can manifest as build network failures that have nothing to do with the actual repository or registry being reached and everything to do with routing conflicts on the host itself:

docker network inspect bridge --format '{{.IPAM.Config}}'
{
  "bip": "172.30.0.1/16"
}

Reconfiguring Docker's default bridge subnet to avoid overlapping with the VPN's own address range, through the daemon's bip or default-address-pools configuration, resolves this specific class of conflict when it is the actual underlying cause.

Isolating build-specific versus host-wide network problems

A useful diagnostic distinction is testing the same connectivity check both directly on the host and inside an ordinary, already-running container (not during a build), which isolates whether a failure is specific to the build's particular network context or reflects a more general, host-wide networking issue:

curl -I https://example.com
docker run --rm alpine curl -I https://example.com

If the host succeeds but an ordinary running container fails, the problem is in Docker's general container networking configuration, not specific to builds; if both succeed but the build itself still fails, the issue is more likely specific to the build network context, isolation settings, or proxy configuration not being correctly passed through.

Common mistakes

  • Assuming a build's network connectivity is identical to the host's own, without accounting for the build's separate, potentially differently configured network context.
  • Passing proxy values only as --build-arg flags on the command line without the corresponding ARG declarations in the Dockerfile, leaving them with no actual effect inside the build.
  • Not considering DNS configuration differences between the host and the build's own network namespace, particularly for internal hostnames in corporate environments.
  • Overlooking VPN and Docker bridge network address range conflicts as a cause of build connectivity failures that have nothing to do with the actual target being reached.
  • Not isolating whether a connectivity failure is build-specific or a general container networking issue by testing the same check both on the host and inside an ordinary running container.

Build network failures are best diagnosed by treating the build's network context as genuinely distinct from both the host's networking and from whether the specific remote target is reachable in principle, working through DNS configuration, proxy pass-through, and potential VPN or bridge network conflicts systematically before assuming the remote repository or registry itself is the problem.