Skip to content
DevOps AI ToolKit
Newsletter

Kali Linux on Docker · Part 7 of 16

Kali Linux and User-Defined Docker Networks

Difficulty: Intermediate ~16 min Part 7/16
Prerequisites: Kali Linux fundamentalsBasic Docker knowledge
Series progress7 / 16
Series curriculum (16 lessons)

When you build a security lab you want your Kali container to talk to the services you are testing the same way a real client would — by name, not by chasing IP addresses that change every time you recreate a container. A user-defined Docker network gives you exactly that: an isolated segment with built-in DNS, so kali can simply ping web and it works.

This lesson shows you how to create your own network, attach Kali and a couple of lab services to it, and understand why this beats Docker’s default bridge for reproducible labs.

Why not just use the default network?

Every container you start without a --network flag lands on Docker’s built-in bridge network. It works, containers get IP addresses, and they can reach each other over those IPs. But the default bridge has one big limitation for lab work: no automatic service-name resolution. Container A cannot resolve container B by name — you are stuck passing raw IPs around, and those IPs change whenever a container is recreated.

A user-defined bridge network fixes this. Docker runs an embedded DNS server (reachable inside containers at 127.0.0.11) that automatically resolves container names and network aliases to their current IPs. Attach two containers to the same user-defined network and each can reach the other by name — no config, no /etc/hosts editing, no IP bookkeeping.

💡 Note — The difference is not the bridge driver (both use bridge); it is that Docker only wires up automatic DNS name resolution on networks you create, not on the legacy default bridge. This is a deliberate backward-compatibility choice.

Create a user-defined network

docker network create security-lab
  • docker network create provisions a new network.
  • security-lab is the name you will attach containers to. With no other flags Docker uses the bridge driver, which is what you want for containers on a single host.

Verify it exists and inspect it:

docker network ls
docker network inspect security-lab
  • docker network ls lists all networks; you should see security-lab with driver bridge.
  • docker network inspect security-lab prints the subnet, gateway, and (once containers join) the list of connected containers with their IPs. This is your first troubleshooting tool when name resolution misbehaves.

Run Kali on the network

docker run --rm -it \
  --network security-lab \
  --name kali \
  kali-devops-toolbox
  • --rm removes the container when you exit, keeping the environment disposable.
  • -i keeps STDIN open and -t allocates a TTY, so you get an interactive shell.
  • --network security-lab attaches this container to the network you just created instead of the default bridge.
  • --name kali gives the container a stable name. On a user-defined network this name is its DNS hostname — other containers can reach it as kali.
  • kali-devops-toolbox is the image (the custom Kali image built earlier in this series; substitute kali-rolling if you have not built it yet).

At this point Kali is on the network but alone. It has nothing to talk to yet.

Add a lab service to talk to

Open a second terminal and start a benign web service on the same network:

docker run --rm -d \
  --network security-lab \
  --name web \
  nginx
  • --rm again keeps it disposable.
  • -d runs it detached (in the background) so it stays up while you probe it from Kali.
  • --network security-lab puts it on the same network as Kali — this is the part that makes name resolution work.
  • --name web is both the container name and its DNS name.
  • nginx is a standard, safe HTTP server that makes an ideal lab target.

Now back in the Kali shell, reach the service by name:

ping -c 3 web
curl -I http://web
  • ping -c 3 web sends 3 ICMP echoes; Docker’s embedded DNS resolves web to nginx’s current IP.
  • curl -I http://web fetches just the HTTP response headers from nginx over port 80. A 200 OK (or HTTP/1.1 200) confirms name resolution and HTTP connectivity end to end.

You never looked up an IP. That is the whole point.

🛠️ DevOps Perspective — Name-based service discovery is how real infrastructure works: Kubernetes Services, Consul, and cloud load balancers all hand you a stable DNS name, not an IP. Practicing against Docker’s built-in DNS on a user-defined network builds the exact mental model you need for production service meshes — and lets you rebuild the whole lab from scratch in seconds without editing a single hardcoded address.

The lab topology

As you grow the lab, add more services (an api backend, a database, etc.) to the same network. Everything on security-lab can find everything else by name:

security-lab

├── kali

├── web

└── api

kali can resolve and reach web and api; web and api can reach each other. Anything not attached to security-lab is invisible to them — that isolation is a feature, not a bug.

🔐 Security Note — A user-defined network is an isolation boundary, but it is not a hardened firewall. Containers on the same network trust each other freely. Keep deliberately vulnerable practice targets on their own throwaway network, never one shared with anything real, and only scan, inspect, or test systems you own or have explicit permission to assess.

Try It Yourself

🧪 Try It — Build the three-node topology above and prove name resolution works.

  1. Create the network: docker network create security-lab.
  2. Start the web service: docker run --rm -d --network security-lab --name web nginx.
  3. Start a stand-in API service (a second nginx is fine): docker run --rm -d --network security-lab --name api nginx.
  4. Launch Kali on the network: docker run --rm -it --network security-lab --name kali kali-devops-toolbox.
  5. From inside Kali, resolve each service: getent hosts web and getent hosts api should each return an IP.
  6. Confirm connectivity: curl -I http://web and curl -I http://api.
  7. Clean up when done: exit Kali, then docker stop web api and docker network rm security-lab.

Expected state: every name resolves, both curl calls return 200 OK. If observed state differs, work through Common Problems below.

Common Problems

Symptom: ping: web: Name or service not known (or curl: Could not resolve host: web).

The name is not resolving, which almost always means the two containers are not on the same user-defined network.

  • Diagnose: docker inspect -f '{{json .NetworkSettings.Networks}}' kali and the same for web. Both must list security-lab.
  • A very common cause: one container was started without --network security-lab, so it silently landed on the default bridge. On the default bridge there is no automatic name resolution — even if both containers were there, ping web would still fail by name.
  • Fix: recreate the stray container with the correct --network security-lab, or attach it live with docker network connect security-lab web.

Symptom: containers are up but simply cannot reach each other at all.

They are probably on different networks. Containers on separate Docker networks are isolated by design and cannot talk, by name or by IP.

  • Diagnose: docker network inspect security-lab and confirm every container you expect appears in the Containers list.
  • Fix: put them on the same network (docker network connect security-lab <container>), or start them together with the same --network flag.

Symptom: name resolves but the connection is refused.

DNS is fine; the target service is not listening or not ready.

  • Diagnose: getent hosts web returns an IP (DNS works), but curl gives Connection refused. Check the target with docker logs web and confirm it is actually serving on the port you are hitting.

🔎 Troubleshooting Tip — Split the problem in two. getent hosts web (or nslookup web) tests name resolution only; curl -I http://web tests reachability + the service. Knowing which half fails tells you whether to fix the network wiring or the service itself.

Where to go next

What You Learned

  • How to create an isolated user-defined network with docker network create and attach containers to it with --network.
  • Why user-defined bridge networks provide automatic service-name resolution via Docker’s embedded DNS, while the default bridge does not.
  • How to attach Kali plus lab services (web, api) to one network so Kali can reach them by name — no IP bookkeeping.
  • That separate Docker networks are isolated: containers on different networks cannot communicate, and a forgotten --network flag is the most common reason lab name resolution fails.
  • How to split troubleshooting into name resolution (getent hosts) versus reachability (curl) to pinpoint the failing layer.

Affiliate Disclosure: Some links on this page are affiliate links. If you purchase through one of these links, DevOps AI Toolkit may earn a commission at no additional cost to you. See our affiliate disclosure.

← Back to Kali Linux on Docker Back to Kali Linux

Related on DevOps AI Toolkit