Overview
POS Kasir provides a complete Docker setup with multi-stage builds for optimized production images. The application uses Docker Compose to orchestrate both backend and frontend services.
Prerequisites
Docker Engine 20.10+
Docker Compose v2.0+
At least 1GB available RAM
PostgreSQL database (external or containerized)
Docker Compose Configuration
The application includes a docker-compose.yml file that defines two services:
Services
Backend Service
Built from multi-stage Dockerfile using Go 1.25
Container name: pos-backend
Port mapping: ${APP_PORT:-8080}:8080
Resource limits: 0.5 CPU, 512MB RAM
Auto-restart enabled
Frontend Service
Built from web directory
Container name: pos-frontend
Port mapping: 3000:80
Auto-restart enabled
Network
Both services communicate via a bridge network named pos-network.
Quick Start
cd /path/to/pos-kasir
cp .env.example .env
cp web/.env.example web/.env
Edit both .env files with your configuration. See Environment Variables for complete reference.
2. Build Images
This command builds both backend and frontend images using multi-stage builds for optimization.
3. Start Services
The -d flag runs containers in detached mode.
4. Verify Deployment
# Check container status
docker compose ps
# View logs
docker compose logs -f
# Check backend health
curl http://localhost:8080/health
# Check frontend
curl http://localhost:3000
Backend Dockerfile
The backend uses a multi-stage build for minimal image size:
# Stage 1: Builder
FROM golang:1.25-alpine AS builder
WORKDIR /app
RUN apk add --no-cache git
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags= "-s -w" -o main ./cmd/app/main.go
# Stage 2: Runtime
FROM alpine:latest
WORKDIR /root/
RUN apk --no-cache add ca-certificates tzdata
ENV TZ=Asia/Jakarta
COPY --from=builder /app/main .
EXPOSE 8080
CMD [ "./main" ]
Build Optimizations
CGO disabled : Static binary for better portability
Stripped symbols : -ldflags="-s -w" reduces binary size
Alpine base : Minimal image (~5MB base)
Timezone : Pre-configured for Asia/Jakarta
Management Commands
Start/Stop Services
# Start all services
docker compose up -d
# Stop all services
docker compose down
# Restart services
docker compose restart
# Stop and remove volumes (WARNING: deletes data)
docker compose down -v
View Logs
# All services
docker compose logs -f
# Backend only
docker compose logs -f backend
# Frontend only
docker compose logs -f frontend
# Last 100 lines
docker compose logs --tail=100
Update Application
# Pull latest code
git pull
# Rebuild and restart
docker compose up -d --build
Execute Commands
# Access backend shell
docker compose exec backend sh
# Access frontend shell
docker compose exec frontend sh
# Run database migrations
docker compose exec backend ./main migrate
Resource Management
Current Limits
The backend service has resource constraints defined:
deploy :
resources :
limits :
cpus : '0.50'
memory : 512M
Adjusting Resources
Edit docker-compose.yml to modify resource limits based on your server capacity:
deploy :
resources :
limits :
cpus : '1.0' # Increase CPU limit
memory : 1024M # Increase RAM limit
reservations :
cpus : '0.25'
memory : 256M
Resource limits help prevent a single container from consuming all system resources.
Database Setup
External PostgreSQL
If using an external PostgreSQL database, configure in .env:
DB_HOST = your-postgres-host
DB_PORT = 5432
DB_USER = your-username
DB_PASSWORD = your-password
DB_NAME = pos_kasir
DB_SSLMODE = require
Add PostgreSQL to Docker Compose
To run PostgreSQL in Docker, add this service to docker-compose.yml:
services :
postgres :
image : postgres:16-alpine
container_name : pos-postgres
environment :
POSTGRES_USER : ${DB_USER}
POSTGRES_PASSWORD : ${DB_PASSWORD}
POSTGRES_DB : ${DB_NAME}
ports :
- "5432:5432"
volumes :
- postgres-data:/var/lib/postgresql/data
networks :
- pos-network
restart : always
volumes :
postgres-data :
Then update backend .env:
DB_HOST = postgres
DB_PORT = 5432
Production Considerations
Before deploying to production, ensure you:
Set APP_ENV=production
Use strong random values for JWT_SECRET
Enable SSL/TLS for database connections
Configure proper backup strategies
Set up monitoring and logging
Security Checklist
Reverse Proxy Setup
For production, run behind a reverse proxy:
server {
listen 80 ;
server_name your-domain.com;
# Frontend
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $ host ;
proxy_set_header X-Real-IP $ remote_addr ;
}
# Backend API
location /api {
proxy_pass http://localhost:8080;
proxy_set_header Host $ host ;
proxy_set_header X-Real-IP $ remote_addr ;
}
}
Troubleshooting
Container Won’t Start
# Check container logs
docker compose logs backend
# Check container status
docker compose ps
# Rebuild from scratch
docker compose down
docker compose build --no-cache
docker compose up -d
Database Connection Issues
# Verify database connectivity from container
docker compose exec backend sh
ping postgres # If using containerized DB
# Check environment variables
docker compose exec backend env | grep DB_
Port Already in Use
# Find process using the port
sudo lsof -i :8080
# Change port in .env
APP_PORT = 8081
# Restart services
docker compose down
docker compose up -d
High Memory Usage
# Check resource usage
docker stats
# Reduce memory limit in docker-compose.yml
# Or increase available system memory
Next Steps
Production Deployment Learn about production deployment strategies
Environment Variables Complete reference for all configuration options