Skip to content

DevOps

Docker DevContainer for Velocity X — One-Command Onboarding for New Engineers

No "Works on My Machine" — Ever Again

🐳 ⚙️ 🚀

New engineer clones your Velocity X repo on day one. Pops open VS Code. Clicks "Reopen in Container". Waits 2 minutes. Gets out: exact Node 20, Supabase CLI ready, prettier configured, Astro CLI installed, database connection pre-wired. No Slack threads, no "try deleting node_modules", no version mismatch between their M1 Mac and your CI pipeline. That's DevContainers. That's one .devcontainer/devcontainer.json file shipped with the repo.

Why Dev Environments Drift (And Why It Matters)

Dev environments are entropy machines. You ship a project with Node 18. One developer upgrades to 20 because they're on another project. Another installs Astro 4 globally but your repo wants 5. A third runs M1 hardware. Suddenly you've got three developers, three local environments, three different build outputs. The CI pipeline passes because CI is clean. Your production deploy passes because it pulls exact versions. But the developer's local npm run dev breaks and they spend an hour investigating before realizing it's a Node version issue.

Multiply that across 5 developers, 4 projects, and 18 months and you're paying for the privilege of debugging environment configuration instead of building features. DevContainers end that game. One .devcontainer.json file is the source of truth. Every developer, every day, runs the same environment. No surprises.

The Setup: One File, Container Config

Velocity X ships with a .devcontainer/devcontainer.json that looks like this:

{`{
  "name": "Velocity X",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:20",
  "features": {
    "ghcr.io/devcontainers/features/github-cli:1": {},
    "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "esbenp.prettier-vscode",
        "bradlc.vscode-tailwindcss",
        "dbaeumer.vscode-eslint"
      ]
    }
  },
  "postCreateCommand": "npm install && npx supabase projects list"
}`}

Read top to bottom: base image is Node 20 + TypeScript (from Microsoft's official devcontainer registry). Features layer in GitHub CLI and Docker. VS Code extension customizations auto-install prettier, Tailwind IntelliSense, and ESLint. The postCreateCommand runs npm install and verifies Supabase CLI works. Twenty-five lines of JSON. Done.

How It Works: Local Docker + Codespaces

On a developer's Mac: they have Docker Desktop running. They clone the repo. VS Code sees .devcontainer/devcontainer.json, shows "Reopen in Container" prompt. They click. VS Code spins up a Linux container with Node 20, mounts the project folder inside, runs npm install in that container, and opens the editor inside the container. Their local filesystem is shared, but npm modules, node_modules cache, everything else runs in the container. Repeat with 5 developers and they all get identical Node, identical npm, identical pre-installed tools.

On GitHub Codespaces: the workflow is identical but the container runs in Azure instead of locally. New developer, brand-new laptop, no Docker Desktop? They open the repo on github.com, press the Code button, pick "Codespaces", and wait 90 seconds. VS Code opens in their browser with the exact same environment ready to work. GitHub charges $0.18/hour for the compute. A developer can spin up a Codespace, fix a bug, push a PR, and kill the Codespace, all without touching their local machine.

Pre-Installed Tools That Ship With Velocity X

Node 20 + npm 10: exact version. Supabase CLI: runs supabase projects list on first boot to verify auth. Astro CLI: installed as a dev dependency but also available globally in the container. prettier: configured to format on save (VS Code setting baked into .devcontainer/devcontainer.json). Tailwind IntelliSense: VS Code extension that autocompletes Tailwind classes. ESLint: checks code as you type. Docker socket: if you need to run a Docker command from inside the container (rare, but it's there). GitHub CLI: for branch management and PR interaction without leaving the terminal.

What Happens on postCreateCommand

First spin-up takes 2–3 minutes because Docker is pulling the base image and running npm install. Subsequent restarts are seconds. The postCreateCommand runs npm install (installs dependencies in the container) and npx supabase projects list (verifies the Supabase CLI is installed and your SUPABASE_ACCESS_TOKEN env var works if it's set). If Supabase init fails, that's caught early — the developer fixes their token and restarts the container instead of debugging 30 minutes into coding.

Environment Variables + Secrets

The .devcontainer/devcontainer.json itself has no secrets. Instead, it can reference a .devcontainer/.env file (added to .gitignore). Individual developers check out that template, fill in their Supabase access token, and the container mounts it on startup. The container's shell sees the env vars and the Supabase CLI works. Netlify secrets stay in Netlify, Stripe keys stay in Stripe, nothing touches the repo.

Extensions + VS Code Settings Baked In

The "customizations.vscode" block auto-installs extensions the moment the container spins up. No developer has to remember "oh yeah, install Tailwind IntelliSense manually". It's there. VS Code settings can also be embedded in the devcontainer config — font size, theme, formatOnSave, etc. Optional, but it means on-brand editor experience for the whole team.

Does It Slow Down Development?

The container is local (Docker Desktop on the dev's machine), so there's zero latency. npm install runs on your local NVMe. Code changes are instant. The only overhead is the initial image pull (one-time, ~500MB) and container startup (one-time per VS Code restart, <30s). For a team of 5, you save 20+ hours per engineer per year from debugging environment mismatches. The math is obvious.

GitHub Actions + CI/CD Consistency

Your CI pipeline (GitHub Actions) should use the same base image as your devcontainer. If your devcontainer uses Node 20, your build job should use node:20. Now "it works locally" and "it works in CI" are the same statement. Debugging a build failure means debugging the same environment the engineer tested in.

Frequently Asked Questions

What if I'm on Windows?

DevContainers work on Windows 11 Pro / Enterprise with WSL 2 and Docker Desktop for Windows. The experience is identical — container spins up in WSL, you code in VS Code connected to the container. Windows Home doesn't have WSL 2, which is a limitation of Windows, not DevContainers.

Can I still use my local Node if I don't want DevContainers?

Yes. The .devcontainer/devcontainer.json is optional. A developer can ignore it, run npm install on their local machine with their local Node, and use the repo normally. They just don't get the guarantee that it matches CI.

How do I add a new global tool (e.g., a linter, a CLI)?

Add it to the Dockerfile that builds the base image, or add a feature to the .devcontainer/devcontainer.json. For npm-based tools, add them to package.json dev dependencies and they're installed in the container automatically.

What about database migrations?

Supabase CLI handles schema. You can add supabase db pull to postCreateCommand to sync the dev database on container startup, or require the developer to run it manually once they've authenticated. The devcontainer ensures the Supabase CLI itself is ready; the developer manages their own credentials and database state.

Does every team member need Docker Desktop?

For local development, yes. For code review and one-off PRs, no — they can use GitHub Codespaces and not pay anything (GitHub provides free Codespace hours per month). For an agency or contractor model, Codespaces is genuinely free 99% of the time.

What if the .devcontainer gets out of date?

It's a .git-tracked file in the repo. When it changes, developers get a "container rebuild needed" notification. One click and the image updates. No mystery upgrades; every update flows through code review like any other change.

The Bottom Line

DevContainers are a 25-line config file that trades one-time complexity for permanent elimination of environment drift. Ship Velocity X with .devcontainer/devcontainer.json and new engineers onboard in minutes. Developers, agencies, contractors, Codespaces users — all get the same box. Production confidence starts the moment they hit "npm run dev". See pricing for Velocity X licensing, and check the AI-ready architecture post for the full stack picture.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.