Nutek Security

We are here to help, we are here to protect, we are here to deliver.

Docker for Network Analysis: A Hands-On Tutorial

By Neosb

Published: 2026-02-07 09:00

Last Modified: 2026-02-07 09:00

Tags: dockernetwork analysistutorialmitmproxyrustsecuritydevopsprogramming

Categories: developmentnetworksecuritytutorialdocker

Docker for Network Analysis: A Hands-On Tutorial

Welcome to the world of containerized network analysis! In this tutorial, we'll explore how to use Docker to create isolated, reproducible environments for tinkering with networking tools. Forget cluttering your host machine with dependencies; we're going to build a self-contained lab for capturing, analyzing, and intercepting network traffic.

We will cover:

  • Setting up a custom Docker image with tcpdump, tshark, and mitmproxy.
  • Building a simple web server with the Rust programming language and running it in a container.
  • Creating a dedicated Docker network for our containers to communicate.
  • Capturing live traffic between containers with tcpdump.
  • Analyzing captured traffic with tshark, the command-line sibling of Wireshark.
  • Intercepting and inspecting HTTP requests with the powerful mitmproxy.

Prerequisites

Before we dive in, make sure you have Docker installed on your system. It's the only dependency you'll need on your host machine.

  • Docker: You can download it from the official website: Get Docker.

Basic familiarity with the command line will be helpful, but I'll guide you through every step.

Step 1: The Analyst's Dockerfile

Our first mission is to create a Docker image that will serve as our "analyst" machine. This container will hold all our networking tools.

Create a file named Dockerfile in a new directory for our project.

Language: dockerfile

# Use a recent Fedora base image
FROM fedora:latest

# Install essential networking tools
RUN dnf update -y && 
    dnf install -y 
    tcpdump 
    wireshark-cli 
    mitmproxy 
    curl 
    tmux 
    vim-enhanced 
    && dnf clean all

# Set a working directory
WORKDIR /app

# Drop into a shell by default
CMD ["/bin/bash"]

What's happening here?

  • FROM fedora:latest: We're starting with a fresh, up-to-date Fedora Linux distribution.
  • RUN dnf install -y ...: This command installs our toolkit:
    • tcpdump: The classic command-line packet sniffer.
    • wireshark-cli: This package includes tshark, the tool we'll use for deep packet inspection.
    • mitmproxy: Our interactive HTTPS proxy.
    • curl: An essential tool for making web requests.
    • tmux: A terminal multiplexer that will let us run multiple commands in one window.
    • vim-enhanced: A powerful text editor, in case we need to edit files inside the container.
  • WORKDIR /app: This sets a default directory for us to work in when we enter the container.
  • CMD ["/bin/bash"]: This tells Docker to start a bash shell when the container runs, so we can interact with it.

Now, let's build the image. Open your terminal in the directory where you saved the Dockerfile and run:

Language: bash

docker build -t analyst-toolbox .

This command builds an image from our Dockerfile and tags it with the name analyst-toolbox.

Step 2: Our Target - A Simple Rust Web App

What's a network analysis session without something to analyze? Let's create a simple "Hello, Docker!" web server in Rust. You don't need Rust installed on your host machine; we'll build it inside a Docker container.

Create a new directory for our Rust app, let's call it rust-webapp. Inside this directory, create the following three files.

rust-webapp/Cargo.toml This file defines our project and its dependencies.

Language: toml

[package]
name = "rust-webapp"
version = "0.1.0"
edition = "2021"

[dependencies]
actix-web = "4"

rust-webapp/src/main.rs This is our application's source code. It creates a web server that listens on port 8080 and responds to requests.

Language: rust

use actix_web::{get, App, HttpResponse, HttpServer, Responder};

#[get("/")]
async fn hello() -> impl Responder {
    HttpResponse::Ok().body("Hello, Docker!")
}

