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 # Production Docker Compose
services: services:
app: app:
image: codeberg.org/lvl0/buckets:latest image: forge.lvl0.xyz/lvl0/buckets:latest
container_name: buckets_app container_name: buckets_app
restart: always restart: always
ports: 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: services:
app: app:
build: build:
context: . context: ../..
dockerfile: Dockerfile.dev dockerfile: Dockerfile.dev
container_name: buckets_app container_name: buckets_dev_app
restart: unless-stopped restart: unless-stopped
# Remove user directive to run as root in container
# The container will handle permissions internally
ports: ports:
- "8100:8000" # Laravel app - "8100:8000"
- "5174:5173" # Vite dev server - "5174:5173"
volumes:
- ../..:/app
- app_vendor:/app/vendor
- app_node_modules:/app/node_modules
environment: environment:
# Laravel
APP_NAME: "${APP_NAME:-buckets}" APP_NAME: "${APP_NAME:-buckets}"
APP_ENV: "${APP_ENV:-local}" APP_ENV: "${APP_ENV:-local}"
APP_KEY: "${APP_KEY:-base64:YOUR_KEY_HERE}" APP_KEY: "${APP_KEY:-base64:YOUR_KEY_HERE}"
APP_DEBUG: "${APP_DEBUG:-true}" APP_DEBUG: "${APP_DEBUG:-true}"
APP_URL: "${APP_URL:-http://localhost:8100}" APP_URL: "${APP_URL:-http://localhost:8100}"
# Database
DB_CONNECTION: mysql DB_CONNECTION: mysql
DB_HOST: db DB_HOST: db
DB_PORT: 3306 DB_PORT: 3306
DB_DATABASE: "${DB_DATABASE:-buckets}" DB_DATABASE: "${DB_DATABASE:-buckets}"
DB_USERNAME: "${DB_USERNAME:-buckets}" DB_USERNAME: "${DB_USERNAME:-buckets}"
DB_PASSWORD: "${DB_PASSWORD:-buckets}" DB_PASSWORD: "${DB_PASSWORD:-buckets}"
# Session & Cache
SESSION_DRIVER: "${SESSION_DRIVER:-file}" SESSION_DRIVER: "${SESSION_DRIVER:-file}"
CACHE_DRIVER: "${CACHE_DRIVER:-file}" CACHE_DRIVER: "${CACHE_DRIVER:-file}"
QUEUE_CONNECTION: "${QUEUE_CONNECTION:-sync}" QUEUE_CONNECTION: "${QUEUE_CONNECTION:-sync}"
# Mail (for development)
MAIL_MAILER: "${MAIL_MAILER:-log}" MAIL_MAILER: "${MAIL_MAILER:-log}"
# Vite
VITE_HOST: "0.0.0.0" VITE_HOST: "0.0.0.0"
VITE_PORT: "5174" 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: depends_on:
- db db:
condition: service_healthy
networks: networks:
- buckets - buckets-network
db: db:
image: mariadb:11 image: mariadb:11
container_name: buckets_db container_name: buckets_dev_db
hostname: db hostname: db
restart: unless-stopped restart: unless-stopped
ports: ports:
@ -65,39 +58,28 @@ services:
MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD:-root}" MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD:-root}"
volumes: volumes:
- db_data:/var/lib/mysql - db_data:/var/lib/mysql
# Initialize with SQL scripts - ../../docker/mysql-init:/docker-entrypoint-initdb.d
- ./docker/mysql-init:/docker-entrypoint-initdb.d
healthcheck: healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 3 retries: 5
start_period: 30s
networks: networks:
- buckets - buckets-network
# Optional: Mailhog for email testing
mailhog: mailhog:
image: mailhog/mailhog image: mailhog/mailhog
container_name: buckets_mailhog container_name: buckets_dev_mailhog
restart: unless-stopped restart: unless-stopped
ports: ports:
- "1026:1025" # SMTP server - "1026:1025"
- "8026:8025" # Web UI - "8026:8025"
networks: networks:
- buckets - buckets-network
# Optional: Redis for caching/sessions
# redis:
# image: redis:alpine
# container_name: buckets_redis
# restart: unless-stopped
# ports:
# - "6379:6379"
# networks:
# - buckets
networks: networks:
buckets: buckets-network:
driver: bridge driver: bridge
volumes: volumes:

