Docker
CI / ci (push) Canceled after 0s

This commit is contained in:
Stefan Lazic committed 2026-09-05 08:36:54 +01:00
1 parent 2ef3654841
commit c4325018e0
7 files changed
+312 -23

No files matched your search

+20 -15
View File
@@ -1,21 +1,26 @@
node_modules
.next
generated
.git .git
.gitea .github
.idea
.vscode
# The previous Next.js application is intentionally outside this build.
legacy-nextjs
node_modules
vendor
.env .env
.env.* .env.*
!.env.example !.env.example
!.env.local.example storage/logs/*
test-results storage/framework/cache/data/*
playwright-report storage/framework/sessions/*
blob-report storage/framework/views/*
playwright/.cache bootstrap/cache/*.php
coverage public/build
docker-compose*.yml
docker-compose*.yaml
*.log
tests
e2e e2e
docs docs
*.md templates
.vscode
.idea
.DS_Store
npm-debug.log*
+9 -4
View File
@@ -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:8000 APP_URL=http://localhost:8085
APP_DEFAULT_BUSINESS_SLUG= APP_DEFAULT_BUSINESS_SLUG=
APP_LOCALE=en APP_LOCALE=en
@@ -22,11 +22,16 @@ LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug LOG_LEVEL=debug
DB_CONNECTION=mysql DB_CONNECTION=mysql
DB_HOST=127.0.0.1 DB_HOST=db
DB_PORT=3306 DB_PORT=3306
DB_DATABASE=nextchair DB_DATABASE=nextchair
DB_USERNAME=root DB_USERNAME=nextchair
DB_PASSWORD= DB_PASSWORD=change-me
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
View File
@@ -0,0 +1,83 @@
# 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
+48 -4
View File
@@ -5,10 +5,9 @@ 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. Deployment-specific files as the functional and visual migration reference. The Laravel application has
from the previous implementation are retained there for reference only; the its own deployment-neutral Docker option at the repository root; files inside
Laravel application does not manage Docker, Caddy, Nginx, or server `legacy-nextjs` are not used by it.
provisioning.
## Local development ## Local development
@@ -26,6 +25,51 @@ 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
View File
@@ -0,0 +1,102 @@
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:
+24
View File
@@ -0,0 +1,24 @@
#!/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 "$@"
+26
View File
@@ -0,0 +1,26 @@
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; }
}