Context & Why: The Problem with Manual Terraform
Managing Infrastructure as Code (IaC) with Terraform usually starts as a solo project. You write some HCL, run terraform plan, and hit apply from your terminal. It’s smooth sailing until a second engineer joins the team. Suddenly, the friction begins. You start hearing shouts across the office: “Who updated the staging RDS instance last?” or “Why is the state file locked for the last 20 minutes?”
Local execution is a gamble. It lacks a centralized audit trail and invites the ‘works on my machine’ syndrome. One engineer might be running AWS provider v4.0 while another is on v5.0, leading to immediate state drift. GitOps solves this by moving execution away from your laptop. Infrastructure evolves through Git commits, not manual terminal commands.
Atlantis bridges this gap. It is a dedicated application that listens for GitHub, GitLab, or Bitbucket webhooks. When you open a PR, Atlantis runs a plan and comments the output back to the PR for everyone to see. Once the team approves, you simply comment atlantis apply to trigger the changes. In my experience managing clusters with 50+ microservices, this workflow eliminated 90% of our ‘out-of-sync’ environment headaches.
Installation: Deploying Atlantis with Docker
Docker is the fastest way to get Atlantis live without cluttering your host system. We will use Docker Compose to orchestrate the container and its environment variables.
1. Prerequisites
- A Linux VPS or local machine with Docker and Compose installed.
- A GitHub account with admin access to your repo.
- A public-facing IP or domain. Atlantis must receive webhooks. For local testing, tools like
ngrokcan expose port 4141 to the internet.
2. The Docker Compose Blueprint
First, create a dedicated directory. Inside, add a docker-compose.yml file. This configuration pulls the official image and maps a persistent volume to save your Terraform data.
version: '3.8'
services:
atlantis:
image: runatlantis/atlantis:latest
container_name: atlantis
ports:
- "4141:4141"
volumes:
- ./atlantis-data:/atlantis-data
environment:
- ATLANTIS_GH_USER=your-github-username
- ATLANTIS_GH_TOKEN=your-github-token
- ATLANTIS_GH_WEBHOOK_SECRET=your-webhook-secret
- ATLANTIS_REPO_ALLOWLIST=github.com/your-org/*
- ATLANTIS_DATA_DIR=/atlantis-data
- ATLANTIS_ATLANTIS_URL=http://your-public-url:4141
restart: always
Security matters. The ATLANTIS_REPO_ALLOWLIST is your primary shield; it ensures only your verified repositories can trigger the bot.
Configuration: The Two-Way Handshake
With the container ready, you need to authorize the connection between your server and GitHub. This requires a Personal Access Token (PAT) and a specific Webhook setup.
1. Generate a GitHub PAT
Head to your GitHub Settings > Developer Settings > Personal Access Tokens (Classic). Create a token with the repo scope. This allows Atlantis to read your HCL files and post comments. Copy this token immediately—you won’t see it again—and paste it into your ATLANTIS_GH_TOKEN variable.
2. Configure the GitHub Webhook
Open the repository you want to automate. Navigate to Settings > Webhooks > Add webhook.
- Payload URL:
http://your-public-url:4141/events - Content type:
application/json - Secret: Use the exact string from your
ATLANTIS_GH_WEBHOOK_SECRET. - Events: Choose “Let me select individual events” and check Issue comments, Pull requests, Pull request reviews, and Pushes.
3. Granular Control with atlantis.yaml
Atlantis defaults to scanning every directory for .tf files. To gain precise control, drop an atlantis.yaml file into your repository root. This defines specific projects and their automation rules.
version: 3
projects:
- name: staging-app
dir: staging/us-east-1
autoplan:
when_modified: ["*.tf", "../modules/**"]
enabled: true
- name: production-app
dir: prod/us-east-1
autoplan:
enabled: false # Manual plan only for high-stakes environments
Verification: Your First Automated PR
It’s time for the moment of truth. Fire up your container:
docker-compose up -d
1. The Workflow in Action
Create a new branch, add a simple tag to an existing resource, and open a Pull Request. Seconds later, Atlantis should wake up. It will scan your changes and post a formatted comment showing the terraform plan output directly in the PR thread.
Review the plan carefully. If the diff looks correct, type a new comment:
atlantis apply
The bot executes the command and reports the results. If successful, it places a lock on the project to prevent race conditions until the PR is merged.
2. Monitoring and Troubleshooting
Visit http://your-public-url:4141 to see the Atlantis UI. It provides a clear view of current state locks. If the bot stays silent after a PR, check the logs immediately:
docker logs -f atlantis
Watch for 403 Forbidden errors (usually a token permission issue) or 400 errors (often a webhook secret mismatch). Using this Docker-based approach ensures your CI/CD pipeline is isolated, reproducible, and easy to scale as your infrastructure grows.

