Move docker-compose to docker/dev, modernize shell.nix, migrate to Forgejo registry

This commit is contained in:
myrmidex 2026-03-19 00:38:13 +01:00
parent 0f02939f27
commit 5614fc3915
3 changed files with 146 additions and 237 deletions

View file

@ -1,7 +1,7 @@
# Production Docker Compose
services:
app:
image: codeberg.org/lvl0/buckets:latest
image: forge.lvl0.xyz/lvl0/buckets:latest
container_name: buckets_app
restart: always
ports:

View file

@ -1,59 +1,52 @@
# Local Development Docker Compose
version: '3.8'
# ===================
# Buckets Development Services
# ===================
# Port allocation:
# App: 8100 (frankenphp), 5174 (vite)
# DB: 3307 (mysql)
# Mailhog: 8026 (web), 1026 (smtp)
services:
app:
build:
context: .
context: ../..
dockerfile: Dockerfile.dev
container_name: buckets_app
container_name: buckets_dev_app
restart: unless-stopped
# Remove user directive to run as root in container
# The container will handle permissions internally
ports:
- "8100:8000" # Laravel app
- "5174:5173" # Vite dev server
- "8100:8000"
- "5174:5173"
volumes:
- ../..:/app
- app_vendor:/app/vendor
- app_node_modules:/app/node_modules
environment:
# Laravel
APP_NAME: "${APP_NAME:-buckets}"
APP_ENV: "${APP_ENV:-local}"
APP_KEY: "${APP_KEY:-base64:YOUR_KEY_HERE}"
APP_DEBUG: "${APP_DEBUG:-true}"
APP_URL: "${APP_URL:-http://localhost:8100}"
# Database
DB_CONNECTION: mysql
DB_HOST: db
DB_PORT: 3306
DB_DATABASE: "${DB_DATABASE:-buckets}"
DB_USERNAME: "${DB_USERNAME:-buckets}"
DB_PASSWORD: "${DB_PASSWORD:-buckets}"
# Session & Cache
SESSION_DRIVER: "${SESSION_DRIVER:-file}"
CACHE_DRIVER: "${CACHE_DRIVER:-file}"
QUEUE_CONNECTION: "${QUEUE_CONNECTION:-sync}"
# Mail (for development)
MAIL_MAILER: "${MAIL_MAILER:-log}"
# Vite
VITE_HOST: "0.0.0.0"
VITE_PORT: "5174"
volumes:
# Mount entire project for hot reload with SELinux context
- .:/app:Z
# Named volumes for performance and permission isolation
- app_vendor:/app/vendor
- app_node_modules:/app/node_modules
depends_on:
- db
db:
condition: service_healthy
networks:
- buckets
- buckets-network
db:
image: mariadb:11
container_name: buckets_db
container_name: buckets_dev_db
hostname: db
restart: unless-stopped
ports:
@ -65,39 +58,28 @@ services:
MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD:-root}"
volumes:
- db_data:/var/lib/mysql
# Initialize with SQL scripts
- ./docker/mysql-init:/docker-entrypoint-initdb.d
- ../../docker/mysql-init:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 3
retries: 5
start_period: 30s
networks:
- buckets
- buckets-network
# Optional: Mailhog for email testing
mailhog:
image: mailhog/mailhog
container_name: buckets_mailhog
container_name: buckets_dev_mailhog
restart: unless-stopped
ports:
- "1026:1025" # SMTP server
- "8026:8025" # Web UI
- "1026:1025"
- "8026:8025"
networks:
- buckets
# Optional: Redis for caching/sessions
# redis:
# image: redis:alpine
# container_name: buckets_redis
# restart: unless-stopped
# ports:
# - "6379:6379"
# networks:
# - buckets
- buckets-network
networks:
buckets:
buckets-network:
driver: bridge
volumes:

257
shell.nix
View file

