diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2ffd76f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +.git +.git +.gitignore +node_modules +npm-debug.log +yarn.lock +pnpm-lock.yaml +vendor +storage +bootstrap/cache +.env +.env.* +docker-compose*.yml +tests +artifacts diff --git a/.env.docker b/.env.docker new file mode 100644 index 0000000..6302706 --- /dev/null +++ b/.env.docker @@ -0,0 +1,54 @@ +APP_NAME=StyleGallery +APP_ENV=production +APP_KEY=base64:WVUdeK3uPHb0qbhHzkPnqhZwS1TedYQNFLHUohI14mo= +APP_DEBUG=false +APP_URL=https://stylegallery.fotospiel.app + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=info + +DB_CONNECTION=mysql +DB_HOST=mysql +DB_PORT=3306 +DB_DATABASE=stylegallery_prod +DB_USERNAME=sg_b2b7abc82a +DB_PASSWORD=80521323cd53d24a3b370fb74f61c5a3 +DB_ROOT_PASSWORD=7716f61e49044043e987c898f431496b1d35 + +BROADCAST_DRIVER=log +CACHE_DRIVER=redis +FILESYSTEM_DISK=public +QUEUE_CONNECTION=redis +SESSION_DRIVER=redis +SESSION_LIFETIME=120 + +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=redis +REDIS_PASSWORD=704360ffdea7c0e904ca019464a4ec07a9ccd32d +REDIS_PORT=6379 + +MAIL_MAILER=log +MAIL_HOST=localhost +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="info@fotospiel.app" +MAIL_FROM_NAME="${APP_NAME}" + + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_HOST= +PUSHER_PORT=443 +PUSHER_SCHEME=https +PUSHER_APP_CLUSTER=mt1 + +VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +VITE_PUSHER_HOST="${PUSHER_HOST}" +VITE_PUSHER_PORT="${PUSHER_PORT}" +VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" +VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..678cd1c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,69 @@ +FROM php:8.3-fpm-alpine AS php_build + +ENV COMPOSER_ALLOW_SUPERUSER=1 + +RUN set -eux; \ + apk add --no-cache \ + icu-libs \ + libpng \ + libjpeg-turbo \ + freetype \ + libzip \ + bash \ + shadow \ + curl \ + git; \ + apk add --no-cache --virtual .build-deps \ + $PHPIZE_DEPS \ + icu-dev \ + libpng-dev \ + libjpeg-turbo-dev \ + freetype-dev \ + libzip-dev; \ + docker-php-ext-configure gd --with-freetype --with-jpeg; \ + docker-php-ext-install -j"$(nproc)" \ + bcmath \ + gd \ + intl \ + pcntl \ + pdo_mysql \ + zip \ + opcache; \ + pecl install redis; \ + docker-php-ext-enable redis; \ + apk del .build-deps + +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer + +WORKDIR /var/www/html + +COPY composer.json composer.lock ./ + +RUN set -eux; \ + composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction + +COPY . . + +RUN set -eux; \ + mkdir -p storage/app/public storage/logs bootstrap/cache; \ + chown -R www-data:www-data storage bootstrap/cache + +FROM php_build AS php_app + +EXPOSE 9000 + +CMD ["php-fpm"] + +FROM nginx:alpine AS nginx + +WORKDIR /var/www/html + +COPY --from=php_app /var/www/html/public /var/www/html/public +COPY --from=php_app /var/www/html/storage/app/public /var/www/html/storage/app/public + +COPY docker/nginx/default.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 +# syntax=docker/dockerfile:1 + +FROM php:8.3-fpm-alpine AS php_build diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ba1d9a2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,142 @@ +version: "3.9" + +networks: + backend: + +volumes: + mysql_data: + redis_data: + storage_data: + bootstrap_cache: + +services: + app: + build: + context: . + target: php_app + image: stylegallery-app:latest + env_file: + - .env.docker + restart: unless-stopped + command: > + sh -c " + chown -R www-data:www-data storage bootstrap/cache && + php artisan storage:link --ansi || true && + php artisan config:cache --ansi && + php artisan route:cache --ansi && + php artisan view:cache --ansi && + php-fpm + " + volumes: + - storage_data:/var/www/html/storage + - bootstrap_cache:/var/www/html/bootstrap/cache + depends_on: + app: + condition: service_started + mysql: + condition: service_healthy + redis: + condition: service_healthy + networks: + - backend + healthcheck: + test: ["CMD", "php", "-v"] + interval: 30s + timeout: 5s + retries: 3 + + queue: + build: + context: . + target: php_app + image: stylegallery-app:latest + env_file: + - .env.docker + restart: unless-stopped + command: ["sh", "-c", "php artisan queue:work --sleep=3 --tries=3 --max-time=3600"] + volumes: + - storage_data:/var/www/html/storage + - bootstrap_cache:/var/www/html/bootstrap/cache + depends_on: + app: + condition: service_started + mysql: + condition: service_healthy + redis: + condition: service_healthy + networks: + - backend + + scheduler: + build: + context: . + target: php_app + image: stylegallery-app:latest + env_file: + - .env.docker + restart: unless-stopped + command: ["sh", "-c", "php artisan schedule:work"] + volumes: + - storage_data:/var/www/html/storage + - bootstrap_cache:/var/www/html/bootstrap/cache + depends_on: + mysql: + condition: service_healthy + redis: + condition: service_healthy + networks: + - backend + + nginx: + build: + context: . + target: nginx + image: stylegallery-nginx:latest + restart: unless-stopped + depends_on: + app: + condition: service_started + ports: + - "80:80" + networks: + - backend + volumes: + - storage_data:/var/www/html/storage:ro + - bootstrap_cache:/var/www/html/bootstrap/cache:ro + + mysql: + image: mysql:8.0 + env_file: + - .env.docker + restart: unless-stopped + environment: + MYSQL_DATABASE: ${DB_DATABASE} + MYSQL_USER: ${DB_USERNAME} + MYSQL_PASSWORD: ${DB_PASSWORD} + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + command: ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"] + volumes: + - mysql_data:/var/lib/mysql + networks: + - backend + healthcheck: + test: ["CMD-SHELL", "mysqladmin ping -h localhost -p${DB_PASSWORD}"] + interval: 30s + timeout: 10s + retries: 5 + + redis: + image: redis:7-alpine + env_file: + - .env.docker + restart: unless-stopped + command: ["sh", "-c", "exec redis-server --appendonly yes --requirepass \"$REDIS_PASSWORD\""] + volumes: + - redis_data:/data + networks: + - backend + healthcheck: + test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] + interval: 30s + timeout: 5s + retries: 3 diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf new file mode 100644 index 0000000..52663f0 --- /dev/null +++ b/docker/nginx/default.conf @@ -0,0 +1,30 @@ +server { + listen 80; + server_name _; + root /var/www/html/public; + index index.php index.html; + + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-Content-Type-Options "nosniff"; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + try_files $uri =404; + fastcgi_pass app:9000; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + } + + location ~* \.(?:css|js|jpg|jpeg|gif|png|svg|ico|webp|ttf|otf|woff|woff2)$ { + expires 7d; + access_log off; + try_files $uri $uri/ /index.php?$query_string; + } + + client_max_body_size 20m; +}