Run Antigravity locally for any length of time and you start hitting reproducibility walls: a new machine breaks the setup, OS-specific paths leak in, you can't hand the project to a colleague. The clean fix is a DevContainer.
This guide pulls together everything I wish I'd known when I first containerized Antigravity for personal projects and small teams. Docker and VS Code basics are assumed; the focus is on what's specific to Antigravity.
Why Antigravity in particular benefits from DevContainers
Antigravity is more than an editor — it's an agent execution environment. Agents run shell commands, write files, hit the network. When that runtime is your bare laptop, an agent misstep affects your real system.
DevContainerizing it gives you:
- Destructive agent operations stay inside the container
- Toolchains (Node, Python, Go) pinned per project
- Ollama, Postgres, etc. start in the same compose, instantly available to the agent
- Onboarding teammates becomes "open this in VS Code" — that's the entire instruction
In my experience, what used to be a half-day to a full day of new-member setup compressed to about 30 minutes after going container-first.
A minimum working DevContainer
Start with something that runs. Create a .devcontainer/ directory at the project root with these two files:
.devcontainer/devcontainer.json:
{
"name": "Antigravity Workspace",
"build": {
"dockerfile": "Dockerfile"
},
"customizations": {
"vscode": {
"extensions": [
"google.antigravity",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint"
],
"settings": {
"antigravity.workspaceMode": "container",
"antigravity.allowedTools": ["bash", "fileEdit", "webSearch"]
}
}
},
"remoteUser": "node",
"forwardPorts": [3000, 11434, 5432],
"postCreateCommand": "npm install"
}.devcontainer/Dockerfile:
FROM mcr.microsoft.com/devcontainers/javascript-node:22
RUN apt-get update && apt-get install -y \
curl jq postgresql-client redis-tools \
&& rm -rf /var/lib/apt/lists/*
# Install the Antigravity CLI (pinned version)
RUN curl -fsSL https://antigravity.google.com/install.sh | sh -s -- --version 2.4.1That's enough. From VS Code, "Reopen in Container" gives you a working Antigravity environment.
Adding Ollama to the same compose
If you use local LLMs, running Ollama as a sibling service in Docker Compose is by far the most stable approach.
.devcontainer/docker-compose.yml:
services:
workspace:
build:
context: .
dockerfile: Dockerfile
volumes:
- ../..:/workspace:cached
command: sleep infinity
depends_on:
- ollama
environment:
- OLLAMA_BASE_URL=http://ollama:11434
ollama:
image: ollama/ollama:latest
volumes:
- ollama-models:/root/.ollama
ports:
- "11434:11434"
deploy:
resources:
reservations:
devices:
- capabilities: ["gpu"]
count: all
volumes:
ollama-models:Switch devcontainer.json to compose form:
{
"name": "Antigravity + Ollama",
"dockerComposeFile": "docker-compose.yml",
"service": "workspace",
"workspaceFolder": "/workspace"
}Now agents inside Antigravity reach Ollama at http://ollama:11434. The OLLAMA_BASE_URL env var means you don't have to hardcode anything in Antigravity's settings.
The deploy.resources GPU section assumes the NVIDIA Container Toolkit is installed on the host. On Apple Silicon, drop the entire deploy block — Docker Desktop on macOS can't pass through the Metal GPU.
Secrets, safely
Never hardcode API keys into a DevContainer. The .env file pattern is what holds up:
.devcontainer/.env.example:
ANTHROPIC_API_KEY=
GOOGLE_API_KEY=
GITHUB_TOKEN=
OPENAI_API_KEY=
Add .devcontainer/.env to .gitignore. Each teammate copies the example and fills in their own keys. Wire it into compose:
services:
workspace:
env_file:
- .envAntigravity reads them via process.env.ANTHROPIC_API_KEY, and Git never sees them.
The mistake I want to flag: don't put keys directly into containerEnv inside devcontainer.json. That file is committed to Git. Keys leak immediately. Always go through env_file.
Volume persistence pitfalls
Default DevContainer behavior wipes container internals on rebuild. To survive that, declare volumes for things you care about:
- Ollama models (multi-GB downloads — re-pulling every time is not viable)
- Antigravity conversation history and agent state
- npm and pip caches
Updated compose:
services:
workspace:
volumes:
- ../..:/workspace:cached
- antigravity-state:/home/node/.antigravity
- npm-cache:/home/node/.npm
- pip-cache:/home/node/.cache/pip
volumes:
ollama-models:
antigravity-state:
npm-cache:
pip-cache:Now rebuilds preserve history and caches. Before I configured this, every rebuild cost me a 20-minute Ollama redownload.
A team distribution pattern
For team usage:
1. Commit .devcontainer/ — Dockerfile, docker-compose.yml, devcontainer.json, .env.example. Don't commit .env.
2. Three-line README startup instructions:
## Dev environment
1. Start Docker Desktop
2. `cp .devcontainer/.env.example .devcontainer/.env` and fill in your API keys
3. Open in VS Code, then "Reopen in Container"3. Centralize Antigravity settings in customizations.vscode.settings so every container has identical Antigravity behavior. "Works on my machine" stops being a meaningful complaint.
CI parity
Running the same Dockerfile in CI prevents "works locally, fails in CI." GitHub Actions example:
name: Test in DevContainer
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: devcontainers/ci@v0.3
with:
imageName: my-app-devcontainer
push: never
runCmd: npm testThe devcontainers/ci Action builds your .devcontainer/Dockerfile in CI and runs your command inside it. Local and CI now share the exact same image, eliminating environment-mismatch bugs.
Tradeoffs to know
A few honest caveats.
File-watcher behavior. /workspace is a bind mount. Host changes propagate, but framework hot reload (Next.js next dev, etc.) sometimes doesn't see them in-container. Setting CHOKIDAR_USEPOLLING=true usually fixes it.
First build takes time. Five to fifteen minutes is normal. Keep postCreateCommand minimal so subsequent boots are fast.
Host shell config doesn't carry in. Your .zshrc aliases don't exist inside the container. The standard fix is a project aliases.sh in .devcontainer/, sourced from ~/.bashrc in the Dockerfile.
When the AI Behaves Differently Inside and Outside the Container
The first surprise after containerizing was that the same prompt produced different Antigravity responses on the host and inside the container. The culprit was environment variables.
ANTIGRAVITY_MODEL and my API key pointers lived on the host and never made it into the container. Inside, everything silently fell back to the default model, changing both the granularity and the speed of responses. For a while I nearly convinced myself that "containers make it less accurate."
The fix is small: list exactly the variables you need under remoteEnv in devcontainer.json. Use remoteEnv rather than containerEnv so the values are never baked into the image build cache.
{
"remoteEnv": {
"ANTIGRAVITY_MODEL": "${localEnv:ANTIGRAVITY_MODEL}",
"GOOGLE_API_KEY": "${localEnv:GOOGLE_API_KEY}"
}
}Keep the keys themselves in .env, and make sure .env is in .gitignore. Writing them straight into containerEnv leaves the values sitting in an image layer, and they leak the moment you share that image. Even as an indie developer working alone, this is not the corner to cut.
If you call a local LLM from inside the container, you will also need to reach the host's Ollama through host.docker.internal — that setup is covered in "Calling Local LLMs from Antigravity", and keeping your automation running through a CLI migration is covered in "From Gemini CLI to Antigravity CLI".
What to do first
If you only execute one part of this guide, copy and paste the minimum DevContainer above. Ollama integration and CI parity can come later.
The moment your first "Reopen in Container" succeeds, you can grow the setup from there. Once Antigravity is part of your real workflow, reproducible environments stop being optional. Build it once, and every new project you start can copy and modify it.