257
shell.nix
View file

@ -7,14 +7,14 @@ pkgs.mkShell {
php83Packages.composer php83Packages.composer
# Node.js and npm # Node.js and npm
nodejs_20 nodejs_22
# Container tools # Container tools
podman podman
podman-compose podman-compose
# Database client (optional, for direct DB access) # Database client (for direct DB access)
mariadb-client mariadb.client
# Utilities # Utilities
git git
@ -23,198 +23,125 @@ pkgs.mkShell {
]; ];
shellHook = '' shellHook = ''
# Export user/group IDs for Docker permission matching
export USER_ID=$(id -u) export USER_ID=$(id -u)
export GROUP_ID=$(id -g) export GROUP_ID=$(id -g)
# Use keep-id for proper permission mapping in rootless podman
export PODMAN_USERNS=keep-id export PODMAN_USERNS=keep-id
# Define helper functions # Compose file location
dev-rebuild() { COMPOSE_FILE="$PWD/docker/dev/docker-compose.yml"
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
echo "📦 Installing dependencies..." # ===================
# Wait for containers to be ready # ALIASES
echo " Waiting for containers to be ready..." # ===================
sleep 5 alias pc='podman-compose -f $COMPOSE_FILE'
# 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!"
}
# ===================
# DEV COMMANDS
# ===================
dev-up() { dev-up() {
echo "🚀 Starting development environment..." echo "Starting services..."
PODMAN_USERNS=keep-id podman-compose up -d PODMAN_USERNS=keep-id podman-compose -f $COMPOSE_FILE up -d "$@"
echo " Dev environment started!"
echo "" echo ""
echo "📍 Services available at:" podman-compose -f $COMPOSE_FILE ps
echo " App: http://localhost:8100" echo ""
echo " Vite: http://localhost:5174" echo "App available at: http://localhost:8100"
echo " Mailhog: http://localhost:8026"
echo " MariaDB: localhost:3307"
} }
dev-down() { dev-down() {
echo "🛑 Stopping development environment..." if [[ "$1" == "-v" ]]; then
podman-compose down echo "Stopping services and removing volumes..."
echo " Dev environment stopped!" podman-compose -f $COMPOSE_FILE down -v
else
echo "Stopping services..."
podman-compose -f $COMPOSE_FILE down
fi
} }
dev-restart() { dev-restart() {
echo "🔄 Restarting development environment..." echo "Restarting services..."
podman-compose restart podman-compose -f $COMPOSE_FILE restart "$@"
echo " Dev environment restarted!" }
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() { 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() { dev-shell() {
podman-compose exec app sh podman-compose -f $COMPOSE_FILE exec app sh
} }
dev-artisan() { dev-artisan() {
podman-compose exec app php artisan "$@" podman-compose -f $COMPOSE_FILE exec app php artisan "$@"
} }
dev-fix-permissions() { # ===================
echo "🔧 Fixing file permissions..." # BUILD COMMANDS
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 base-build() {
echo " Permissions fixed!" local image="forge.lvl0.xyz/lvl0/buckets:latest"
}
prod-build() { # Check if logged in, prompt if not
local TAG="''${1:-latest}" if ! podman login --get-login forge.lvl0.xyz &>/dev/null; then
local REGISTRY="codeberg.org" echo "Not logged in to forge.lvl0.xyz"
local NAMESPACE="lvl0" podman login forge.lvl0.xyz || return 1
local IMAGE_NAME="buckets" fi
echo "🔨 Building production image..." echo "Building image: $image"
podman build -f Dockerfile -t ''${REGISTRY}/''${NAMESPACE}/''${IMAGE_NAME}:''${TAG} . if ! podman build -t "$image" -f Dockerfile .; then
echo "Build failed!"
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'"
return 1 return 1
fi fi
}
prod-build-push() { echo ""
local TAG="''${1:-latest}" echo "Pushing to registry..."
prod-build "$TAG" && prod-push "$TAG" if ! podman push "$image"; then
} echo "Push failed!"
return 1
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"
fi 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 ""
''; '';
} }