#[get("/secret")]
async fn secret() -> impl Responder {
    HttpResponse::Ok().body("You found the secret endpoint!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    println!("🚀 Server starting on http://0.0.0.0:8080");
    HttpServer::new(|| {
        App::new()
            .service(hello)
            .service(secret)
    })
    .bind(("0.0.0.0", 8080))?
    .run()
    .await
}

rust-webapp/Dockerfile This Dockerfile will compile and run our Rust application. It uses a multi-stage build, which is a best practice for creating small, secure production images.

Language: dockerfile

# Stage 1: Build the application
FROM rust:1 as builder
WORKDIR /usr/src/app
COPY . .
RUN cargo build --release

# Stage 2: Create the final, small image
FROM fedora:latest
WORKDIR /app
# Copy the compiled binary from the builder stage
COPY --from=builder /usr/src/app/target/release/rust-webapp .
# Expose the port the app runs on
EXPOSE 8080
# Run the application
CMD ["./rust-webapp"]

Now, from within the rust-webapp directory, build the app's image:

Language: bash

docker build -t rust-webapp .

Step 3: Setting Up the Network

To allow our containers to talk to each other easily by name, we'll create a dedicated virtual network.

Language: bash

docker network create a-net

Simple as that! The network is named a-net.

Scenario 1: Capturing Packets with tcpdump

Time for some action! Let's start our containers and watch the traffic.

  1. Start the web server: Run our Rust web app container and connect it to our network. We'll name it webserver so we can refer to it by that name.

    Language: bash

    docker run -d --rm --network a-net --name webserver rust-webapp
    
    • -d: Detached mode (runs in the background).
    • --rm: Automatically removes the container when it stops.
  2. Start the analyst toolbox: Now, start an interactive session in our analyst container, also connected to the same network.

    Language: bash

    docker run --rm -it --network a-net --name analyst analyst-toolbox
    
  3. Capture the traffic: Inside the analyst container's shell, start tcpdump. We'll tell it to listen on the eth0 interface (the default for Docker containers) and write the packets to a file named capture.pcap.

    Language: bash

    # Inside the 'analyst' container
    tcpdump -i eth0 -w capture.pcap
    

    tcpdump is now listening. It won't show any output until it captures packets.

  4. Generate some traffic: We need another terminal. Don't close the current one! You can open a new terminal window on your host machine. From there, execute a curl command inside our running analyst container.

    Language: bash

    # From a new terminal on your host machine
    docker exec analyst curl http://webserver:8080/
    docker exec analyst curl http://webserver:8080/secret
    

    docker exec runs a command inside an already running container. We're telling curl inside the analyst container to make a request to our webserver container on port 8080.

  5. Stop the capture: Go back to the terminal where tcpdump is running and press Ctrl+C to stop it. You'll see a summary of how many packets were captured. You now have a capture.pcap file in the /app directory of your analyst container.

Scenario 2: Analyzing with tshark

With our capture.pcap file ready, let's dissect it with tshark.

Still inside the analyst container, run the following commands:

  • Read the capture file: This gives a summary of each packet, similar to tcpdump.

    Language: bash

    # Inside the 'analyst' container
    tshark -r capture.pcap
    
  • Filter for HTTP traffic: This is where tshark shines. We can use display filters (the same ones as in Wireshark) to see only the traffic we care about.

    Language: bash

    # Inside the 'analyst' container
    tshark -r capture.pcap -Y "http"
    

    You'll see the GET / and GET /secret requests and the HTTP/1.1 200 OK responses.

  • Inspect a specific packet: Let's look at the full details of the first HTTP GET request.

    Language: bash

    # Inside the 'analyst' container
    tshark -r capture.pcap -Y "http.request.method == GET" -V -c 1
    
    • -V: Verbose output, showing all packet details.
    • -c 1: Only process the first matching packet.

You can now see the full TCP/IP and HTTP headers, revealing the inner workings of the request.

Scenario 3: Intercepting with mitmproxy

Packet sniffing is passive. What if we want to actively intercept and even modify traffic? That's a job for mitmproxy.

  1. Stop and remove old containers: First, let's clean up our previous session. Open a terminal on your host machine and run:

    Language: bash

    docker stop webserver analyst
    

    (The --rm flag we used earlier ensures they are removed after stopping).

  2. Start mitmproxy: We'll run mitmproxy in its own container. It's good practice to mount a local volume to ~/.mitmproxy inside the container to persist the generated certificates.

    Language: bash

    # From your host machine
    docker run -d --rm --network a-net --name proxy -p 8081:8080 mitmproxy/mitmproxy mitmproxy
    

    Note: We are using the official mitmproxy/mitmproxy image here. We map port 8081 on the host to 8080 in the container, which is mitmproxy's default port.

  3. Start the web server again: Same command as before.

    Language: bash

    # From your host machine
    docker run -d --rm --network a-net --name webserver rust-webapp
    
  4. Send traffic through the proxy: Now, let's run a one-off curl command in a temporary container, but this time we'll tell it to use our mitmproxy container as a proxy.

    Language: bash

    # From your host machine
    docker run --rm -it --network a-net analyst-toolbox 
    curl --proxy http://proxy:8080 http://webserver:8080/
    

    This command tells curl to route its request through http://proxy:8080.

  5. View the intercepted traffic: Attach to the running proxy container to see the mitmproxy interface.

    Language: bash

    # From your host machine
    docker attach proxy
    

You are now inside the interactive mitmproxy console! You'll see the GET http://webserver:8080/ request in the flow list. You can select it, view its details, and even replay or modify it. Press q to exit and go back.

HTTPS Traffic: Intercepting HTTPS is more complex as it requires the client to trust mitmproxy's certificate. For curl, you would use the --insecure flag or point it to mitmproxy's CA certificate. For browsers, you need to install the certificate, which you can typically fetch from http://mitm.it when your browser is configured to use the proxy.

Conclusion

You've successfully built a portable lab for network analysis! We've only scratched the surface, but you now have a solid foundation. You can package any tool into a Docker container and create complex network topologies to test, analyze, and secure applications.

From here, you could:

  • Write mitmproxy scripts in Python to automate modifications.
  • Explore more advanced tshark filters.
  • Containerize other tools like nmap for vulnerability scanning within your private Docker networks.

Happy hacking!