βοΈ Cloud & DevOps Tooling Guide¶
Run production-grade infrastructure locally. Test before you deploy. Break things safely.
π§° What Gets Installed¶
| Tool | Purpose | Local Equivalent |
|---|---|---|
| Docker | Container runtime | (it IS the local equivalent) |
| kubectl | Kubernetes CLI | Talks to Minikube/kind locally |
| Helm | K8s package manager | Deploy charts to local cluster |
| k9s | Kubernetes TUI | Monitor local/remote clusters |
| Terraform | Infrastructure as Code | Plan/apply against LocalStack |
| AWS CLI | Amazon Web Services | Configure for LocalStack |
| GCP CLI | Google Cloud Platform | gcloud emulators |
| Minikube | Local Kubernetes cluster | Single-node K8s on your laptop |
| LocalStack | Local AWS emulation | S3, Lambda, DynamoDB, SQS locally |
| Ansible | Configuration management | Test playbooks against local VMs |
π³ Docker The Foundation¶
Everything in cloud-native starts with containers.
Essential Commands¶
# Build an image
docker build -t myapp:latest .
# Run a container
docker run -d -p 8080:80 --name web myapp:latest
# Interactive shell inside container
docker exec -it web /bin/bash
# View logs
docker logs -f web
# Clean up everything
docker system prune -af --volumes
Docker Compose Multi-Container Apps¶
# docker-compose.yml
services:
app:
build: .
ports:
- "8080:8080"
depends_on:
- db
- redis
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: dev
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
pgdata:
docker compose up -d # Start all services
docker compose logs -f # Follow all logs
docker compose down -v # Stop and remove volumes
Anecdote¶
"Before Docker, 'works on my machine' was a meme. Now it's a guarantee if it runs in the container, it runs everywhere. The first time I shipped a multi-service app with
docker compose upand it just worked in CI, I understood why containers won."
βΈοΈ Kubernetes Locally¶
Minikube (Single-Node Cluster)¶
# Start a local cluster
minikube start --driver=docker --memory=4096 --cpus=2
# Dashboard
minikube dashboard
# Deploy an app
kubectl create deployment hello --image=nginx
kubectl expose deployment hello --port=80 --type=NodePort
minikube service hello --url
# Stop (preserves state)
minikube stop
# Delete (clean slate)
minikube delete
kind (Kubernetes in Docker) Lighter Alternative¶
# Install
go install sigs.k8s.io/kind@latest
# Create cluster
kind create cluster --name dev
# Load local images (no registry needed)
kind load docker-image myapp:latest --name dev
# Delete
kind delete cluster --name dev
k9s The Kubernetes TUI¶
k9s
# Navigate:
# :pods β list pods
# :deploy β list deployments
# :svc β list services
# /pattern β filter
# d β describe
# l β logs
# s β shell into pod
# ctrl+d β delete
# :q β quit
Anecdote¶
"k9s replaced my need for Lens, kubectl get, and half my terminal tabs. It's like htop for Kubernetes. Once you try it, you can't go back to raw kubectl."
ποΈ Terraform Infrastructure as Code¶
Local Development with LocalStack¶
# Start LocalStack
localstack start -d
# Configure AWS CLI to point to LocalStack
aws configure set aws_access_key_id test
aws configure set aws_secret_access_key test
aws configure set region us-east-1
# Use --endpoint-url for LocalStack
aws --endpoint-url=http://localhost:4566 s3 mb s3://my-bucket
aws --endpoint-url=http://localhost:4566 s3 ls
Terraform Against LocalStack¶
# main.tf
provider "aws" {
access_key = "test"
secret_key = "test"
region = "us-east-1"
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
endpoints {
s3 = "http://localhost:4566"
dynamodb = "http://localhost:4566"
lambda = "http://localhost:4566"
sqs = "http://localhost:4566"
iam = "http://localhost:4566"
}
}
resource "aws_s3_bucket" "data" {
bucket = "my-data-bucket"
}
resource "aws_dynamodb_table" "users" {
name = "users"
billing_mode = "PAY_PER_REQUEST"
hash_key = "user_id"
attribute {
name = "user_id"
type = "S"
}
}
terraform init
terraform plan
terraform apply -auto-approve
# All resources created locally no AWS bill
Anecdote¶
"I once ran
terraform destroyon the wrong workspace and deleted a production DynamoDB table. Since then, I test every Terraform change against LocalStack first. The 5 minutes of local testing saved me from a 3 AM incident."
π§ GCP Local Development¶
Emulators¶
# Pub/Sub emulator
gcloud beta emulators pubsub start --project=test-project
# Datastore emulator
gcloud beta emulators datastore start --project=test-project
# Firestore emulator
gcloud beta emulators firestore start --project=test-project
# Set environment to use emulator
$(gcloud beta emulators pubsub env-init)
Local Functions¶
# Install Functions Framework
pip install functions-framework
# Run locally
functions-framework --target=my_function --debug
π¦ Helm Kubernetes Package Manager¶
# Add a chart repository
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# Search for charts
helm search repo postgresql
# Install a chart
helm install my-db bitnami/postgresql --set auth.postgresPassword=dev
# List releases
helm list
# Upgrade
helm upgrade my-db bitnami/postgresql --set auth.postgresPassword=newpass
# Uninstall
helm uninstall my-db
# Create your own chart
helm create my-app
π CI/CD Locally¶
GitHub Actions (act)¶
Run GitHub Actions workflows locally:
# Install
curl -s https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash
# Run default workflow
act
# Run specific job
act -j build
# Run with specific event
act pull_request
GitLab CI (gitlab-runner)¶
# Install
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt install gitlab-runner
# Run a job locally
gitlab-runner exec docker build
π‘οΈ Security Scanning¶
# Scan Docker images for vulnerabilities
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:latest
# Scan Terraform for misconfigurations
docker run --rm -v $(pwd):/src aquasec/tfsec /src
# Scan Kubernetes manifests
docker run --rm -v $(pwd):/src kubesec/kubesec scan /src/deployment.yaml
π Typical Cloud Dev Workflow¶
1. Write infrastructure (Terraform)
2. Test locally (LocalStack / emulators)
3. Write application (Docker container)
4. Test locally (docker compose up)
5. Deploy to local K8s (Minikube + Helm)
6. Validate (k9s, curl, logs)
7. Push to CI (GitHub Actions / GitLab CI)
8. Deploy to staging (Terraform apply)
9. Promote to production (same Terraform, different vars)
The Golden Rule¶
If you can't run it locally, you can't debug it efficiently. Every cloud service should have a local equivalent for development.
| Cloud Service | Local Equivalent |
|---|---|
| AWS S3 | LocalStack / MinIO |
| AWS Lambda | LocalStack / SAM CLI |
| AWS DynamoDB | LocalStack / DynamoDB Local |
| AWS SQS/SNS | LocalStack |
| GCP Pub/Sub | gcloud emulator |
| GCP Firestore | gcloud emulator |
| Kubernetes | Minikube / kind |
| CI/CD | act / gitlab-runner exec |
"Cloud is just someone else's computer. Local development is YOUR computer. Master both."