1 - Add Nix shell and Docker dev environment

This commit is contained in:
myrmidex 2026-04-23 03:00:07 +02:00
parent d377f7601c
commit 541cc8a3e7
5 changed files with 376 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/.idea/

125
Dockerfile.dev Normal file
View file

@ -0,0 +1,125 @@
# Development Dockerfile with FrankenPHP
FROM dunglas/frankenphp:latest-php8.3-alpine
# Install system dependencies
RUN apk add --no-cache \
git \
postgresql-client \
vim \
bash \
nano \
curl
# Install Node.js 20.19.0+ from unofficial builds (for Vite 7 compatibility)
RUN curl -fsSL https://unofficial-builds.nodejs.org/download/release/v20.19.0/node-v20.19.0-linux-x64-musl.tar.xz | tar -xJ -C /usr/local --strip-components=1
# Install PHP extensions including xdebug for development
RUN install-php-extensions \
pdo_pgsql \
opcache \
zip \
gd \
intl \
redis \
xdebug
# Install Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /app
# Configure PHP for development
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
# Configure Xdebug (disabled by default to reduce noise)
RUN echo "xdebug.mode=off" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
&& echo ";xdebug.mode=debug" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
&& echo ";xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
&& echo ";xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
# Configure Caddy for development
RUN cat > /etc/caddy/Caddyfile <<EOF
{
frankenphp
order php_server before file_server
}
:8000 {
root * /app/public
php_server {
index index.php
}
encode gzip
file_server
# Less strict headers for development
header {
X-Frame-Options "SAMEORIGIN"
}
}
EOF
# Create startup script for development
RUN cat > /start.sh <<'EOF'
#!/bin/sh
set -e
# Create .env file if it doesn't exist
if [ ! -f ".env" ]; then
echo "Creating .env file from .env.example..."
cp .env.example .env
fi
# Install composer dependencies if vendor is empty
if [ ! -f "vendor/autoload.php" ]; then
echo "Installing Composer dependencies..."
composer install --no-interaction
fi
# Install npm dependencies if node_modules is empty
if [ ! -d "node_modules" ] && [ -f "package.json" ]; then
echo "Installing npm dependencies..."
npm install
fi
# Clear Laravel caches
php artisan config:clear || true
php artisan cache:clear || true
# Wait for database
echo "Waiting for database..."
until pg_isready -h db -U trove -q; do
echo "Database not ready, retrying..."
sleep 2
done
echo "Database is ready!"
# Generate app key if not set
if grep -q "^APP_KEY=$" .env 2>/dev/null; then
echo "Generating application key..."
php artisan key:generate
fi
# Run migrations
php artisan migrate --force
# Start Vite dev server in background (if package.json exists)
if [ -f "package.json" ]; then
npm run dev &
fi
# Start FrankenPHP
exec frankenphp run --config /etc/caddy/Caddyfile
EOF
RUN chmod +x /start.sh
# Expose ports
EXPOSE 8000 5173
# Use the startup script
CMD ["/start.sh"]

View file

@ -1,2 +1,3 @@
# trove # trove
A small web search engine.

View file

@ -0,0 +1,96 @@
# ===================
# Trove Development Services
# ===================
# Port allocation:
# App: 8200 (frankenphp), 5175 (vite)
# DB: 5433 (postgresql)
# Redis: 6380
services:
app:
build:
context: ../..
dockerfile: Dockerfile.dev
container_name: trove_dev_app
restart: unless-stopped
ports:
- "8200:8000"
- "5175:5173"
volumes:
- ../..:/app
- app_vendor:/app/vendor
- app_node_modules:/app/node_modules
environment:
APP_NAME: "${APP_NAME:-Trove}"
APP_ENV: "${APP_ENV:-local}"
APP_DEBUG: "${APP_DEBUG:-true}"
APP_URL: "${APP_URL:-http://localhost:8200}"
DB_CONNECTION: pgsql
DB_HOST: db
DB_PORT: 5432
DB_DATABASE: "${DB_DATABASE:-trove}"
DB_USERNAME: "${DB_USERNAME:-trove}"
DB_PASSWORD: "${DB_PASSWORD:-trove}"
REDIS_HOST: redis
REDIS_PORT: 6379
SESSION_DRIVER: "${SESSION_DRIVER:-database}"
CACHE_STORE: "${CACHE_STORE:-redis}"
QUEUE_CONNECTION: "${QUEUE_CONNECTION:-redis}"
MAIL_MAILER: "${MAIL_MAILER:-log}"
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks:
- trove-network
db:
image: postgres:17-alpine
container_name: trove_dev_db
hostname: db
restart: unless-stopped
ports:
- "5433:5432"
environment:
POSTGRES_DB: "${DB_DATABASE:-trove}"
POSTGRES_USER: "${DB_USERNAME:-trove}"
POSTGRES_PASSWORD: "${DB_PASSWORD:-trove}"
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-trove}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
- trove-network
redis:
image: redis:7-alpine
container_name: trove_dev_redis
hostname: redis
restart: unless-stopped
ports:
- "6380:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 5s
networks:
- trove-network
networks:
trove-network:
driver: bridge
volumes:
db_data:
redis_data:
app_vendor:
app_node_modules:

153
shell.nix Normal file
View file

@ -0,0 +1,153 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = with pkgs; [
# PHP and tools
php83
php83Packages.composer
# Node.js (needed for Tailwind CSS / Vite)
nodejs_22
# Container tools
podman
podman-compose
# Database client
postgresql
# Utilities
git
curl
gnumake
];
shellHook = ''
export USER_ID=$(id -u)
export GROUP_ID=$(id -g)
export PODMAN_USERNS=keep-id
# Compose file location
COMPOSE_FILE="$PWD/docker/dev/docker-compose.yml"
# ===================
# ALIASES
# ===================
alias pc='podman-compose -f $COMPOSE_FILE'
# ===================
# DEV COMMANDS
# ===================
dev-up() {
echo "Starting services..."
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:8200"
}
dev-down() {
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 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:8200"
}
dev-logs() {
podman-compose -f $COMPOSE_FILE logs -f app "$@"
}
dev-logs-db() {
podman-compose -f $COMPOSE_FILE logs -f db "$@"
}
dev-logs-redis() {
podman-compose -f $COMPOSE_FILE logs -f redis "$@"
}
dev-shell() {
podman-compose -f $COMPOSE_FILE exec app bash
}
dev-artisan() {
podman-compose -f $COMPOSE_FILE exec app php artisan "$@"
}
# ===================
# BUILD COMMANDS
# ===================
base-build() {
local image="forge.lvl0.xyz/lvl0/trove:latest"
# 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 image: $image"
if ! podman build -t "$image" -f Dockerfile .; then
echo "Build failed!"
return 1
fi
echo ""
echo "Pushing to registry..."
if ! podman push "$image"; then
echo "Push failed!"
return 1
fi
echo ""
echo "Done! Image pushed: $image"
}
# ===================
# WELCOME MESSAGE
# ===================
echo ""
echo "================================================="
echo " Trove 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-logs-redis Tail Redis 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 http://localhost:8200"
echo " vite HMR http://localhost:5175"
echo " db PostgreSQL localhost:5433"
echo " redis Redis localhost:6380"
echo ""
'';
}