This guide covers how to run the GoShop E-Commerce API using Docker and Docker Compose.
Make sure your .env file has the required variables:
# Database
DB_USER=commerce
DB_PASSWORD=commerce
DB_NAME=commerce
DB_PORT=5432
DB_DRIVER=postgres
# JWT (REQUIRED - must be at least 32 characters)
JWT_SECRET=your-super-secret-jwt-key-minimum-32-characters-long-change-this
# Google OAuth (Optional)
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URL=http://localhost:8080/api/v1/auth/google/callback
# Seeding
SEED_DB=truedocker-compose up --buildThis will:
- Build the Go API Docker image
- Start PostgreSQL database
- Start the API service
- Run migrations automatically
- Seed database if
SEED_DB=true
The API will be available at:
- API Base URL: http://localhost:8080/api/v1
- Health Check: http://localhost:8080/health
- Image: postgres:16-alpine
- Container: goshop-postgres
- Port: 5432 (configurable via
DB_PORT) - Volume: postgres_data (persistent storage)
- Health Check: Automated readiness check
- Image: Built from Dockerfile
- Container: goshop-api
- Port: 8080 (configurable via
PORT) - Health Check: HTTP check on /health endpoint
- Depends On: PostgreSQL (waits for database to be healthy)
# Start in foreground (see logs)
docker-compose up
# Start in background (detached)
docker-compose up -d
# Rebuild and start
docker-compose up --build# Stop services (preserves data)
docker-compose down
# Stop and remove volumes (deletes database data)
docker-compose down -v# All services
docker-compose logs -f
# Specific service
docker-compose logs -f api
docker-compose logs -f postgres# Rebuild just the API service
docker-compose build api
# Force rebuild without cache
docker-compose build --no-cache api# Access PostgreSQL
docker-compose exec postgres psql -U commerce -d commerce
# Access API container shell
docker-compose exec api sh
# Run database queries
docker-compose exec postgres psql -U commerce -d commerce -c "SELECT * FROM users LIMIT 5;"The API container receives environment variables from your .env file. Key variables:
| Variable | Description | Default |
|---|---|---|
PORT |
API server port | 8080 |
DB_HOST |
Database hostname | postgres |
DB_PORT |
Database port | 5432 |
DB_USER |
Database username | commerce |
DB_PASSWORD |
Database password | commerce |
DB_NAME |
Database name | commerce |
JWT_SECRET |
JWT signing key (REQUIRED) | - |
GOOGLE_CLIENT_ID |
Google OAuth client ID | - |
GOOGLE_CLIENT_SECRET |
Google OAuth secret | - |
SEED_DB |
Seed with sample data | false |
For production, update your .env or set environment variables:
# Use strong, random JWT secret
JWT_SECRET=$(openssl rand -base64 48)
# Use strong database password
DB_PASSWORD=$(openssl rand -base64 32)
# Update OAuth redirect URL for your domain
GOOGLE_REDIRECT_URL=https://your-domain.com/api/v1/auth/google/callback
# Disable seeding in production
SEED_DB=false# Build with production tag
docker-compose build
# Or build manually
docker build -t goshop-api:1.0.0 .# Tag for your registry
docker tag goshop-api:1.0.0 your-registry.com/goshop-api:1.0.0
# Push to registry
docker push your-registry.com/goshop-api:1.0.0Update docker-compose.yml to use the registry image:
services:
api:
image: your-registry.com/goshop-api:1.0.0
# ... rest of configThe application uses a multi-stage build for optimal image size:
- Base:
golang:1.23-alpine - Installs build dependencies
- Downloads Go modules
- Compiles static binary with optimizations
- Result: ~15MB binary
- Base:
alpine:3.19 - Minimal dependencies (ca-certificates, tzdata)
- Non-root user for security
- Only includes compiled binary
- Final image: ~25MB
- ✅ Non-root user (appuser:1000)
- ✅ Minimal attack surface (Alpine Linux)
- ✅ No build tools in runtime image
- ✅ Read-only filesystem compatible
- ✅ Health checks enabled
Services communicate through goshop-network bridge network:
- API connects to postgres via hostname
postgres - External access via exposed ports
- Database not exposed to host by default (more secure)
pg_isready -U commerce -d commerce- Interval: 10s
- Timeout: 5s
- Retries: 5
wget --spider http://localhost:8080/health- Interval: 30s
- Timeout: 3s
- Start Period: 10s (allows time for migrations)
- Retries: 3
Check logs:
docker-compose logs apiCommon issues:
- JWT_SECRET not set or too short
- Database not ready (wait for health check)
- Port 8080 already in use
Check database health:
docker-compose ps
docker-compose logs postgresTest connection:
docker-compose exec postgres psql -U commerce -d commerce -c "SELECT 1;"View migration status:
docker-compose exec postgres psql -U commerce -d commerce -c "SELECT * FROM schema_migrations;"Reset database (WARNING: deletes all data):
docker-compose down -v
docker-compose up --buildEnsure redirect URL is correct:
- For Docker: Use
http://localhost:8080/api/v1/auth/google/callback - For production: Update to your domain
- Must match exactly in Google Cloud Console
Change the port in .env:
PORT=8081Then rebuild:
docker-compose down
docker-compose up --builddocker stats goshop-api goshop-postgresdocker-compose ps
docker system dfdocker-compose exec postgres psql -U commerce -d commerce -c "
SELECT pg_size_pretty(pg_database_size('commerce')) AS db_size;
"docker-compose exec postgres pg_dump -U commerce commerce > backup.sqldocker-compose exec -T postgres psql -U commerce commerce < backup.sqldocker run --rm \
-v goshop_postgres_data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/postgres-backup.tar.gz /dataUpdate docker-compose.yml:
services:
api:
# ... config
deploy:
replicas: 3Add a load balancer (nginx, traefik, etc.) in front of API instances.
services:
api:
# ... config
deploy:
resources:
limits:
cpus: '2'
memory: 512M
reservations:
cpus: '0.5'
memory: 256Mname: Build and Push Docker Image
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker image
run: docker build -t goshop-api:${{ github.sha }} .
- name: Push to registry
run: |
echo ${{ secrets.REGISTRY_TOKEN }} | docker login -u ${{ secrets.REGISTRY_USER }} --password-stdin
docker push goshop-api:${{ github.sha }}