commit 57d14dc152ca6caadbe400fa257fd9b564581de2 Author: Boban Blaskovic Date: Fri May 22 00:19:01 2026 +0200 feat(docker): add Dockerfiles + docker-compose.yml with healthchecks Co-Authored-By: Claude Sonnet 4.6 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2614efa --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,121 @@ +services: + app: + build: + context: . + dockerfile: docker/app/Dockerfile + volumes: + - .:/var/www/html + - app_storage:/var/www/html/storage/app + - app_public:/var/www/html/storage/app/public + env_file: .env + depends_on: + mysql: + condition: service_healthy + redis: + condition: service_healthy + networks: [lernschiff_net] + + nginx: + build: + context: ./docker/nginx + dockerfile: Dockerfile + ports: + - "127.0.0.1:8080:80" + volumes: + - .:/var/www/html:ro + - app_public:/var/www/html/storage/app/public:ro + depends_on: [app] + networks: [lernschiff_net] + + queue: + build: + context: . + dockerfile: docker/app/Dockerfile + command: php artisan queue:work --sleep=3 --tries=3 + volumes: + - .:/var/www/html + - app_storage:/var/www/html/storage/app + - app_public:/var/www/html/storage/app/public + env_file: .env + depends_on: + mysql: + condition: service_healthy + redis: + condition: service_healthy + networks: [lernschiff_net] + + scheduler: + build: + context: . + dockerfile: docker/app/Dockerfile + command: sh -c "while true; do php artisan schedule:run --verbose --no-interaction; sleep 60; done" + volumes: + - .:/var/www/html + - app_storage:/var/www/html/storage/app + - app_public:/var/www/html/storage/app/public + env_file: .env + depends_on: + mysql: + condition: service_healthy + redis: + condition: service_healthy + networks: [lernschiff_net] + + reverb: + build: + context: . + dockerfile: docker/app/Dockerfile + command: php artisan reverb:start --host=0.0.0.0 --port=8081 + ports: + - "127.0.0.1:8081:8081" + volumes: + - .:/var/www/html + - app_storage:/var/www/html/storage/app + - app_public:/var/www/html/storage/app/public + env_file: .env + depends_on: [redis] + networks: [lernschiff_net] + + mysql: + image: mysql:8 + environment: + MYSQL_DATABASE: ${DB_DATABASE} + MYSQL_USER: ${DB_USERNAME} + MYSQL_PASSWORD: ${DB_PASSWORD} + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + volumes: + - mysql_data:/var/lib/mysql + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "${DB_USERNAME}", "-p${DB_PASSWORD}"] + interval: 10s + timeout: 5s + retries: 10 + networks: [lernschiff_net] + + redis: + image: redis:7-alpine + volumes: + - redis_data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 3s + retries: 10 + networks: [lernschiff_net] + + mailpit: + image: axllent/mailpit + ports: + - "127.0.0.1:8025:8025" + - "127.0.0.1:1025:1025" + networks: [lernschiff_net] + +networks: + lernschiff_net: + driver: bridge + +volumes: + mysql_data: + redis_data: + app_storage: + app_public: diff --git a/docker/app/Dockerfile b/docker/app/Dockerfile new file mode 100644 index 0000000..b5b8f11 --- /dev/null +++ b/docker/app/Dockerfile @@ -0,0 +1,17 @@ +FROM php:8.4-fpm + +RUN apt-get update && apt-get install -y \ + git curl zip unzip libpng-dev libonig-dev libxml2-dev libzip-dev libicu-dev \ + && docker-php-ext-install pdo_mysql gd zip pcntl intl bcmath exif \ + && pecl install redis && docker-php-ext-enable redis \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer + +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ + && apt-get install -y nodejs + +WORKDIR /var/www/html +COPY . . +RUN composer install --no-dev --optimize-autoloader \ + && chown -R www-data:www-data storage bootstrap/cache diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile new file mode 100644 index 0000000..2fab38a --- /dev/null +++ b/docker/nginx/Dockerfile @@ -0,0 +1,2 @@ +FROM nginx:stable-alpine +COPY default.conf /etc/nginx/conf.d/default.conf diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf new file mode 100644 index 0000000..82a7a4a --- /dev/null +++ b/docker/nginx/default.conf @@ -0,0 +1,55 @@ +# app.dev.lernschiff.com — Livewire SPA + Vite assets +server { + listen 80; + server_name app.dev.lernschiff.com; + root /var/www/html/public; + index index.php; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass app:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + + location /storage { + alias /var/www/html/storage/app/public; + } +} + +# api.dev.lernschiff.com — Laravel JSON API + CORS (Single-Source-of-Truth) +server { + listen 80; + server_name api.dev.lernschiff.com; + root /var/www/html/public; + index index.php; + + # OPTIONS Preflight fast-path + location / { + if ($request_method = OPTIONS) { + add_header Access-Control-Allow-Origin "https://app.dev.lernschiff.com" always; + add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS" always; + add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-XSRF-TOKEN, X-Requested-With" always; + add_header Access-Control-Allow-Credentials "true" always; + add_header Access-Control-Max-Age 86400 always; + add_header Content-Length 0; + return 204; + } + + add_header Access-Control-Allow-Origin "https://app.dev.lernschiff.com" always; + add_header Access-Control-Allow-Credentials "true" always; + + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass app:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } +}