Skip to content
DevOps AI ToolKit
Newsletter

Kali Linux on Docker · Part 2 of 16

How to Run Kali Linux in Docker

Difficulty: Beginner ~12 min Part 2/16
Prerequisites: Basic Docker knowledge
Series progress2 / 16
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 pull downloads an image from a registry (Docker Hub by default) to your machine.
  • kalilinux/kali-rolling is the image reference: the kalilinux namespace (the official Kali team’s account) and the kali-rolling repository, 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 pull entirely. docker run pulls 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 from docker 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 with docker rm. For quick, disposable work, --rm keeps 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. -i and -t are 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 root inside 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 --privileged or 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:

  1. docker pull kalilinux/kali-rolling — pre-download the image.
  2. docker run --rm -it kalilinux/kali-rolling bash — drop into Kali.
  3. cat /etc/os-release — confirm you are in Kali.
  4. uname -a — note the kernel string. Open a second terminal, run uname -a on your host, and confirm they match.
  5. echo "test" > /root/scratch.txt then exit.
  6. 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 --rm for one run so the stopped container survives, then inspect it with docker logs <id> and docker inspect <id>. Once you have the answer, clean it up with docker rm <id> and put --rm back.

Where to Go Next

What You Learned

  • docker pull kalilinux/kali-rolling downloads the official Kali image, and docker run builds a fresh container from it.
  • Every docker run --rm -it ... bash flag has a job: --rm deletes the container on exit, -i keeps STDIN open, -t allocates a TTY, and bash overrides the default command to give you a shell.
  • cat /etc/os-release confirms the Kali userland while uname -a shows the host kernel — because containers share the host kernel rather than booting their own.
  • A --rm container is disposable: when you exit, 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.

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