DEV Community

Cover image for One Dockerfile to Rule Them All: Building a DevSecOps Container You'll Actually Love
jaydeep gohel
jaydeep gohel

Posted on

One Dockerfile to Rule Them All: Building a DevSecOps Container You'll Actually Love

BetterWay

The Problem Every DevOps Engineer Knows Too Well

It's 3 AM. You're debugging a Kubernetes issue in production. You SSH into your jump box and... kubectl isn't installed. Fine, you install it. But wait, you also need helm. And kubectx. Oh, and that security scanner your manager asked about three sprints ago.

Two hours later, you've got 23 tabs open about installing tools, half of them conflict with each other, and you're Googling "how to uninstall everything and start over" while questioning your career choices.

I've been there. We've all been there.

So one weekend, fueled by frustration and probably too much coffee, I decided to build something different: a single Docker container with every DevSecOps tool I'd ever need. Not just the basicsβ€”I'm talking everything. Kubernetes? Check. Security scanning? Triple check. Infrastructure as Code? You bet. Cost optimization tools? Why not!

What started as a simple "let me automate my setup" project turned into a 475-line Dockerfile odyssey, 130+ tools, and more debugging adventures than I'd like to admit.

This is that story.


🎯 The Idea: One Container to Rule Them All

Here's the thing about DevSecOps: the tools are amazing, but managing them is a nightmare.

You've got:

  • πŸ›‘οΈ Security scanners (Trivy, Kubescape, Grype, oh my!)
  • ☸️ Kubernetes tools (kubectl, helm, k9s, kustomize, and 20 plugins you forgot you installed)
  • πŸ—οΈ Infrastructure as Code (Terraform, but also OpenTofu now because licensing, plus Terragrunt, plus Ansible...)
  • πŸ”„ GitOps platforms (ArgoCD? Flux? Why not both!)
  • ☁️ Cloud CLIs (AWS, GCP, Azureβ€”because of course you support all three)

And that's just scratching the surface.

GitHub and Docker Hub links at the end of this article

My vision was simple: A single Docker container that has everything. No more "let me install this real quick." No more dependency hell. No more "it works on my machine" (because my machine is now a container).

πŸ’‘ Key Philosophy: If Batman can have a utility belt with gadgets for every situation, why can't we have a container with tools for every DevOps situation?

DevSecOps-batman


πŸ”οΈ Why Alpine? (Or: How I Learned to Love Minimalism)

Let me tell you about my first attempt: Ubuntu.

The Dockerfile worked great! The image size? 23GB.

Eight. Gigabytes.

For a tools container.

That's when Alpine Linux entered the chat. At ~5MB base image size, Alpine is like Marie Kondo for containersβ€”ruthlessly minimal, sparking joy through sheer efficiency.

FROM alpine:3.20

# That's it. That's the base. 5MB of pure minimalist beauty.
Enter fullscreen mode Exit fullscreen mode

The Good:

  • ⚑ Lightning-fast pulls
  • 🎯 Minimal attack surface (security team loved this)
  • πŸ“¦ Small layer sizes

The "Character Building Moments":

  • Uses BusyBox (no GNU tools by default)
  • Missing libraries you thought were "standard"
  • apk instead of apt (not hard, just different)

But here's the thing: those constraints make you better. You learn what tools actually need versus what they're just used to having. It's like moving to a tiny houseβ€”you discover you didn't need 90% of your stuff anyway.

# Install base utilities - this took longer than I'd like to admit
RUN apk add --no-cache \
    bash \
    curl \
    wget \
    git \
    jq \
    vim \
    # ... and about 30 more carefully chosen tools
Enter fullscreen mode Exit fullscreen mode

The --no-cache flag? That's Alpine's way of saying "we don't keep unnecessary package indexes around." This alone saves hundreds of megabytes.


πŸ› οΈ Building the Toolbox: Where Things Got Interesting

Stage 1: The Kubernetes Essentials

Everyone needs kubectl. That's not controversial. But here's where it gets fun:

