None Network #
Among all the network drivers Docker offers, none is the simplest conceptually and the least often discussed seriously. When a container runs with --network none, it has no network interface at all — not bridge, not host, not overlay. Only one interface exists: lo (loopback). The container is truly offline.
At first glance, this sounds useless. Why run a container that can’t talk to anyone? But that’s exactly where its power lies: there are many workloads that simply must not talk to the outside. Batch jobs processing local files, security sandboxes running untrusted code, even containers deliberately isolated for auditing — all are ideal use cases for the none network.
This article covers none networking in depth: how it works at the OS level, when to use it, when not to use it, and how to combine it with other patterns for extra isolation. By the end, you’ll understand why this seemingly “useless” mode is actually one of Docker’s sharpest security tools.
What Is the None Network? #
None networking is a mode where Docker doesn’t create any network interface for the container. No veth, no bridge, no external IP address. The container only has the lo (loopback) interface that exists on every Unix-like OS.
flowchart TB
subgraph HOST["Docker Host"]
H_NET[Host Network]
end
subgraph CT["Container (none network)"]
LO[lo: 127.0.0.1]
end
HOST -. X no link .-> CTMain characteristics:
- No
eth0, no IP address from DHCP or IPAM. - No internet or host network access.
- No communication with other containers, except via filesystems or stdin/stdout.
- Only internal communication via
127.0.0.1(loopback) inside the container itself. - No port mapping — impossible because there’s no interface.
- Maximum network isolation — network attack surface = 0.
Loopback still exists:localhostinside the container points to the container itself, not the host or other containers. This is useful for applications listening on127.0.0.1that should only be accessed internally (e.g. an admin UI reverse-proxied via a UNIX socket).
How It Works at the OS Level #
To understand none networking, you need to understand two things: how Docker normally creates interfaces, and what it doesn’t do in none mode.
When a Normal Container Runs (Bridge) #
flowchart LR
H_BR[bridge: docker0<br/>172.17.0.1] -->|veth| C_ETH[eth0: 172.17.0.2]
H_BR -->|iptables NAT| H_ETH[host eth0]Docker creates:
- A veth pair — the virtual cable between container and host.
- A bridge interface — the virtual switch connecting many containers.
- An IP address from the bridge subnet.
- A default route through the bridge gateway.
- iptables rules for outbound NAT and inbound DNAT.
When a Container Is on the None Network #
flowchart LR
C_LO[lo: 127.0.0.1]
C_NO[eth0: DOESN'T EXIST]
ROUTE[Default route: DOESN'T EXIST]Docker creates very little:
- Loopback
lo— always present, only127.0.0.1. - No veth — no cable to the host.
- No eth0 — no external interface.
- No default route — no way out.
- No iptables rules for this container — nothing to NAT.
The result: the container is a totally isolated process at the network level. It still has its own namespaces (PID, mount, UTS, IPC), but its network namespace contains only lo.
How to Run a Container with None Networking #
# CLI way
docker run -d --network none --name isolated alpine sleep 3600
# Check the interfaces inside the container
docker exec isolated ip addr show
Output:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
Only lo. No eth0, no other IPs.
Check routing:
docker exec isolated ip route
Output:
# (empty - no routes, including no default)
Check connectivity:
docker exec isolated ping -c 1 8.8.8.8
# ping: connect: Network is unreachable
docker exec isolated wget -qO- http://google.com
# wget: unable to resolve host address 'google.com'
# (even DNS fails because there's no resolver)
There’s still no DNS resolver: Even Docker’s internal DNS (127.0.0.11) is inactive on none networks. The container is completely cut off from all DNS systems. Every dependency must already exist inside the image.Docker Compose with None Networking #
version: "3.9"
services:
batch-processor:
image: my-batch:v1
network_mode: none
volumes:
- ./input:/data/input:ro
- ./output:/data/output:rw
This container:
- Reads files from
/data/input(volume). - Processes files locally.
- Writes results to
/data/output(volume). - Never talks to the internet or other containers.
Fits offline ETL, image processing, transcoding, or any workload working purely on local data.
Use Case: Batch Jobs and Offline Processing #
Batch jobs are the clearest use case. If a process only needs file input/output and no network, the none network provides:
- Security — no accidental data egress path.
- Performance — no networking overhead; the container focuses on CPU/disk.
- Predictability — deterministic batch jobs, no “internet went down” variable.
Concrete examples:
# Image processing pipeline
docker run --rm --network none \
-v $PWD/photos:/photos:ro \
-v $PWD/thumbs:/thumbs:rw \
image-processor \
--input /photos --output /thumbs --size 256x256
# Video transcoding
docker run --rm --network none \
-v $PWD/videos:/videos:rw \
jrottenberg/ffmpeg \
-i /videos/input.mov -c:v libx264 /videos/output.mp4
# CSV to Parquet
docker run --rm --network none \
-v $PWD/data:/data:rw \
csv-to-parquet:latest \
--input /data/raw.csv --output /data/processed.parquet
A general principle: if your batch job works entirely on the filesystem, enable --network none. This removes one class of problems (network flakiness) and one attack vector (network exfiltration).Use Case: Security Sandboxes for Untrusted Code #
One of the most valuable use cases: running untrusted code with minimal risk. Code injections, third-party scripts, ML models from unclear sources — all can be put into a none-network container.
# Run a script from an untrusted user
docker run --rm --network none \
--read-only \
--tmpfs /tmp:size=10m \
--cpus=1 --memory=256m \
--user 1000:1000 \
python:3.12-slim \
python /mnt/user-script.py
The combination of none network + read-only + tmpfs + resource limits + non-root is Docker’s strongest sandbox pattern. It isn’t perfect (kernel exploit risk remains), but for application-level threats it’s very effective.
Defense in Depth #
flowchart TB
A[Untrusted Code] --> B[Container]
B --> C[none network]
B --> D[read-only fs]
B --> E[--user 1000]
B --> F[--memory 256m]
B --> G[--cpus 1]
B --> H[--cap-drop ALL]
style C fill:#dfd
style D fill:#dfd
style E fill:#dfd
style F fill:#dfd
style G fill:#dfd
style H fill:#dfdEach layer adds isolation. The none network is the layer that closes network-based vectors: data exfiltration, command & control callbacks, internal service scanning. Without a network, many modern attacks fail immediately.
Use Case: CI/CD Build Steps That Don’t Need the Network #
CI/CD often runs build steps that shouldn’t need the internet. The image is already pulled, dependencies already cached. A build step that downloads again is a code smell — and a security risk.
# GitHub Actions - build step without network
jobs:
build:
runs-on: ubuntu-latest
container:
image: my-build-image:latest
options: --network none
steps:
- uses: actions/checkout@v4
- run: make build
- run: make test
With --network none, the build step is guaranteed deterministic and safe: nothing downloads extra binaries, nothing fetches uncached dependencies. If the build succeeds, its dependability is assured.
A bug commonly exposed bynonenetworking: applications that silently fetch configuration from the internet at startup. When--network noneis enabled, the app crashes because it can’t reach the endpoint. That’s a sign of fragile architecture — configuration should be embedded in the image, not fetched at runtime.
Use Case: Applications with Offline Sidecars #
An interesting pattern: offline sidecar containers running in none mode for housekeeping.
version: "3.9"
services:
app:
image: my-app
networks: [app-net]
audit-log:
image: log-rotator
network_mode: none
volumes:
- app-logs:/var/log/app:ro
- archive:/archive:rw
# Rotate log files without a network
audit-log reads logs from a volume, compresses them, and writes an archive. It doesn’t need to talk to anyone. With the none network, it’s guaranteed not to suddenly upload logs outside.
Comparison with Bridge Networking #
| Aspect | none | bridge |
|---|---|---|
| IP Address | None | Automatic |
| Internet Access | No | Yes (via NAT) |
| Inter-Container Communication | No | Yes (same bridge) |
| Internal DNS | No | Yes (user-defined) |
| Port Mapping | Not possible | Yes (-p) |
| veth pair | None | Yes |
| iptables rules | Minimal (or none) | Complete |
| Use case | Sandboxes, batch, security | Multi-container apps |
| Network overhead | Zero | Standard |
Don’t equatenonewith “no network at all”. Loopback127.0.0.1still exists, and applications inside the container can still listen on a loopback port (e.g. an admin UI). What’s lost is the ability to exit to other networks.127.0.0.1is the container itself, not the host or other containers.
When None Networking Should NOT Be Used #
1. Web / API Server Applications #
Web servers need to receive requests and responses. No network = no requests arrive.
# ✗ Anti-pattern: web server without a network
docker run --network none -p 80:80 nginx
# The container runs but nobody can connect
# -p is ignored because there's no interface
2. Databases with Clients in Other Containers #
A database on the none network = clients can’t connect. Databases must be on the same bridge network as their clients.
3. Services Needing Updates / Image Pulls #
Containers that download something at runtime (apt-get update, pip install, npm install) need a network. Build dependencies must already be in the image.
4. Network-Based Health Checks #
Network health checks (HTTP endpoints, TCP connects) won’t work on the none network. Use process- or file-based health checks.
services:
worker:
image: my-worker
network_mode: none
healthcheck:
test: ["CMD", "test", "-f", "/tmp/worker.alive"]
interval: 30s
Combining with Manual Networking (Advanced) #
For rare cases, you can add a network manually to a none container after it’s running. This gives you full control over when the container may talk to the network.
# 1. Create a container with none networking
docker run -d --network none --name audit alpine sleep 3600
# 2. When communication is needed, connect to a network (if host policy allows)
docker network connect bridge audit
# 3. Do the communication
docker exec audit ping -c 1 172.17.0.3
# 4. Disconnect again
docker network disconnect bridge audit
This is rarely used, but useful for:
- Emergency debugging — open the network briefly, inspect, close it again.
- Conditional connectivity — containers normally offline, but enable the network for periodic sync.
- Privileged operations — admins can attach a network during troubleshooting.
Be careful: giving anonecontainer network access in production must go through very strict controls. This is one of the patterns attackers often use to escape a sandbox. Audit everydocker network connectto a container that was originallynone.
None Network Best Practices #
✓ USE the none network if:
✓ Batch jobs / offline processing
✓ Sandboxes for untrusted code
✓ Already-deterministic CI/CD build steps
✓ Sidecar housekeeping (log rotation, metric aggregation)
✓ Fault-tolerance testing (check the app still runs without a network)
✓ Audit / compliance requirements (no network access)
✗ DON'T use the none network if:
✗ Web/API/worker apps that must receive requests
✗ Databases with clients
✗ Services needing to download dependencies
✗ Network-based health checks
✗ Containers needing sync to external systems
Common Anti-Patterns #
1. Using None for Apps That Need a Network #
# ✗ Anti-pattern: web server on the none network
docker run -d --network none -p 80:80 nginx
# The container crashes; host port 80 receives nothing
# ✓ Solution: bridge + port mapping
docker run -d --network app-net -p 80:80 nginx
2. Forgetting That DNS Is Also Gone #
# ✗ Anti-pattern: an app fetching config from the internet
docker run --network none my-app
# The app crashes because it can't resolve "config.example.com"
# ✓ Solution: embed the config in the image, or use bridge
3. Assuming -p Works on the None Network
#
# ✗ Anti-pattern: using -p without a network
docker run -d --network none -p 8080:80 my-app
# -p is ignored. The container can't be reached.
# ✓ Solution: use bridge with -p, or host networking
None Networking for Compliance and Regulatory Requirements #
Some industries have regulations that explicitly forbid containers having network access. Finance, healthcare, and government have requirements that certain workloads must never talk to external systems at all.
# Example: HIPAA-compliant processing pod
apiVersion: v1
kind: Pod
metadata:
name: phi-processor
spec:
containers:
- name: processor
image: phi-processor:v1
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
resources:
limits:
memory: "512Mi"
cpu: "500m"
volumeMounts:
- name: data
mountPath: /data
readOnly: true
- name: output
mountPath: /output
volumes:
- name: data
persistentVolumeClaim:
claimName: phi-input
- name: output
persistentVolumeClaim:
claimName: phi-output
On Kubernetes, you can enforce none-style networking with a NetworkPolicy denying all egress, or with an empty podSelector in the policy. The result: containers can only communicate via the filesystem, per regulation.
Compliance pattern: For workloads processing sensitive data (PHI, PII, financial data), combine thenonenetwork with aread-onlyfilesystem,runAsNonRoot, and audit logging. This provides a clear audit trail: data enters via a volume, gets processed, exits via a volume — it never leaves the pod.
Summary #
- None networking = a container with no network interface at all (except loopback). No eth0, no IP, no default route, no iptables rules.
- The strongest network isolation among all network modes. Network attack surface = 0.
- Good for: offline batch jobs, untrusted-code sandboxes, deterministic CI/CD build steps, sidecar housekeeping, audit/compliance.
- Bad for: web servers, databases with clients, services downloading dependencies, network-based health checks.
- The DNS resolver is also gone —
127.0.0.11(Docker’s internal DNS) is inactive. All dependencies must be embedded in the image.- The security combination:
none network + --read-only + --user non-root + --cap-drop ALL + resource limits= Docker’s strongest sandbox.- Unexpected usefulness: fault-tolerance testing — run the app with
noneand see what breaks. This exposes hidden network dependencies that are often the source of bugs.- Networks can be added manually via
docker network connect, but this is an advanced pattern that must be strictly audited.- Anti-patterns: web servers on
none, forgetting DNS is also gone, using-ponnone(ignored).- A general principle: if a workload doesn’t need a network, disable the network. The default should be “least privilege” — open only what’s needed.