Building a Recon Toolkit with Docker

A humpback whale with green numbers and characters floating in the background.

With the rise in popularity of bug bounty hunting, there’s been a lot of great tools developed. ProjectDiscovery‘s suite of tools and contributions made by Tomnomnom certainly come to mind.

With the amount of tools, however, comes the complexity of managing them: keeping them up to date, making sure dependencies are installed, keeping your bounty tools separate from personal projects, and managing the clutter that comes with having tons of tools.

The solution: Docker. Docker is a platform for running and managing containers. You can think of a container as a light-weight VM. That light-weight comes from sharing resources with your host machine instead of virtualizing lower-level functions (the kernel for example).

With Docker, you can package all of your bug bounty tools inside of a container, which allows for:

  • Portability – your tools are guaranteed to run anywhere (so long as docker is installed).
  • Isolation – everything lives inside of the container. You don’t have to install/maintain unnecessary bloat on your host machine to get all of your tools working.
  • Easy cleanup – once the container is removed, the tools and their dependencies go with it. Getting everything up and running again is as easy as re-building/pulling the container.
  • Easy updates – If you do your setup right, updating all of your tools is as easy as removing then rebuilding the container. You don’t have to worry about anything else!

I’m sure I sold you on the idea. Let’s get into how to practically do it!

Containerizing your toolkit

1. Setting the foundation

I’m not going into how to install Docker or how to manage containers. They have their documentation I highly recommend reading if you’re new to Docker.

For now, all you need to get started is a Dockerfile in a directory like this:

$ mkdir recon-toolkit-demo
$ cd recon-toolkit-demo
$ touch Dockerfile

Now, we can start adding to the Dockerfile.

Every Dockerfile starts with a base layer using the FROM keyword. For my toolkit, I’m choosing to use a variant of Debian, for it’s ease of use and wide support. But, feel free to choose your favorite OS (as long as it’s unix-based 🙂 ).

FROM debian:bookworm-slim

This is all I need to build and run the container:

$ docker build . -t recon-toolkit-demo
$ docker run -it recon-toolkit-demo

And just like that, you have your own Linux shell:

root@26e0023b58e6:/# ls
bin   dev  home  lib64	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 media	opt  root  sbin  sys  usr
root@26e0023b58e6:/# 

Pretty cool!

2. Installing tools

For demo purposes, I’m only going to install one tool. Everyone’s favorite sub-domain enumeration script: subfinder.

Reading the install instructions, I first need to install go

But before I even do that, I need curl so I can download go:

root@26e0023b58e6:/# apt-get update && apt-get install curl -y

Now that that’s taken care of, I can run through go’s install steps

root@26e0023b58e6:/# curl 'https://dl.google.com/go/go1.25.6.linux-amd64.tar.gz' -O
root@26e0023b58e6:/# rm -rf /usr/local/go && tar -C /usr/local -xzf go1.25.6.linux-amd64.tar.gz
root@26e0023b58e6:/# export PATH=$PATH:/usr/local/go/bin
root@26e0023b58e6:/# go version
go version go1.25.6 linux/amd64

Now we can install subfinder:

root@26e0023b58e6:/# go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
root@26e0023b58e6:/# export PATH=$PATH:/root/go/bin/         
root@26e0023b58e6:/# subfinder --version
[INF] Current Version: v2.12.0
[INF] Subfinder Config Directory: /root/.config/subfinder

Great! Now we have everything we need.

The only problem is, when I re-build the container, none of the tools we installed will be there.

To solve this, we just have to translate our manual install steps (which we verified work) into the Dockerfile:

FROM debian:bookworm-slim
RUN apt-get update && apt-get upgrade -y && apt-get install curl -y

# go install
RUN curl 'https://dl.google.com/go/go1.25.6.linux-amd64.tar.gz' -O 
RUN rm -rf /usr/local/go && tar -C /usr/local -xzf go1.25.6.linux-amd64.tar.gz
ENV PATH=$PATH:/usr/local/go/bin

# subfinder install
RUN go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
ENV PATH=$PATH:/root/go/bin/

With the exception of ENV (which is pretty self-explanatory), everything looks the same as our manual setup steps.

Now we can build the container again and run it to verify everything works:

$ docker build . -t recon-toolkit-demo
$ docker run -it recon-toolkit-demo
root@d351c95c3742:/# subfinder --version
[INF] Current Version: v2.12.0
[INF] Subfinder Config Directory: /root/.config/subfinder

Cool!

Tip: Use docker run -it to debug and manually verify if something goes wrong.

3. Install configurations

subfinder is great out-of-box, but even better when you add API keys.

To do this, you can specify a provider-config.yaml that is stored in by default in $CONFIG/subfinder/provider-config.yaml.

To achieve this in docker we can use the COPY directive to transfer the file from our working directory to the container like so:

$ touch provider-config.yaml
$ echo 'COPY provider-config.yaml /root/.config/subfinder/provider-config.yaml' >> Dockerfile

Of course, passing an empty provider-config.yaml won’t get you anywhere. You would need to specify your own keys. But this is how you would transfer config files into the container.

4. Binding to a workspace

Usually when I do my bounty recon, I like to keep all of my recon files on my host machine. That way, they’re persisted and I can process them using other tools I have installed on my machine.

To do this, you can create a dedicated directory on the container for bounty recon files by adding this to the Dockerfile:

RUN mkdir /bounty

Then, you can run the container (after re-building) with the --mount argument:

$ docker run -it --mount type=bind,source=/path/to/local/bounty_dir,target=/bounty recon-toolkit-demo

Now, if you cd into the /bounty directory on the container, you should see your host’s system files!

From there, you can run subfinder on any of your workspace files. And, if you pipe the output to a file, it will be saved on your local. The same behavior as if you had subfinder installed and running on your host!

5. Automating

Now we can run subfinder using docker manually, but eventually, you’re going to want to automate runs. Especially as your toolkit grows.

To script this process, you can write a shell script:

#!/bin/bash

cat wildcards.txt | subfinder -o subdomains.txt


and then COPY it over as we did earlier with provider-config.yaml:

COPY recon.sh .
RUN chmod +x recon.sh

Now we can run the script on our bounty files:

docker run -it --mount type=bind,source=/path/to/local/bounty_dir,target=/bounty recon-toolkit-demo ./recon.sh

Conclusion

Now you should be able to use docker package your bug bounty tools into a container.

From here, you may want to:

  • Add more tools
  • Publish your container to Dockerhub
  • Add wrapper scripts for ease of use

You can checkout my implementation on my github.

Happy hacking!