Deployment
V1 — Docker Compose + Traefik
The repository root already ships a docker-compose.yml with:
server— PHP-FPM running Laravel.queue— runsphp artisan queue:work.scheduler— runsphp artisan schedule:work.nginx-server— front door for the Laravel API.ui— production React build served by Nginx.mysql— MySQL 8 data store.phpmyadmin— ops console.traefik(external networkweb) — TLS termination via Let's Encrypt.
Environment Variables
Top-level .env (already present) feeds Compose:
PROJECT_NAME=attendance
DOMAIN=example.com
HOST_NAME_SERVER=${PROJECT_NAME}-api.${DOMAIN}
HOST_NAME_UI=${PROJECT_NAME}.${DOMAIN}
HOST_NAME_PMA=${PROJECT_NAME}-pma.${DOMAIN}
MYSQL_ROOT_PASSWORD=change-me
MYSQL_DATABASE=${PROJECT_NAME}_db
MYSQL_USER=${PROJECT_NAME}_user
MYSQL_PASSWORD=change-me
Laravel-specific variables live in server/.env (created from .env.example on first setup).
Bring-Up
# 1. Shared external network for Traefik
docker network create web
# 2. Build and start
docker compose up -d --build
# 3. First-time Laravel setup (run once)
docker compose exec server php artisan key:generate
docker compose exec server php artisan migrate --seed
docker compose exec server php artisan horizon:install
Horizon
Horizon is the queue supervisor. In V1 Compose, point the queue service at Horizon:
queue:
build: { context: ., dockerfile: docker/server/Dockerfile }
command: php artisan horizon
Migration Path to Kubernetes
- Each container is stateless; swap Compose for a Helm chart.
- MySQL and Redis move to managed services (RDS, ElastiCache).
- Exports write to S3 instead of a local volume.
- Horizon runs as a
Deploymentscaled on queue depth. - Use an ingress-nginx or ALB instead of Traefik.