7 files changed
+23
-312
No files matched your search
+15
-20
@@ -1,26 +1,21 @@
|
|||||||
.git
|
|
||||||
.github
|
|
||||||
.idea
|
|
||||||
.vscode
|
|
||||||
|
|
||||||
# The previous Next.js application is intentionally outside this build.
|
|
||||||
legacy-nextjs
|
|
||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
vendor
|
.next
|
||||||
|
generated
|
||||||
|
.git
|
||||||
|
.gitea
|
||||||
.env
|
.env
|
||||||
.env.*
|
.env.*
|
||||||
!.env.example
|
!.env.example
|
||||||
storage/logs/*
|
!.env.local.example
|
||||||
storage/framework/cache/data/*
|
test-results
|
||||||
storage/framework/sessions/*
|
playwright-report
|
||||||
storage/framework/views/*
|
blob-report
|
||||||
bootstrap/cache/*.php
|
playwright/.cache
|
||||||
public/build
|
coverage
|
||||||
docker-compose*.yml
|
|
||||||
docker-compose*.yaml
|
|
||||||
*.log
|
|
||||||
tests
|
|
||||||
e2e
|
e2e
|
||||||
docs
|
docs
|
||||||
templates
|
*.md
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
npm-debug.log*
|
||||||
+4
-9
@@ -2,7 +2,7 @@ APP_NAME=NextChair
|
|||||||
APP_ENV=local
|
APP_ENV=local
|
||||||
APP_KEY=
|
APP_KEY=
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
APP_URL=http://localhost:8085
|
APP_URL=http://localhost:8000
|
||||||
APP_DEFAULT_BUSINESS_SLUG=
|
APP_DEFAULT_BUSINESS_SLUG=
|
||||||
|
|
||||||
APP_LOCALE=en
|
APP_LOCALE=en
|
||||||
@@ -22,16 +22,11 @@ LOG_DEPRECATIONS_CHANNEL=null
|
|||||||
LOG_LEVEL=debug
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=db
|
DB_HOST=127.0.0.1
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
DB_DATABASE=nextchair
|
DB_DATABASE=nextchair
|
||||||
DB_USERNAME=nextchair
|
DB_USERNAME=root
|
||||||
DB_PASSWORD=change-me
|
DB_PASSWORD=
|
||||||
DB_ROOT_PASSWORD=change-me-root
|
|
||||||
|
|
||||||
# Docker publishes Nginx on this local bind address by default.
|
|
||||||
NEXTCHAIR_HTTP_BIND=127.0.0.1
|
|
||||||
NEXTCHAIR_HTTP_PORT=8085
|
|
||||||
|
|
||||||
SESSION_DRIVER=database
|
SESSION_DRIVER=database
|
||||||
SESSION_LIFETIME=120
|
SESSION_LIFETIME=120
|
||||||
|
|||||||
-83
@@ -1,83 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
|
|
||||||
FROM node:22-bookworm-slim AS frontend
|
|
||||||
|
|
||||||
WORKDIR /var/www/html
|
|
||||||
|
|
||||||
COPY package.json package-lock.json ./
|
|
||||||
RUN npm ci
|
|
||||||
|
|
||||||
COPY resources ./resources
|
|
||||||
COPY public ./public
|
|
||||||
COPY vite.config.js .
|
|
||||||
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
|
|
||||||
FROM composer:2 AS composer
|
|
||||||
|
|
||||||
|
|
||||||
FROM php:8.4-fpm-bookworm AS app
|
|
||||||
|
|
||||||
ENV COMPOSER_ALLOW_SUPERUSER=1 \
|
|
||||||
PHP_OPCACHE_VALIDATE_TIMESTAMPS=0
|
|
||||||
|
|
||||||
WORKDIR /var/www/html
|
|
||||||
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get install -y --no-install-recommends \
|
|
||||||
gosu \
|
|
||||||
libfreetype6-dev \
|
|
||||||
libicu-dev \
|
|
||||||
libjpeg62-turbo-dev \
|
|
||||||
libonig-dev \
|
|
||||||
libpng-dev \
|
|
||||||
libxml2-dev \
|
|
||||||
libzip-dev \
|
|
||||||
unzip \
|
|
||||||
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
|
|
||||||
&& docker-php-ext-install -j"$(nproc)" \
|
|
||||||
bcmath \
|
|
||||||
exif \
|
|
||||||
gd \
|
|
||||||
intl \
|
|
||||||
mbstring \
|
|
||||||
opcache \
|
|
||||||
pcntl \
|
|
||||||
pdo_mysql \
|
|
||||||
xml \
|
|
||||||
zip \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
COPY --from=composer /usr/bin/composer /usr/bin/composer
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
COPY --from=frontend /var/www/html/public/build ./public/build
|
|
||||||
|
|
||||||
RUN composer install --no-dev --optimize-autoloader --no-interaction --prefer-dist \
|
|
||||||
&& mkdir -p \
|
|
||||||
storage/framework/cache/data \
|
|
||||||
storage/framework/sessions \
|
|
||||||
storage/framework/views \
|
|
||||||
storage/logs \
|
|
||||||
bootstrap/cache \
|
|
||||||
&& chown -R www-data:www-data storage bootstrap/cache \
|
|
||||||
&& chmod -R ug+rwX storage bootstrap/cache
|
|
||||||
|
|
||||||
COPY docker/entrypoint.sh /usr/local/bin/nextchair-entrypoint
|
|
||||||
RUN chmod +x /usr/local/bin/nextchair-entrypoint
|
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/local/bin/nextchair-entrypoint"]
|
|
||||||
CMD ["php-fpm", "-F"]
|
|
||||||
|
|
||||||
|
|
||||||
FROM nginx:1.27-alpine AS nginx
|
|
||||||
|
|
||||||
WORKDIR /var/www/html
|
|
||||||
|
|
||||||
COPY public ./public
|
|
||||||
COPY --from=frontend /var/www/html/public/build ./public/build
|
|
||||||
COPY docker/nginx/default.conf /etc/nginx/conf.d/default.conf
|
|
||||||
|
|
||||||
RUN mkdir -p /var/www/html/storage/app/public \
|
|
||||||
&& ln -s /var/www/html/storage/app/public /var/www/html/public/storage
|
|
||||||
@@ -5,9 +5,10 @@ The application is being rebuilt as a conventional Laravel web application
|
|||||||
using PHP, MySQL, Blade, Tailwind CSS, Alpine.js, and Vite.
|
using PHP, MySQL, Blade, Tailwind CSS, Alpine.js, and Vite.
|
||||||
|
|
||||||
The audited Next.js implementation is preserved in [`legacy-nextjs`](legacy-nextjs)
|
The audited Next.js implementation is preserved in [`legacy-nextjs`](legacy-nextjs)
|
||||||
as the functional and visual migration reference. The Laravel application has
|
as the functional and visual migration reference. Deployment-specific files
|
||||||
its own deployment-neutral Docker option at the repository root; files inside
|
from the previous implementation are retained there for reference only; the
|
||||||
`legacy-nextjs` are not used by it.
|
Laravel application does not manage Docker, Caddy, Nginx, or server
|
||||||
|
provisioning.
|
||||||
|
|
||||||
## Local development
|
## Local development
|
||||||
|
|
||||||
@@ -25,51 +26,6 @@ application resolves a business from the request hostname through the
|
|||||||
`business_domains` table. Local development can use a configured local domain
|
`business_domains` table. Local development can use a configured local domain
|
||||||
or the `APP_DEFAULT_BUSINESS_SLUG` fallback.
|
or the `APP_DEFAULT_BUSINESS_SLUG` fallback.
|
||||||
|
|
||||||
## Docker deployment
|
|
||||||
|
|
||||||
The root `compose.yaml` runs Laravel with PHP 8.4 FPM, Nginx, MySQL 8,
|
|
||||||
the database-backed queue worker, and the scheduler. It does not include or
|
|
||||||
configure Caddy; an existing reverse proxy can forward traffic to Nginx on
|
|
||||||
`127.0.0.1:8085`.
|
|
||||||
|
|
||||||
First run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp .env.example .env
|
|
||||||
```
|
|
||||||
|
|
||||||
Set private values in `.env`, including:
|
|
||||||
|
|
||||||
```dotenv
|
|
||||||
APP_URL=http://localhost:8085
|
|
||||||
APP_KEY=
|
|
||||||
DB_HOST=db
|
|
||||||
DB_DATABASE=nextchair
|
|
||||||
DB_USERNAME=nextchair
|
|
||||||
DB_PASSWORD=replace-with-a-private-password
|
|
||||||
DB_ROOT_PASSWORD=replace-with-a-private-root-password
|
|
||||||
```
|
|
||||||
|
|
||||||
Then build and start the stack:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose build
|
|
||||||
docker compose up -d
|
|
||||||
docker compose exec app php artisan key:generate
|
|
||||||
docker compose exec app php artisan migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
Migrations are intentionally not run by container startup. To inspect the
|
|
||||||
application logs:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose logs -f app nginx queue scheduler db
|
|
||||||
```
|
|
||||||
|
|
||||||
The default host binding is `127.0.0.1:8085:80`. Override it with
|
|
||||||
`NEXTCHAIR_HTTP_BIND` and `NEXTCHAIR_HTTP_PORT` in `.env` when needed. MySQL
|
|
||||||
has no published host port and is reachable only as `db:3306` inside Compose.
|
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
-102
@@ -1,102 +0,0 @@
|
|||||||
services:
|
|
||||||
app:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: app
|
|
||||||
image: nextchair-laravel:latest
|
|
||||||
restart: unless-stopped
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
environment:
|
|
||||||
APP_ENV: ${APP_ENV:-production}
|
|
||||||
APP_DEBUG: ${APP_DEBUG:-false}
|
|
||||||
APP_URL: ${APP_URL:-http://localhost:8085}
|
|
||||||
DB_CONNECTION: mysql
|
|
||||||
DB_HOST: db
|
|
||||||
DB_PORT: 3306
|
|
||||||
DB_DATABASE: ${DB_DATABASE:-nextchair}
|
|
||||||
DB_USERNAME: ${DB_USERNAME:-nextchair}
|
|
||||||
DB_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD in .env}
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
volumes:
|
|
||||||
- nextchair_storage:/var/www/html/storage
|
|
||||||
|
|
||||||
nginx:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: nginx
|
|
||||||
image: nextchair-nginx:latest
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
- app
|
|
||||||
ports:
|
|
||||||
- "${NEXTCHAIR_HTTP_BIND:-127.0.0.1}:${NEXTCHAIR_HTTP_PORT:-8085}:80"
|
|
||||||
volumes:
|
|
||||||
- nextchair_storage:/var/www/html/storage:ro
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: mysql:8.4
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
MYSQL_DATABASE: ${DB_DATABASE:-nextchair}
|
|
||||||
MYSQL_USER: ${DB_USERNAME:-nextchair}
|
|
||||||
MYSQL_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD in .env}
|
|
||||||
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:?Set DB_ROOT_PASSWORD in .env}
|
|
||||||
volumes:
|
|
||||||
- nextchair_mysql_data:/var/lib/mysql
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -p$$MYSQL_ROOT_PASSWORD --silent"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 20
|
|
||||||
start_period: 20s
|
|
||||||
|
|
||||||
queue:
|
|
||||||
image: nextchair-laravel:latest
|
|
||||||
restart: unless-stopped
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
environment:
|
|
||||||
APP_ENV: ${APP_ENV:-production}
|
|
||||||
APP_DEBUG: ${APP_DEBUG:-false}
|
|
||||||
DB_CONNECTION: mysql
|
|
||||||
DB_HOST: db
|
|
||||||
DB_PORT: 3306
|
|
||||||
DB_DATABASE: ${DB_DATABASE:-nextchair}
|
|
||||||
DB_USERNAME: ${DB_USERNAME:-nextchair}
|
|
||||||
DB_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD in .env}
|
|
||||||
command: ["php", "artisan", "queue:work", "--sleep=3", "--tries=3", "--timeout=90"]
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
volumes:
|
|
||||||
- nextchair_storage:/var/www/html/storage
|
|
||||||
|
|
||||||
scheduler:
|
|
||||||
image: nextchair-laravel:latest
|
|
||||||
restart: unless-stopped
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
environment:
|
|
||||||
APP_ENV: ${APP_ENV:-production}
|
|
||||||
APP_DEBUG: ${APP_DEBUG:-false}
|
|
||||||
DB_CONNECTION: mysql
|
|
||||||
DB_HOST: db
|
|
||||||
DB_PORT: 3306
|
|
||||||
DB_DATABASE: ${DB_DATABASE:-nextchair}
|
|
||||||
DB_USERNAME: ${DB_USERNAME:-nextchair}
|
|
||||||
DB_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD in .env}
|
|
||||||
command: ["php", "artisan", "schedule:work"]
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
volumes:
|
|
||||||
- nextchair_storage:/var/www/html/storage
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
nextchair_mysql_data:
|
|
||||||
nextchair_storage:
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
cd /var/www/html
|
|
||||||
|
|
||||||
mkdir -p \
|
|
||||||
storage/framework/cache/data \
|
|
||||||
storage/framework/sessions \
|
|
||||||
storage/framework/views \
|
|
||||||
storage/logs \
|
|
||||||
bootstrap/cache
|
|
||||||
|
|
||||||
chown -R www-data:www-data storage bootstrap/cache
|
|
||||||
chmod -R ug+rwX storage bootstrap/cache
|
|
||||||
|
|
||||||
# This is safe to run on every start and does not perform migrations.
|
|
||||||
php artisan storage:link --force >/dev/null 2>&1 || true
|
|
||||||
|
|
||||||
if [ "$(id -u)" = "0" ]; then
|
|
||||||
exec gosu www-data "$@"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec "$@"
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
root /var/www/html/public;
|
|
||||||
index index.php;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.php?$query_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
location = /favicon.ico { access_log off; log_not_found off; }
|
|
||||||
location = /robots.txt { access_log off; log_not_found off; }
|
|
||||||
|
|
||||||
location ~ \.php$ {
|
|
||||||
try_files $uri =404;
|
|
||||||
include fastcgi_params;
|
|
||||||
fastcgi_param SCRIPT_FILENAME /var/www/html/public$fastcgi_script_name;
|
|
||||||
fastcgi_param DOCUMENT_ROOT /var/www/html/public;
|
|
||||||
fastcgi_pass app:9000;
|
|
||||||
fastcgi_read_timeout 90s;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ /\. { deny all; }
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user