# Install kubectl - latest version, dynamically fetched
RUN KUBECTL_VERSION=$(curl -L -s https://dl.k8s.io/release/stable.txt) && \
    curl -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" && \
    install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl && \
    rm kubectl
Enter fullscreen mode Exit fullscreen mode

Translation: "Dear GitHub API, what's the latest version? Cool, download that. Thanks."

This pattern became my best friend. Instead of hardcoding versions (which become outdated in 3 days), I fetch the latest. Sure, it makes builds slightly slower, but your tools are always current.

Then came the plugins. Oh, the plugins.

# kubectx and kubens - because typing is overrated
RUN KUBECTX_VERSION=$(curl -s https://api.github.com/repos/ahmetb/kubectx/releases/latest | \
    sed -n 's/.*"tag_name": "v\([0-9.]*\)".*/\1/p') && \
    wget https://github.com/ahmetb/kubectx/releases/download/v${KUBECTX_VERSION}/kubectx_v${KUBECTX_VERSION}_linux_x86_64.tar.gz && \
    tar -xzvf kubectx*.tar.gz && \
    mv kubectx /usr/local/bin/ && \
    rm kubectx*.tar.gz
Enter fullscreen mode Exit fullscreen mode

If you've ever typed kubectl config use-context production-cluster-us-east-1-k8s-cluster more than once, you understand why kubectx exists.

devops-coffee

Stage 2: The Security Battalion

This is where I went a bit overboard. In a good way.

# Trivy - because vulnerabilities don't scan themselves
RUN TRIVY_VERSION=$(curl -s https://api.github.com/repos/aquasecurity/trivy/releases/latest | \
    sed -n 's/.*"tag_name": "\([^"]*\)".*/\1/p') && \
    curl -LO "https://github.com/aquasecurity/trivy/releases/download/${TRIVY_VERSION}/trivy_${TRIVY_VERSION#v}_Linux-64bit.tar.gz" && \
    tar -xvzf trivy*.tar.gz -C /usr/local/bin && \
    rm trivy*.tar.gz

# Kubescape - CNCF's gift to security teams
RUN curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | /bin/bash

# Grype, Syft, Docker Scout... the gang's all here
Enter fullscreen mode Exit fullscreen mode

I ended up with 18 different security tools.

Is that excessive? Maybe.

But have you ever been in a meeting where someone asks "Can we scan for X?" and you can confidently say "Already got three tools for that"?

Chef's kiss.

Stage 3: Infrastructure as Code (Or: The Terraform Saga)

Terraform installation looks simple:

RUN TF_VERSION=$(curl -s https://checkpoint-api.hashicorp.com/v1/check/terraform | \
    jq -r .current_version | sed 's/^v//') && \
    wget "https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_amd64.zip" && \
    unzip terraform.zip && \
    mv terraform /usr/local/bin/ && \
    rm terraform.zip
Enter fullscreen mode Exit fullscreen mode

Then HashiCorp changed their license. The community forked it into OpenTofu. So now we have:

# OpenTofu - because open source matters
RUN OPENTOFU_VERSION=$(curl -s https://api.github.com/repos/opentofu/opentofu/releases/latest | \
    grep tag_name | cut -d '"' -f 4 | sed 's/^v//') && \
    wget "https://github.com/opentofu/opentofu/releases/download/v${OPENTOFU_VERSION}/tofu_${OPENTOFU_VERSION}_linux_amd64.zip" && \
    unzip tofu.zip && \
    mv tofu /usr/local/bin/ && \
    rm tofu.zip
Enter fullscreen mode Exit fullscreen mode

Both Terraform and OpenTofu. Because flexibility.

Then I added Terragrunt (for the overachievers), tflint (for the perfectionists), terraform-docs (for the documenters), and tfsec (for the security conscious).

At this point, my IaC tooling alone could deploy infrastructure on Mars.


πŸ› The Debugging Chronicles: A Comedy in Three Acts

Code-fuel

Act 1: The BusyBox Awakening

RUN grep -P "something" file.txt
# grep: invalid option -- P
Enter fullscreen mode Exit fullscreen mode

Me: "What do you mean invalid option? -P is standard!"

Alpine: "Not in BusyBox, buddy."

BusyBox implements common Unix utilities but with fewer options. Perl-compatible regex (-P)? Not supported. Extended regex (-E)? Also no.

Solution: Install grep from GNU coreutils, or rewrite my patterns. I chose option B and learned to love basic regex again. Character development!

Act 2: The gzip Mystery

RUN tar -xzf tool.tar.gz
# gzip: invalid magic
Enter fullscreen mode Exit fullscreen mode

This error message haunted my dreams. "Invalid magic"β€”like I was casting the wrong spell.

After hours of debugging, the culprit? Partial downloads. The network connection kept timing out, leaving me with corrupted archives.

Solution: Added retry logic and hash verification:

RUN wget --tries=3 --timeout=30 https://example.com/tool.tar.gz && \
    sha256sum tool.tar.gz  # Verify it's not cursed
Enter fullscreen mode Exit fullscreen mode

Act 3: The GitHub API Null Saga

TOOL_VERSION=$(curl -s https://api.github.com/repos/owner/tool/releases/latest | jq -r .tag_name)
# Version: null
Enter fullscreen mode Exit fullscreen mode

GitHub's API rate limit hit me like a brick wall. Without authentication, you get 60 requests per hour. My Dockerfile had 50+ tools using this pattern.

Solution: Batch the API calls and add fallbacks:

# Use cached version as fallback
RUN TOOL_VERSION=$(curl -s https://api.github.com/repos/owner/tool/releases/latest | \
    jq -r .tag_name || echo "v1.0.0") && \
    # ... rest of installation
Enter fullscreen mode Exit fullscreen mode

Also, building at 3 AM when API rates reset helps. Not that I did that. Multiple times.


🎨 The Final Touches: Organization is Everything

Here's a secret: the organization matters more than the tools.

I split the Dockerfile into 21 logical stages:

STAGE 1:  Environment Setup
STAGE 2:  Base System Packages
STAGE 3:  Networking & Diagnostics
STAGE 4:  Programming Languages
STAGE 5:  Cloud CLI Tools
STAGE 6:  Container & Orchestration
STAGE 7:  Kubectl Plugins
STAGE 8:  Infrastructure as Code
STAGE 9:  Service Mesh Tools
STAGE 10: GitOps & CI/CD
...and 11 more
Enter fullscreen mode Exit fullscreen mode

Each stage is clearly commented, explaining why each tool exists and what it does.

################################################################################
# STAGE 6: CONTAINER & ORCHESTRATION TOOLS
################################################################################
# Purpose: Everything you need to build, run, and manage containers
# Includes: Docker CLI, kubectl, helm, k9s, kind
################################################################################
Enter fullscreen mode Exit fullscreen mode

This isn't just for others reading the Dockerfileβ€”it's for future me. When I come back in 6 months wondering "why did I install this?", clear comments save the day.

The Developer Experience Layer

I also added quality-of-life tools that don't technically fit "DevSecOps" but make daily work so much better:

# lazygit - because Git UIs are nice actually
# bat - cat but with syntax highlighting and line numbers
# fzf - fuzzy finder that will change your life
# httpie - curl's friendlier cousin
Enter fullscreen mode Exit fullscreen mode

These tools transform the container from "functional" to "actually enjoyable to use."

befor


🎁 The Big Reveal: What's Actually In This Thing?

Let me give you the highlight reel of the 130+ tools packed into this container:

☸️ Kubernetes (25+ tools)

  • kubectl, helm, k9s (the TUI you never knew you needed)
  • kubectx, kubens (context switching made human)
  • stern (multi-pod logs), popeye (cluster linter)
  • skaffold (local development magic)

πŸ›‘οΈ Security (18 tools)

  • trivy, grype, syft (the CVE hunting trio)
  • kubescape, kube-bench (Kubernetes hardening)
  • checkov, tfsec, terrascan (IaC security)
  • snyk, falco (because paranoia is good)

πŸ—οΈ Infrastructure (10 tools)

  • terraform + opentofu (choose your fighter)
  • terragrunt (for the truly ambitious)
  • ansible (the original cool kid)
  • pulumi (modern IaC with real code)

πŸ”„ GitOps (5 tools)

  • argocd, flux (declarative everything)
  • tekton (cloud-native pipelines)
  • gh, glab (GitHub/GitLab from CLI)

πŸ” Secrets (4 tools)

  • sops, age (encrypt all the things)
  • vault, kubeseal (production-grade secrets)

πŸ’° Cost Optimization (2 tools)

  • kubecost (know where money goes)
  • infracost (Terraform cost estimation)

Plus: Service mesh tools (Istio, Linkerd, Cilium), cloud CLIs (AWS, GCP, Azure), database clients, linters, performance testing tools, and a whole developer experience suite.

πŸ“¦ Container Stats:

  • Base: Alpine Linux 3.20 (~5MB)
  • Final Size: ~15-16GB (yes still humongous, with 130+ tools)
  • Build Time: ~15-30 minutes (based on your hardware + internet conncetion)
  • Time Saved: Countless hours

πŸ”— Want to Try It Yourself?

The full Dockerfile, complete with all 130+ tools, comprehensive documentation, and even an automated build script with security scanning, is available on GitHub:

πŸ‘‰ GITHUB LINK HERE
🐳 Direct Docker Hub Image - docker pull erjaydeepgohel/devsecops-toolkit:main

What you'll find in the repo:

  • βœ… Complete Dockerfile with detailed comments
  • βœ… Build script with security scanning
  • βœ… Docker Compose setup
  • βœ… 3400+ lines of documentation
  • βœ… Cheat sheet with all commands

To get started:

# Clone the repo
git clone [GITHUB LINK HERE]

# Build it (automated with security scans)
./build.sh

# Run it
docker-compose run --rm devsecops bash

# Marvel at your new superpowers
kubectl version
terraform version
trivy --version
# ... try all 130+ tools!
Enter fullscreen mode Exit fullscreen mode

πŸŽ“ What I Learned (Besides Patience)

1. Dynamic Version Fetching is Worth It

Yes, it makes builds slower. But having kubectl 1.28 when 1.30 is out feels wrong. Always fetch latest.

2. Organization Beats Cleverness

A well-organized 500-line Dockerfile beats a "clever" 50-line one that nobody understands.

3. Constraints Make You Better

Alpine's limitations forced me to think carefully about each tool. Every megabyte mattered. This discipline creates better containers.

4. Documentation is a Love Letter to Future You

When you return to your Dockerfile 6 months later, clear comments are the difference between "oh right!" and "what was I thinking?!"

5. Developer Experience Matters

Tools like fzf, bat, and lazygit aren't "necessary," but they transform a container from tolerable to delightful.

hifi


πŸš€ What's Next?

This container is solid, but there's always room for improvement:

Future Ideas:

  • πŸ€– Add AI/ML tools (k8sgpt, kubectl-ai)
  • πŸ“Š More observability (Grafana Loki CLI, Tempo)
  • πŸ”’ Extended security (OPA Gatekeeper, Kyverno policies)
  • ⚑ Performance tools (eBPF utilities, perf)
  • 🌐 Multi-architecture builds (ARM64 support)

The Real Magic:

You can fork this and make it yours. Need different tools? Change the Dockerfile. Want to remove stuff? Easy. Need to add your company's custom tools? Go for it.

πŸ’‘ Pro Tip: Use this as a template for your own "DevOps Swiss Army Knife." The structure and patterns are designed to be extended.


🎬 The TL;DR

I spent way too much time building a Docker container with 130+ DevSecOps tools so you don't have to. It's based on Alpine Linux, includes everything from Kubernetes tools to security scanners to cost optimization platforms, and comes with 3400+ lines of documentation because I believe in doing things right.

Is it overkill? Definitely.

Is it awesome? Absolutely.

Will it save you hours of setup time? Definitely.

Would I do it again? Already planning v2.

If you've ever found yourself installing the same tools repeatedly, or if you've ever thought "there has to be a better way," this container is for you.

Give it a try. Break it. Improve it. Make it yours. That's what open source is all about.

And hey, if you build something cool with it, let me know! I'm always excited to see what the community creates.

Happy containerizing! 🐳✨


P.S. β€” If you enjoyed this journey through Dockerfile hell and back, give the repo a star ⭐ on GitHub. It feeds my developer ego and helps others discover it. Also, follow me here on for more DevSecOps adventures, tales from the terminal, and the occasional "I spent a weekend automating something that takes 5 minutes manually" story.


About the Author:
A DevSecOps Consultant with a slight obsession with automation. Currently explaining why our tools container needs 130+ applications when β€œkubectl and vim would be enough.”

Like my work : β˜• Send coffee and GitHub stars.

Don’t Like my work : Feedback in comment section.

This article was written with the small help of AI.

Top comments (0)