Kali Linux on Docker · Part 2 of 16
How to Run Kali Linux in Docker
Series curriculum (16 lessons)
The fastest way to get a Kali environment in front of you is not to install anything — it is to pull one image and drop straight into a shell. In this lesson you will start Kali Linux inside a Docker container, learn what every flag in the command actually does, verify where you are, and see exactly what happens when a disposable container exits.
The Core Idea: Kali as a Disposable Shell
A container is a lightweight, isolated process built from an image. The official kalilinux/kali-rolling image gives you a minimal Kali userland — the same Debian-based filesystem, package manager, and shell you would get from a full install — but it starts in seconds and disappears just as fast. For a DevOps engineer this is the perfect shape for a troubleshooting environment: reproducible, throwaway, and identical on your laptop, a jump host, or a CI runner.
🛠️ DevOps Perspective — A container image is a fixed, versioned artifact. When you and a teammate both run
kalilinux/kali-rolling, you are running the same filesystem — no “works on my machine” drift. That reproducibility is why containers beat hand-installed tooling for repeatable infrastructure checks.
Step 1: Pull the Image
Before you can run Kali, Docker needs a local copy of the image. Pull it explicitly so you can see the download happen:
docker pull kalilinux/kali-rolling
docker pulldownloads an image from a registry (Docker Hub by default) to your machine.kalilinux/kali-rollingis the image reference: thekalilinuxnamespace (the official Kali team’s account) and thekali-rollingrepository, which tracks Kali’s rolling release. Because no tag is specified, Docker uses:latest.
You will see Docker pull several layers. Each layer is a cached, reusable slice of the filesystem; the next time you pull, unchanged layers are skipped.
💡 Note — You can skip
docker pullentirely.docker runpulls the image automatically the first time if it is not already present locally. Pulling first just separates the “download” step from the “run” step so it is easier to see what is happening.
Step 2: Run an Interactive Container
Now launch a container and land inside a Kali shell:
docker run --rm -it kalilinux/kali-rolling bash
This one line has several parts. Understanding each flag is the whole point of this lesson:
docker run— creates a new container from an image and starts it. (This is different fromdocker start, which resumes an existing stopped container.)--rm— automatically removes the container when it exits. Without this, every run leaves a stopped container behind that you would have to clean up later withdocker rm. For quick, disposable work,--rmkeeps your machine tidy.-i(--interactive) — keeps STDIN open so you can type into the container. Without it, the shell would start and immediately have no input to read.-t(--tty) — allocates a pseudo-TTY, giving you a proper terminal with a prompt, line editing, and colors.-iand-tare almost always used together and are commonly combined as-it.kalilinux/kali-rolling— the image to build the container from.bash— the command to run inside the container, overriding the image’s default. Here it launches an interactive Bash shell so you get a prompt instead of the container running a fixed command and exiting.
Once it starts, your prompt changes to something like root@a1b2c3d4e5f6:/#. That hostname is the container’s short ID, and you are now root inside the container.
🧪 Try It — Run the command above. When your prompt changes to
root@<id>:/#, you are inside Kali. Everything you type from here runs in the container, not on your host.
Step 3: Confirm Where You Are
It is a good habit to verify your environment instead of assuming it. Two commands tell you almost everything:
cat /etc/os-release
cat prints a file to the terminal. /etc/os-release is the standard file describing the running distribution. Inside the container you will see lines like ID=kali and NAME="Kali GNU/Linux" — confirmation that the userland really is Kali, not your host OS.
uname -a
uname reports kernel and system information; -a means “all”. Look closely at the kernel version and build string it prints — then compare it to the same command run on your host.
Why the Kernel Looks Like the Host
Here is the part that surprises people new to containers: containers share the host kernel. A container is not a virtual machine. There is no separate guest kernel booting inside it — the container is just isolated processes running directly on your host’s Linux kernel, using namespaces and cgroups for separation. The filesystem and tools are Kali’s; the kernel is your host’s.
So uname -a inside the Kali container shows your host kernel version, not a “Kali kernel.” If your host is Ubuntu with kernel 6.8.0, that is exactly what uname reports inside the Kali container. /etc/os-release says Kali (the userland) while uname says your host kernel (the shared core). Both are correct — they are describing two different layers.
🏭 Why This Matters in Production — Because the kernel is shared, a container cannot use kernel features your host does not have, and kernel-level tuning (sysctls, modules, capabilities) is governed by the host. This is also why containers are lighter than VMs — no second kernel to boot — and why kernel-level isolation between containers is weaker than between VMs. Keep hosts patched: a kernel vulnerability is a shared surface.
🔐 Security Note — You are
rootinside the container by default. That root maps to a constrained user on the host, but it is still powerful: root-in-container plus a risky flag (like--privilegedor a host mount) can reach the host. Run as an unprivileged user and add only the specific capabilities you need — later lessons cover this. Only inspect or test systems you own or have explicit permission to assess.
Step 4: Exit and Watch the Container Disappear
When you are done, leave the shell:
exit
exit ends the Bash session. Since Bash was the container’s main (PID 1) process, the container stops the instant that shell exits. And because you started it with --rm, Docker immediately removes it. Verify it is gone:
docker ps -a
docker ps lists running containers; -a includes stopped ones too. Your disposable Kali container is not in the list — there is nothing left to clean up.
What Happened to Anything You Created
Try the full cycle to feel the consequence. Start a container, create a file, exit, then start a fresh one:
docker run --rm -it kalilinux/kali-rolling bash
# inside the container:
echo "scan results" > /root/notes.txt
cat /root/notes.txt # prints: scan results
exit
# now start a brand-new container:
docker run --rm -it kalilinux/kali-rolling bash
cat /root/notes.txt # No such file or directory
The file is gone. A container’s writable layer lives and dies with that specific container. Because --rm deleted the first container, /root/notes.txt went with it — and even without --rm, a new container starts from the pristine image with no memory of the old one. This is the intended behavior of a disposable environment: nothing persists unless you deliberately make it persist.
🛠️ DevOps Perspective — “Disposable by default” is a feature, not a bug. It guarantees every run starts clean and reproducible. But when you do need to keep captured packets, scan output, or reports, you must store them outside the container’s writable layer using a volume or bind mount — that is exactly what the volumes and persistence lesson covers.
Try It Yourself
Practice the whole loop on your own machine:
docker pull kalilinux/kali-rolling— pre-download the image.docker run --rm -it kalilinux/kali-rolling bash— drop into Kali.cat /etc/os-release— confirm you are in Kali.uname -a— note the kernel string. Open a second terminal, rununame -aon your host, and confirm they match.echo "test" > /root/scratch.txtthenexit.- Start a fresh container and
cat /root/scratch.txt— confirm it is gone.
You now understand the create → work → exit → destroy lifecycle of a disposable Kali container.
Common Problems
Think in terms of expected state vs. observed state: you expect a Kali shell prompt; if you get something else, the symptom usually points straight at the cause.
Symptom: Unable to find image ... / repository does not exist or may require 'docker login'
The image name is wrong or unreachable. Check the spelling — it is kalilinux/kali-rolling (one word kalilinux, then /kali-rolling), not kali/... or kali-linux/.... Then confirm the image exists locally with docker images | grep kali.
Symptom: pull fails with a timeout, TLS, or net/http error
This is networking, not Kali. Confirm the Docker daemon is running (docker info), check that you can reach the internet, and if you are behind a corporate proxy, configure Docker’s proxy settings. Retry the pull — partial layer downloads resume from cache.
Symptom: the container exits immediately and you never get a prompt
Almost always a missing -it. Without -i there is no STDIN and without -t there is no terminal, so bash has nothing to attach to and exits at once. Re-run with docker run --rm -it kalilinux/kali-rolling bash. Also make sure bash is the last argument — anything after the image name is treated as the command to run.
Symptom: permission denied while trying to connect to the Docker daemon socket
Your user is not in the docker group. Either add it (sudo usermod -aG docker $USER, then log out and back in) or prefix commands with sudo.
🔎 Troubleshooting Tip — When a container behaves unexpectedly, drop the
--rmfor one run so the stopped container survives, then inspect it withdocker logs <id>anddocker inspect <id>. Once you have the answer, clean it up withdocker rm <id>and put--rmback.
Where to Go Next
- Fill your container with real tooling in Installing Kali Tools in Docker.
- Stop losing your work by adding Volumes and Persistence.
- Level up your container fundamentals in the Docker Academy.
What You Learned
docker pull kalilinux/kali-rollingdownloads the official Kali image, anddocker runbuilds a fresh container from it.- Every
docker run --rm -it ... bashflag has a job:--rmdeletes the container on exit,-ikeeps STDIN open,-tallocates a TTY, andbashoverrides the default command to give you a shell. cat /etc/os-releaseconfirms the Kali userland whileuname -ashows the host kernel — because containers share the host kernel rather than booting their own.- A
--rmcontainer is disposable: when youexit, it and everything written inside it are gone, which motivates using volumes for anything worth keeping. - Most “it won’t start” problems trace back to a wrong image name, a network/daemon issue, or a missing
-it.
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