BuildKit’s --network=host mode lets your build containers directly access your host machine’s network interfaces, bypassing the usual container network isolation.
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello from host network!")
})
fmt.Println("Starting server on :8080")
http.ListenAndServe(":8080", nil)
}
Let’s say you have this Go application. Normally, if you build it in a container and try to run it, it’s confined to its own network namespace. If it needs to talk to a service running directly on your laptop (not in another container), it won’t be able to find it.
Here’s how you’d build this app without host networking:
# Build the Dockerfile (assuming a simple Dockerfile that copies and builds the Go app)
docker build -t my-go-app .
# Run it - this will likely fail if it tries to access a host-local service
docker run --rm my-go-app
Now, let’s see the difference with --network=host during the build phase. This is particularly useful when your build process needs to interact with services already running on your development machine, like a local database, a local registry, or a local API.
# Build the Dockerfile using host network mode for the build steps
docker build --network=host -t my-go-app-host-net .
In this scenario, the build process itself (the RUN commands within your Dockerfile) effectively becomes part of your host’s network. If a RUN command tries to curl http://localhost:5432 (for a local PostgreSQL instance), it will succeed because localhost now refers to your actual machine’s network stack.
The mental model here is that the build container’s network interfaces are merged with your host’s. It’s not that the container gets host networking; it’s that for the duration of the build command, the build environment is the host network. This means your build steps can:
- Access localhost services: Connect to databases, APIs, or other services running directly on your machine without complex port forwarding or custom network configurations for the build environment.
- Use host network tools: Tools within the build environment can directly ping, traceroute, or otherwise interact with the host’s network infrastructure as if they were native processes.
- Simplify local development workflows: If your build involves fetching artifacts from a local development server or interacting with a local Kubernetes cluster’s API server,
--network=hostmakes this seamless.
The primary levers you control are the RUN commands within your Dockerfile. Any command executed as a RUN instruction will inherit this host networking. The docker build command itself needs to be invoked with --network=host.
Consider a Dockerfile like this:
FROM golang:1.21-alpine
WORKDIR /app
COPY . .
RUN go build -o myapp
# This RUN command will attempt to connect to a service assumed to be on the host
RUN echo "Pinging local service..." && \
curl -s --fail http://localhost:8080/health || exit 1
When you build this with docker build --network=host -t myapp ., the curl command has direct access to localhost:8080 on your host machine.
The one thing most people don’t know is that --network=host bypasses all network isolation for the build process, including firewall rules that might apply to containers but not directly to host processes. This means if your host firewall is configured to only allow specific ports for external access, the build process running with --network=host will be subject to those same host-level restrictions. It’s less about container networking and more about the build process directly using your host’s network stack.
After successfully building your image, the next challenge is often managing the network configuration of the runtime container, which is typically isolated by default unless you explicitly configure it.