Kali Linux on Docker · Part 7 of 16
Kali Linux and User-Defined Docker Networks
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 defaultbridge. This is a deliberate backward-compatibility choice.
Create a user-defined network
docker network create security-lab
docker network createprovisions a new network.security-labis the name you will attach containers to. With no other flags Docker uses thebridgedriver, 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 lslists all networks; you should seesecurity-labwith driverbridge.docker network inspect security-labprints 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
--rmremoves the container when you exit, keeping the environment disposable.-ikeeps STDIN open and-tallocates a TTY, so you get an interactive shell.--network security-labattaches this container to the network you just created instead of the default bridge.--name kaligives the container a stable name. On a user-defined network this name is its DNS hostname — other containers can reach it askali.kali-devops-toolboxis the image (the custom Kali image built earlier in this series; substitutekali-rollingif 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
--rmagain keeps it disposable.-druns it detached (in the background) so it stays up while you probe it from Kali.--network security-labputs it on the same network as Kali — this is the part that makes name resolution work.--name webis both the container name and its DNS name.nginxis 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 websends 3 ICMP echoes; Docker’s embedded DNS resolveswebto nginx’s current IP.curl -I http://webfetches just the HTTP response headers from nginx over port 80. A200 OK(orHTTP/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.
- Create the network:
docker network create security-lab. - Start the web service:
docker run --rm -d --network security-lab --name web nginx. - Start a stand-in API service (a second nginx is fine):
docker run --rm -d --network security-lab --name api nginx. - Launch Kali on the network:
docker run --rm -it --network security-lab --name kali kali-devops-toolbox. - From inside Kali, resolve each service:
getent hosts webandgetent hosts apishould each return an IP. - Confirm connectivity:
curl -I http://webandcurl -I http://api. - Clean up when done: exit Kali, then
docker stop web apianddocker 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}}' kaliand the same forweb. Both must listsecurity-lab. - A very common cause: one container was started without
--network security-lab, so it silently landed on the defaultbridge. On the default bridge there is no automatic name resolution — even if both containers were there,ping webwould still fail by name. - Fix: recreate the stray container with the correct
--network security-lab, or attach it live withdocker 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-laband confirm every container you expect appears in theContainerslist. - Fix: put them on the same network (
docker network connect security-lab <container>), or start them together with the same--networkflag.
Symptom: name resolves but the connection is refused.
DNS is fine; the target service is not listening or not ready.
- Diagnose:
getent hosts webreturns an IP (DNS works), butcurlgivesConnection refused. Check the target withdocker logs weband confirm it is actually serving on the port you are hitting.
🔎 Troubleshooting Tip — Split the problem in two.
getent hosts web(ornslookup web) tests name resolution only;curl -I http://webtests reachability + the service. Knowing which half fails tells you whether to fix the network wiring or the service itself.
Where to go next
- New to Docker networking concepts? Start with Docker networking for Kali.
- Ready to define this whole lab in one file? See building a Docker Compose security lab — Compose creates a user-defined network automatically.
- When name resolution misbehaves, dig deeper in DNS troubleshooting from Kali.
- Once services resolve by name, map them out with Nmap service discovery.
What You Learned
- How to create an isolated user-defined network with
docker network createand attach containers to it with--network. - Why user-defined bridge networks provide automatic service-name resolution via Docker’s embedded DNS, while the default
bridgedoes 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
--networkflag 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.
Recommended Reading
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