DevOps

Dockerfile, Helm Values, and .env → Compose: A Practical DevOps Checklist

Catch Dockerfile smells, scaffold Helm values.yaml, and turn .env files into Compose environment blocks — before the cluster tells you what you missed.

Nikhil Sai··3 min read
All posts

Most container incidents are boring: a missing tag, a root user left in production, a values file that drifted from the chart, or a .env that never made it into Compose the way you thought. The fixes aren't exotic — they're checklist work you want to do before kubectl apply or a Friday deploy.

Lint the Dockerfile first

Docker will build almost anything. That doesn't mean the image is operable. Common local catches:

  • FROM without a pinned tag (:latest as a silent moving target)
  • Extra layers from RUN apt-get without cleanup
  • Running the process as root
  • Copying secrets or entire build contexts into the image

A Dockerfile Linter won't replace a security scanner, but it surfaces the mistakes that show up in every code review eventually — while you're still editing the file.

Helm charts fail on values, not templates

Teams inherit charts and then spend weeks debugging nil pointer evaluating interface errors that are really missing keys in values.yaml. A starter values file doesn't make the chart correct, but it makes the shape of configuration visible: image tags, resource limits, ingress hosts, env blocks.

A Helm Values Generator is useful when you're scaffolding a new chart or documenting "what this chart expects" for the next person who only sees the templates.

.env ↔ Compose is where local and prod diverge

Developers keep secrets and config in .env. Compose wants an environment: (or env_file:) block. Copy-paste drift is how you get "works on my machine" for variables that never shipped. Converting the file into a Compose-ready block makes the mapping explicit and reviewable.

Use an .env to Docker Compose Converter when you're promoting a local setup toward something shareable — then still decide what belongs in secrets management vs plain env.

Where Kubernetes enters the picture

If your north star is Kubernetes, Compose is often the intermediate language. Converting Compose services into Deployments/Services gets you a starting manifest; validating that YAML before apply avoids the classic "invalid type for io.k8s..." loop.

Pair a Docker Compose to Kubernetes Converter with a Kubernetes YAML Validator, and keep cron expression parsing handy for CronJobs that look right until timezone and day-of-week OR semantics bite you.

Practical checklist

  • Pin base image tags; avoid :latest in anything that ships
  • Lint Dockerfiles for root, layer bloat, and secret leakage patterns
  • Treat values.yaml as the chart's public API — keep it complete and commented
  • Diff .env against Compose/K8s env blocks before calling a migration "done"
  • Validate manifests locally; dry-run against the cluster still matters

These steps are all text transforms and static checks — the kind of work that should run in the browser on a paste, without uploading your production Compose file to a stranger's server.

Try these next