Environment and Tools
Back to Infrastructure Index
Development Environment Setup
Setting up consistent development environments is crucial for team productivity and reducing “it works on my machine” problems.
Makefile
A Makefile is a build automation tool that helps standardize common tasks across your team.
What is a Makefile?
- Build automation tool
- Defines tasks (targets) and their dependencies
- Commonly used in Unix/Linux environments
- Simplifies complex command sequences
Basic Makefile Structure
target: dependencies
command
command.PHONY Directive
Purpose: ใช้เขียนบนหัว Makefile เพื่อหลีกเลี่ยง conflict ของไฟล์ที่มีชื่อซ้ำกัน
.PHONY tells Make that these targets are not actual files, but rather command names.
Example:
.PHONY: build test clean run
build:
go build -o app main.go
test:
go test ./...
clean:
rm -f app
run:
./appWhy use .PHONY?
- Prevents conflicts with files named
build,test, etc. - Ensures targets always run, even if files with those names exist
- Makes Makefile more reliable
Practical Makefile Examples
Go Project Makefile
.PHONY: build test clean run docker-build docker-run
# Variables
APP_NAME=myapp
DOCKER_IMAGE=myapp:latest
# Build the application
build:
go build -o bin/$(APP_NAME) cmd/main.go
# Run tests
test:
go test -v ./...
# Run tests with coverage
test-coverage:
go test -cover ./...
# Clean build artifacts
clean:
rm -rf bin/
go clean
# Run the application
run: build
./bin/$(APP_NAME)
# Build Docker image
docker-build:
docker build -t $(DOCKER_IMAGE) .
# Run Docker container
docker-run:
docker run -p 8080:8080 $(DOCKER_IMAGE)
# Install dependencies
deps:
go mod download
go mod tidy
# Format code
fmt:
go fmt ./...
# Lint code
lint:
golangci-lint runNode.js Project Makefile
.PHONY: install build test dev clean
install:
npm install
build:
npm run build
test:
npm test
dev:
npm run dev
clean:
rm -rf node_modules/ dist/
deploy: build
./deploy.shDocker-focused Makefile
.PHONY: up down build logs shell clean
# Start services
up:
docker-compose up -d
# Stop services
down:
docker-compose down
# Build images
build:
docker-compose build
# View logs
logs:
docker-compose logs -f
# Shell into container
shell:
docker-compose exec app /bin/sh
# Clean up everything
clean:
docker-compose down -v
docker system prune -fEnvironment Variables
What are Environment Variables?
Configuration values that can change between environments without code changes.
Common Use Cases
- Database connection strings
- API keys and secrets
- Feature flags
- Service URLs
- Configuration settings
Managing Environment Variables
.env Files
# .env
DATABASE_URL=postgresql://localhost:5432/mydb
API_KEY=secret-key-here
PORT=3000
NODE_ENV=developmentImportant: Never commit .env files to version control!
# .gitignore
.env
.env.local
.env.*.localLoading Environment Variables
Bash:
export DATABASE_URL="postgresql://localhost:5432/mydb"
source .envNode.js:
require('dotenv').config();
const dbUrl = process.env.DATABASE_URL;Go:
import "os"
dbUrl := os.Getenv("DATABASE_URL")Python:
import os
from dotenv import load_dotenv
load_dotenv()
db_url = os.getenv("DATABASE_URL")Environment-Specific Configuration
.env # Default/development
.env.development # Development specific
.env.staging # Staging specific
.env.production # Production specific
.env.test # Test specific
Configuration Management Best Practices
1. Twelve-Factor App Configuration
Store config in the environment, never in code:
✅ Good:
dbHost := os.Getenv("DB_HOST")❌ Bad:
dbHost := "localhost" // Hardcoded2. Hierarchical Configuration
Default values → Environment files → Environment variables → Command-line args
(Lowest priority) (Highest priority)
3. Secret Management
- Use secret management tools (Vault, AWS Secrets Manager, Azure Key Vault)
- Never commit secrets to git
- Rotate secrets regularly
- Use different secrets per environment
4. Configuration Validation
func validateConfig() error {
required := []string{"DB_HOST", "DB_USER", "DB_PASSWORD"}
for _, key := range required {
if os.Getenv(key) == "" {
return fmt.Errorf("required env var %s is not set", key)
}
}
return nil
}Common Development Tools
Version Managers
- nvm - Node Version Manager
- gvm - Go Version Manager
- pyenv - Python Version Manager
- rbenv - Ruby Version Manager
- asdf - Universal version manager
Package Managers
- npm/yarn/pnpm - JavaScript
- pip/poetry - Python
- go mod - Go
- maven/gradle - Java
Build Tools
- Make - Universal build automation
- Gradle - Java/Kotlin
- Webpack - JavaScript bundling
- Maven - Java dependency management
Infrastructure as Code (IaC)
Tools
- Terraform - Multi-cloud infrastructure
- Ansible - Configuration management
- Kubernetes - Container orchestration
- Docker Compose - Multi-container Docker apps
Example: Docker Compose
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- DATABASE_URL=${DATABASE_URL}
depends_on:
- db
db:
image: postgres:14
environment:
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:Environment Setup Checklist
Development Environment
- Install required programming languages
- Install version managers
- Set up IDE/editor
- Configure git
- Install Docker
- Set up local databases
- Configure environment variables
- Install project dependencies
CI/CD Environment
- Configure build pipeline
- Set up test automation
- Configure deployment scripts
- Set up environment variables
- Configure secret management
- Set up monitoring
Related: