System & Environment Setup
When to use this skill
-
New project: Initial environment setup
-
Team onboarding: Standardizing new developer environments
-
Multiple services: Local execution of microservices
-
Production replication: Testing production environment locally
Instructions
Step 1: Docker Compose Configuration
docker-compose.yml:
version: '3.8'
services:
Web Application
web: build: context: . dockerfile: Dockerfile ports: - "3000:3000" environment: - NODE_ENV=development - DATABASE_URL=postgresql://postgres:password@db:5432/myapp - REDIS_URL=redis://redis:6379 volumes: - .:/app - /app/node_modules depends_on: - db - redis command: npm run dev
PostgreSQL Database
db: image: postgres:15-alpine environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password POSTGRES_DB: myapp ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql
Redis Cache
redis: image: redis:7-alpine ports: - "6379:6379" volumes: - redis_data:/data
Nginx (Reverse Proxy)
nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - web
volumes: postgres_data: redis_data:
Usage:
Start all services
docker-compose up -d
View logs
docker-compose logs -f web
Restart specific service only
docker-compose restart web
Stop and remove
docker-compose down
Remove including volumes
docker-compose down -v
Step 2: Environment Variable Management
.env.example:
Application
NODE_ENV=development PORT=3000 APP_URL=http://localhost:3000
Database
DATABASE_URL=postgresql://postgres:password@localhost:5432/myapp DATABASE_POOL_SIZE=10
Redis
REDIS_URL=redis://localhost:6379
JWT
ACCESS_TOKEN_SECRET=change-me-in-production-min-32-characters REFRESH_TOKEN_SECRET=change-me-in-production-min-32-characters TOKEN_EXPIRY=15m
SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=your-email@gmail.com SMTP_PASSWORD=your-app-password
External APIs
STRIPE_SECRET_KEY=sk_test_xxx STRIPE_PUBLISHABLE_KEY=pk_test_xxx AWS_ACCESS_KEY_ID=AKIAXXXXXXX AWS_SECRET_ACCESS_KEY=xxxxxxxx AWS_REGION=us-east-1
.env (local only, add to gitignore):
.gitignore
.env .env.local .env.*.local
Loading environment variables (Node.js):
import dotenv from 'dotenv'; import path from 'path';
// Load .env file dotenv.config();
// Type-safe environment variables interface Env { NODE_ENV: 'development' | 'production' | 'test'; PORT: number; DATABASE_URL: string; REDIS_URL: string; ACCESS_TOKEN_SECRET: string; }
function loadEnv(): Env { const required = ['DATABASE_URL', 'ACCESS_TOKEN_SECRET', 'REDIS_URL'];
for (const key of required) {
if (!process.env[key]) {
throw new Error(Missing required environment variable: ${key});
}
}
return { NODE_ENV: (process.env.NODE_ENV as any) || 'development', PORT: parseInt(process.env.PORT || '3000'), DATABASE_URL: process.env.DATABASE_URL!, REDIS_URL: process.env.REDIS_URL!, ACCESS_TOKEN_SECRET: process.env.ACCESS_TOKEN_SECRET! }; }
export const env = loadEnv();
Step 3: Dev Container (VS Code)
.devcontainer/devcontainer.json:
{ "name": "Node.js & PostgreSQL", "dockerComposeFile": "../docker-compose.yml", "service": "web", "workspaceFolder": "/app",
"customizations": { "vscode": { "extensions": [ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "ms-azuretools.vscode-docker", "prisma.prisma" ], "settings": { "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "eslint.validate": ["javascript", "typescript"] } } },
"forwardPorts": [3000, 5432, 6379],
"postCreateCommand": "npm install",
"remoteUser": "node" }
Step 4: Makefile (Convenience Commands)
Makefile:
.PHONY: help install dev build test clean docker-up docker-down migrate seed
help: ## Show this help @grep -E '^[a-zA-Z_-]+:.?## .$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
install: ## Install dependencies npm install
dev: ## Start development server npm run dev
build: ## Build for production npm run build
test: ## Run tests npm test
test-watch: ## Run tests in watch mode npm test -- --watch
lint: ## Run linter npm run lint
lint-fix: ## Fix linting issues npm run lint -- --fix
docker-up: ## Start Docker services docker-compose up -d
docker-down: ## Stop Docker services docker-compose down
docker-logs: ## View Docker logs docker-compose logs -f
migrate: ## Run database migrations npm run migrate
migrate-create: ## Create new migration
@read -p "Migration name: " name;
npm run migrate:create -- $$name
seed: ## Seed database npm run seed
clean: ## Clean build artifacts rm -rf dist node_modules coverage
reset: clean install ## Reset project (clean + install)
Usage:
make help # List of commands make install # Install dependencies make dev # Start dev server make docker-up # Start Docker services
Step 5: Infrastructure as Code (Terraform)
main.tf (AWS example):
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }
backend "s3" { bucket = "myapp-terraform-state" key = "production/terraform.tfstate" region = "us-east-1" } }
provider "aws" { region = var.aws_region }
VPC
resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16"
tags = { Name = "${var.project_name}-vpc" Environment = var.environment } }
RDS (PostgreSQL)
resource "aws_db_instance" "postgres" { identifier = "${var.project_name}-db" engine = "postgres" engine_version = "15.4" instance_class = "db.t3.micro" allocated_storage = 20 storage_encrypted = true
db_name = var.db_name username = var.db_username password = var.db_password
vpc_security_group_ids = [aws_security_group.db.id] db_subnet_group_name = aws_db_subnet_group.main.name
backup_retention_period = 7 skip_final_snapshot = false final_snapshot_identifier = "${var.project_name}-final-snapshot"
tags = { Name = "${var.project_name}-db" Environment = var.environment } }
ECS (Container Service)
resource "aws_ecs_cluster" "main" { name = "${var.project_name}-cluster"
setting { name = "containerInsights" value = "enabled" } }
Load Balancer
resource "aws_lb" "main" { name = "${var.project_name}-alb" internal = false load_balancer_type = "application" security_groups = [aws_security_group.alb.id] subnets = aws_subnet.public[*].id }
variables.tf:
variable "project_name" { description = "Project name" type = string default = "myapp" }
variable "environment" { description = "Environment (dev, staging, production)" type = string }
variable "aws_region" { description = "AWS region" type = string default = "us-east-1" }
variable "db_username" { description = "Database username" type = string sensitive = true }
variable "db_password" { description = "Database password" type = string sensitive = true }
Output format
Project Structure
project/ ├── .devcontainer/ │ └── devcontainer.json ├── docker-compose.yml ├── Dockerfile ├── Makefile ├── .env.example ├── .gitignore ├── terraform/ │ ├── main.tf │ ├── variables.tf │ └── outputs.tf └── README.md
Constraints
Mandatory Rules (MUST)
-
Provide .env.example: List of required environment variables
-
.gitignore: Never commit .env files
-
README.md: Document installation and running instructions
Prohibited (MUST NOT)
-
No committing secrets: Never commit .env, credentials files
-
No hardcoding: All configuration via environment variables
Best practices
-
Docker Compose: Use Docker Compose for local development
-
Volume Mount: Instantly reflects code changes
-
Health Checks: Verify service readiness
References
-
Docker Compose
-
Dev Containers
-
Terraform
Metadata
Version
-
Current Version: 1.0.0
-
Last Updated: 2025-01-01
-
Compatible Platforms: Claude, ChatGPT, Gemini
Related Skills
-
deployment
-
environment-setup
Tags
#environment-setup #Docker-Compose #dev-environment #IaC #Terraform #infrastructure
Examples
Example 1: Basic usage
Example 2: Advanced usage