Skip to main content
RunBook Academy

Docker & ContainersVII · NetworkingNone driver

The none network driver — when to disconnect a container

Intermediate⏱ ~18 mindocker

What you'll learn

  • State exactly what `--network none` creates and what it omits
  • Identify workloads where removing the network removes a real risk
  • Predict the error a networked application produces under `none`
  • Recognise what `none` does not protect against

Prerequisites

None — start here.

Verified against Docker Engine 29.x · Docker Engine 28.x · Docker Compose 2.x · containerd 2.x · runc 1.2.x · BuildKit 0.20+ · Linux kernel 5.15+ · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · 2026-08-12

Not yet marked complete on this device.

--network none puts the container in its own network namespace and then puts nothing in it. There is no veth pair, no bridge attachment, no address, no route, and no embedded resolver. The only interface is lo.

Note what that is not: it is not “no network namespace”. The namespace exists and is empty, which is the strongest isolation the network stack can express — there is no interface for a compromised process to send anything out of, because none was created.

What it actually looks like

Read-only / Safeinside a none container
$ docker run --rm --network none alpine:3.20 sh -c '
ip -brief addr
echo "--- routes ---"
ip route || echo "(no routes)"
echo "--- resolv.conf ---"
cat /etc/resolv.conf'
lo               UNKNOWN  127.0.0.1/8 ::1/128
--- routes ---
(no routes)
--- resolv.conf ---
nameserver 192.0.2.53
search example.com

Illustrative output

When to use it

  • Batch jobs. A migration script, a data import, a report generator, a one-shot cleanup. The job does not need the network, so removing it removes a class of failure (DNS, MTU, routing, a flaky upstream) and a class of attack (outbound exfiltration, dependency fetch at runtime).
  • Untrusted computation. A converter that reads a file and writes a file. A user-supplied build step. A linter running someone else’s config. Anything where “what does this actually talk to?” is a question you would rather not have to answer.
  • Credential processing. A signer or decryptor reading a mounted secret and writing a result. With no interface, the material cannot leave over the network regardless of what the process does.
  • Reproducing a symptom. A deterministic “cannot reach anything” for testing timeout handling and retry logic — which is far easier to get right here than by breaking a real network.

What it looks like in practice

Read-only / Safea genuinely offline job
docker run --rm \
--network none \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=64m \
-v /srv/incoming:/in:ro \
-v /srv/processed:/out \
myorg/converter:1.4.2 \
--input /in/batch.csv --output /out/batch.parquet

In Compose:

services:
  migrator:
    image: myorg/migrator:1.0.0
    network_mode: none
    read_only: true
    volumes:
      - migration-data:/data

And the version that does not work, which is worth seeing on purpose:

# check-shell-blocks: allow-invalid
# This job needs the database. `none` makes that impossible.
docker run --rm --network none \
  myorg/migrator:1.0.0 pg_dump -h db.example.com -U app -d mydb
# pg_dump: error: could not translate host name "db.example.com" to address:
#          Temporary failure in name resolution

The lesson of that block is where the error appears. It is a DNS error, from the application, several seconds late — not a Docker error at start time. Docker will happily run a networked application with no network.

What it does NOT do

none removes the network. It removes nothing else, and it is regularly credited with more than it does:

  • It does not sandbox the filesystem. Every bind mount and every volume still works, with the permissions you gave. A -v /:/host under --network none is exactly as dangerous as it was.
  • It does not reduce capabilities. The default capability set is unchanged. Combine with --cap-drop=ALL if that is what you meant.
  • It does not prevent local IPC. Containers sharing a volume can still pass data through files. Containers sharing an IPC or PID namespace have richer channels than that.
  • It does not stop a process listening on lo. Anything that joins this network namespace later — docker exec, or another container started with --network container:<name> — reaches those sockets.
  • It does not survive docker network connect. Attaching a network to a running container gives it one, and nothing warns you that this was the point of the configuration.

Sanity check

  • docker exec "$CONTAINER" ip -brief addr shows lo and nothing else.
  • docker exec "$CONTAINER" ip route prints no default route.
  • The container’s net namespace inode differs from the host’s.
  • Nothing in your job’s runtime path fetches a dependency — you verified that by it working, not by reading the Dockerfile.

Knowledge check

Knowledge check · 5 questions

  1. Q1. What does `/etc/resolv.conf` contain inside a `--network none` container?

  2. Q2. A batch job running under `--network none` hangs for about ten seconds and then logs "Temporary failure in name resolution". What is happening?

  3. Q3. Which risks does `--network none` genuinely remove? Select all that apply.

  4. Q4. A `--network none` container has its own network namespace, containing only the loopback interface.

  5. Q5. Once a container is started with `--network none`, it cannot gain network access without being recreated.

Passing score: 75%. Answers are checked in this browser.