@ -7,14 +7,14 @@ pkgs.mkShell {
php83Packages.composer
# Node.js and npm
nodejs_20
nodejs_22
# Container tools
podman
podman-compose
# Database client (optional, for direct DB access)
mariadb-client
# Database client (for direct DB access)
mariadb.client
# Utilities
git
@ -23,198 +23,125 @@ pkgs.mkShell {
];
shellHook = ''
# Export user/group IDs for Docker permission matching
export USER_ID=$(id -u)
export GROUP_ID=$(id -g)
# Use keep-id for proper permission mapping in rootless podman
export PODMAN_USERNS=keep-id
# Define helper functions
dev-rebuild() {
echo "🔨 Rebuilding development environment..."
PODMAN_USERNS=keep-id podman-compose down -v
PODMAN_USERNS=keep-id podman-compose build --no-cache app
PODMAN_USERNS=keep-id podman-compose up -d
# Compose file location
COMPOSE_FILE="$PWD/docker/dev/docker-compose.yml"
echo "📦 Installing dependencies..."
# Wait for containers to be ready
echo " Waiting for containers to be ready..."
sleep 5
# Wait for database to be healthy
echo " Waiting for database to be ready..."
for i in {1..30}; do
if podman-compose exec db mariadb -u root -proot -e "SELECT 1" > /dev/null 2>&1; then
echo " Database is ready!"
break
fi
if [ $i -eq 30 ]; then
echo " Database not ready after 30 seconds"
fi
sleep 1
done
# Install composer dependencies
echo " Installing composer packages..."
podman-compose exec app composer install --no-interaction || echo " Composer install failed"
# Install npm dependencies
echo " Installing npm packages..."
podman-compose exec app npm install || echo " NPM install failed"
# Run migrations
echo " Running database migrations..."
sleep 2 # Extra wait to ensure DB is fully ready
podman-compose exec app php artisan migrate --force || echo " Migrations failed"
# Restart app container to ensure Vite picks up all changes
echo " Restarting app container..."
podman-compose restart app
echo " Rebuild complete! Check logs with: dev-logs"
echo ""
echo "📍 Services available at:"
echo " App: http://localhost:8100"
echo " Vite: http://localhost:5174"
echo " Mailhog: http://localhost:8026"
echo " MariaDB: localhost:3307"
}
dev-rebuild-quick() {
echo " Quick rebuild (keeping volumes)..."
PODMAN_USERNS=keep-id podman-compose down
PODMAN_USERNS=keep-id podman-compose build app
PODMAN_USERNS=keep-id podman-compose up -d
echo " Quick rebuild complete!"
}
# ===================
# ALIASES
# ===================
alias pc='podman-compose -f $COMPOSE_FILE'
# ===================
# DEV COMMANDS
# ===================
dev-up() {
echo "🚀 Starting development environment..."
PODMAN_USERNS=keep-id podman-compose up -d
echo " Dev environment started!"
echo "Starting services..."
PODMAN_USERNS=keep-id podman-compose -f $COMPOSE_FILE up -d "$@"
echo ""
echo "📍 Services available at:"
echo " App: http://localhost:8100"
echo " Vite: http://localhost:5174"
echo " Mailhog: http://localhost:8026"
echo " MariaDB: localhost:3307"
podman-compose -f $COMPOSE_FILE ps
echo ""
echo "App available at: http://localhost:8100"
}
dev-down() {
echo "🛑 Stopping development environment..."
podman-compose down
echo " Dev environment stopped!"
if [[ "$1" == "-v" ]]; then
echo "Stopping services and removing volumes..."
podman-compose -f $COMPOSE_FILE down -v
else
echo "Stopping services..."
podman-compose -f $COMPOSE_FILE down
fi
}
dev-restart() {
echo "🔄 Restarting development environment..."
podman-compose restart
echo " Dev environment restarted!"
echo "Restarting services..."
podman-compose -f $COMPOSE_FILE restart "$@"
}
dev-rebuild() {
echo "Rebuilding services (down -v + up)..."
podman-compose -f $COMPOSE_FILE down -v
PODMAN_USERNS=keep-id podman-compose -f $COMPOSE_FILE up -d "$@"
echo ""
podman-compose -f $COMPOSE_FILE ps
echo ""
echo "App available at: http://localhost:8100"
}
dev-logs() {
podman-compose logs -f "$@"
podman-compose -f $COMPOSE_FILE logs -f app "$@"
}
dev-logs-db() {
podman-compose -f $COMPOSE_FILE logs -f db "$@"
}
dev-shell() {
podman-compose exec app sh
podman-compose -f $COMPOSE_FILE exec app sh
}
dev-artisan() {
podman-compose exec app php artisan "$@"
podman-compose -f $COMPOSE_FILE exec app php artisan "$@"
}
dev-fix-permissions() {
echo "🔧 Fixing file permissions..."
echo "This will require sudo to fix Docker-created files"
sudo chown -R $(id -u):$(id -g) storage/ bootstrap/cache/ vendor/ node_modules/ 2>/dev/null || true
echo " Permissions fixed!"
}
# ===================
# BUILD COMMANDS
# ===================
base-build() {
local image="forge.lvl0.xyz/lvl0/buckets:latest"
prod-build() {
local TAG="''${1:-latest}"
local REGISTRY="codeberg.org"
local NAMESPACE="lvl0"
local IMAGE_NAME="buckets"
# Check if logged in, prompt if not
if ! podman login --get-login forge.lvl0.xyz &>/dev/null; then
echo "Not logged in to forge.lvl0.xyz"
podman login forge.lvl0.xyz || return 1
fi
echo "🔨 Building production image..."
podman build -f Dockerfile -t ''${REGISTRY}/''${NAMESPACE}/''${IMAGE_NAME}:''${TAG} .
echo " Build complete: ''${REGISTRY}/''${NAMESPACE}/''${IMAGE_NAME}:''${TAG}"
echo "Run 'prod-push' to push to Codeberg"
}
prod-push() {
local TAG="''${1:-latest}"
local REGISTRY="codeberg.org"
local NAMESPACE="lvl0"
local IMAGE_NAME="buckets"
echo "📤 Pushing to Codeberg registry..."
if podman push ''${REGISTRY}/''${NAMESPACE}/''${IMAGE_NAME}:''${TAG}; then
echo " Image pushed to ''${REGISTRY}/''${NAMESPACE}/''${IMAGE_NAME}:''${TAG}"
else
echo " Failed to push image. Did you run 'prod-build' first?"
echo " Also make sure you're logged in with 'prod-login'"
echo "Building image: $image"
if ! podman build -t "$image" -f Dockerfile .; then
echo "Build failed!"
return 1
fi
}
prod-build-push() {
local TAG="''${1:-latest}"
prod-build "$TAG" && prod-push "$TAG"
}
prod-login() {
echo "📝 Logging into Codeberg registry..."
podman login codeberg.org
}
echo "🚀 Buckets Development Environment"
echo "======================================="
echo "PHP: $(php --version | head -n1)"
echo "Node: $(node --version)"
echo "Podman: $(podman --version)"
echo "Podman-compose: $(podman-compose --version 2>/dev/null || echo 'checking...')"
echo ""
echo "Development commands:"
echo " dev-up - Start development environment"
echo " dev-down - Stop development environment"
echo " dev-restart - Restart containers"
echo " dev-rebuild - Full rebuild (removes volumes)"
echo " dev-rebuild-quick - Quick rebuild (keeps volumes)"
echo " dev-logs [svc] - Follow logs (default: all)"
echo " dev-shell - Enter app container"
echo " dev-artisan - Run artisan commands"
echo " dev-fix-permissions - Fix Docker-created file permissions"
echo ""
echo "Production commands:"
echo " prod-login - Login to Codeberg registry"
echo " prod-build [tag] - Build production image (default: latest)"
echo " prod-push [tag] - Push image to Codeberg"
echo " prod-build-push - Build and push in one command"
echo ""
# Auto-start prompt
if [ -f "docker-compose.yml" ]; then
read -p "Start development containers? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Starting containers..."
podman-compose up -d
# Wait a moment for containers to start
sleep 3
echo ""
echo " Services should be available at:"
echo " App: http://localhost:8100"
echo " Vite: http://localhost:5174"
echo " Mailhog: http://localhost:8026"
echo " MariaDB: localhost:3307"
echo ""
echo "Run 'podman-compose logs -f app' to follow logs"
echo ""
echo "Pushing to registry..."
if ! podman push "$image"; then
echo "Push failed!"
return 1
fi
fi
echo ""
echo "Done! Image pushed: $image"
}
# ===================
# WELCOME MESSAGE
# ===================
echo ""
echo "================================================="
echo " Buckets Dev Environment "
echo "================================================="
echo ""
echo " Podman: $(podman --version | cut -d' ' -f3)"
echo ""
echo "Commands:"
echo " dev-up [services] Start all or specific services"
echo " dev-down [-v] Stop services (-v removes volumes)"
echo " dev-rebuild Fresh start (down -v + up)"
echo " dev-restart Restart services"
echo " dev-logs Tail app logs"
echo " dev-logs-db Tail database logs"
echo " dev-shell Shell into app container"
echo " dev-artisan <cmd> Run artisan command"
echo " base-build Build and push image"
echo ""
echo "Services:"
echo " app Laravel + Vite http://localhost:8100"
echo " db MariaDB localhost:3307"
echo " mailhog Web UI http://localhost:8026"
echo ""
'';
}