docker: php 8.5 & typesense & bump elastic and mysql (#1201)

This commit is contained in:
Kyrch
2026-05-09 23:42:40 -03:00
committed by GitHub
parent e0ea789eeb
commit 65a723f9b5
14 changed files with 90 additions and 158 deletions
+13 -10
View File
@@ -12,6 +12,7 @@ AUDITING_ENABLED=true
APP_URL=http://localhost APP_URL=http://localhost
ASSET_URL=null ASSET_URL=null
APP_KEY= APP_KEY=
APP_LOCAL_IPS=
# audio # audio
AUDIO_DISK_DEFAULT=audios_local AUDIO_DISK_DEFAULT=audios_local
@@ -84,7 +85,7 @@ REDIS_CACHE_DB=1
# dump # dump
DUMP_DISK=dumps_local DUMP_DISK=dumps_local
DUMP_DISK_ROOT= DUMP_DISK_ROOT=
DUMP_URL=http://localhost DUMP_URL="${APP_URL}"
DUMP_PATH=/dump DUMP_PATH=/dump
# external profile # external profile
@@ -168,12 +169,14 @@ SCRIPT_DISABLE_ASSERTS=
SCRIPT_VISIBILITY= SCRIPT_VISIBILITY=
# fortify # fortify
FORTIFY_HOME=http://localhost FORTIFY_HOME="${APP_URL}"
FORTIFY_PATH= FORTIFY_PATH=
FORTIFY_URL=http://localhost FORTIFY_URL="${APP_URL}"
# graphql # graphql
GRAPHQL_URL= GRAPHIQL_URL="${GRAPHQL_URL}/graphiql"
GRAPHIQL_GRAPHQL_ENDPOINT="${GRAPHQL_URL}"
GRAPHQL_URL="${APP_URL}"
GRAPHQL_PATH=/graphql GRAPHQL_PATH=/graphql
GRAPHIQL_ENABLED=true GRAPHIQL_ENABLED=true
@@ -288,21 +291,21 @@ VIDEO_DISK_DEFAULT=videos_local
VIDEO_DISKS=videos_local VIDEO_DISKS=videos_local
VIDEO_DISK_ROOT= VIDEO_DISK_ROOT=
VIDEO_PATH=/video VIDEO_PATH=/video
VIDEO_URL= VIDEO_URL="${APP_URL}"
VIDEO_RATE_LIMITER=90 VIDEO_RATE_LIMITER=90
VIDEO_STREAMING_METHOD=response VIDEO_STREAMING_METHOD=response
VIDEO_NGINX_REDIRECT= VIDEO_NGINX_REDIRECT=
SCRIPT_DISK=scripts_local SCRIPT_DISK=scripts_local
SCRIPT_DISK_ROOT= SCRIPT_DISK_ROOT=
SCRIPT_URL= SCRIPT_URL="${APP_URL}"
SCRIPT_PATH=/videoscript SCRIPT_PATH=/videoscript
# web # web
WEB_URL=http://localhost WEB_URL="${APP_URL}:3000"
WEB_PATH= WEB_PATH=
# wiki # wiki
WIKI_LOGIN=http://localhost/login WIKI_LOGIN="h${APP_URL}:3000/login"
WIKI_RESET_PASSWORD=http://localhost/reset-password WIKI_RESET_PASSWORD="${APP_URL}:3000/reset-password"
WIKI_EXTERNAL_PROFILE=http://localhost/external WIKI_EXTERNAL_PROFILE="${APP_URL}:3000/external"
+14 -11
View File
@@ -12,6 +12,7 @@ AUDITING_ENABLED=true
APP_URL=http://localhost APP_URL=http://localhost
ASSET_URL=null ASSET_URL=null
APP_KEY= APP_KEY=
APP_LOCAL_IPS=
# audio # audio
AUDIO_DISK_DEFAULT=audios_local AUDIO_DISK_DEFAULT=audios_local
@@ -85,7 +86,7 @@ REDIS_CACHE_DB=1
# dump # dump
DUMP_DISK=dumps DUMP_DISK=dumps
DUMP_DISK_ROOT= DUMP_DISK_ROOT=
DUMP_URL=http://localhost DUMP_URL="${APP_URL}"
DUMP_PATH=/dump DUMP_PATH=/dump
# ffmpeg # ffmpeg
@@ -166,12 +167,14 @@ SCRIPT_DISABLE_ASSERTS=
SCRIPT_VISIBILITY= SCRIPT_VISIBILITY=
# fortify # fortify
FORTIFY_HOME=http://localhost:3000 FORTIFY_HOME="${APP_URL}":3000
FORTIFY_PATH= FORTIFY_PATH=
FORTIFY_URL=http://localhost FORTIFY_URL="${APP_URL}"
# graphql # graphql
GRAPHQL_URL= GRAPHIQL_URL="${GRAPHQL_URL}/graphiql"
GRAPHIQL_GRAPHQL_ENDPOINT="${GRAPHQL_URL}"
GRAPHQL_URL="${APP_URL}"
GRAPHQL_PATH=/graphql GRAPHQL_PATH=/graphql
GRAPHIQL_ENABLED=true GRAPHIQL_ENABLED=true
@@ -236,7 +239,7 @@ ELASTIC_HOST=http://elasticsearch:9200
ELASTIC_SCOUT_DRIVER_REFRESH_DOCUMENTS=false ELASTIC_SCOUT_DRIVER_REFRESH_DOCUMENTS=false
ELASTIC_MIGRATIONS_TABLE=elastic_migrations ELASTIC_MIGRATIONS_TABLE=elastic_migrations
TYPESENSE_HOST=localhost TYPESENSE_HOST=typesense
TYPESENSE_PORT=8108 TYPESENSE_PORT=8108
TYPESENSE_PROTOCOL=http TYPESENSE_PROTOCOL=http
TYPESENSE_API_KEY= TYPESENSE_API_KEY=
@@ -286,21 +289,21 @@ VIDEO_DISK_DEFAULT=videos_local
VIDEO_DISKS=videos_local VIDEO_DISKS=videos_local
VIDEO_DISK_ROOT= VIDEO_DISK_ROOT=
VIDEO_PATH=/video VIDEO_PATH=/video
VIDEO_URL= VIDEO_URL="${APP_URL}"
VIDEO_RATE_LIMITER=90 VIDEO_RATE_LIMITER=90
VIDEO_STREAMING_METHOD=response VIDEO_STREAMING_METHOD=response
VIDEO_NGINX_REDIRECT= VIDEO_NGINX_REDIRECT=
SCRIPT_DISK=scripts_local SCRIPT_DISK=scripts_local
SCRIPT_DISK_ROOT= SCRIPT_DISK_ROOT=
SCRIPT_URL= SCRIPT_URL="${APP_URL}"
SCRIPT_PATH=/videoscript SCRIPT_PATH=/videoscript
# web # web
WEB_URL=http://localhost WEB_URL="${APP_URL}:3000"
WEB_PATH= WEB_PATH=
# wiki # wiki
WIKI_LOGIN=http://localhost/login WIKI_LOGIN="${APP_URL}:3000/login"
WIKI_RESET_PASSWORD=http://localhost/reset-password WIKI_RESET_PASSWORD="${APP_URL}:3000/reset-password"
WIKI_EXTERNAL_PROFILE=http://localhost/external WIKI_EXTERNAL_PROFILE="${APP_URL}:3000/external"
@@ -7,6 +7,7 @@ namespace App\Http\Middleware\Api;
use App\Constants\FeatureConstants; use App\Constants\FeatureConstants;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Laravel\Pennant\Feature; use Laravel\Pennant\Feature;
class EnabledOnlyOnLocalhost class EnabledOnlyOnLocalhost
@@ -17,8 +18,7 @@ class EnabledOnlyOnLocalhost
public function handle(Request $request, Closure $next): mixed public function handle(Request $request, Closure $next): mixed
{ {
if (Feature::for(null)->active(FeatureConstants::ENABLED_ONLY_ON_LOCALHOST)) { if (Feature::for(null)->active(FeatureConstants::ENABLED_ONLY_ON_LOCALHOST)) {
$ip = $request->ip(); abort_if(!in_array($request->ip(), Config::array('app.local_ips'), true), 403, 'Route only available for localhost');
abort_if($ip !== '127.0.0.1', 403, 'Route only available for localhost');
} }
return $next($request); return $next($request);
+1 -1
View File
@@ -29,6 +29,6 @@ class MaxCount
*/ */
private function isLocal(Request $request): bool private function isLocal(Request $request): bool
{ {
return $request->ip() === '127.0.0.1'; return in_array($request->ip(), Config::array('app.local_ips'), true);
} }
} }
+6 -4
View File
@@ -33,16 +33,17 @@ class RouteServiceProvider extends ServiceProvider
RateLimiter::for('api', function (Request $request) { RateLimiter::for('api', function (Request $request) {
$user = $request->user(); $user = $request->user();
$ip = $request->ip(); $ip = $request->ip();
$isLocal = in_array($ip, Config::array('app.local_ips'), true);
$forwardedIp = $request->header('x-forwarded-ip'); $forwardedIp = $request->header('x-forwarded-ip');
// (If request is from client and no forwarded ip) or (the user logged in has permission to bypass API rate limiting) // (If request is from client and no forwarded ip) or (the user logged in has permission to bypass API rate limiting)
/** @phpstan-ignore-next-line */ /** @phpstan-ignore-next-line */
if (($ip === '127.0.0.1' && ! $forwardedIp) || ($user instanceof User && $user->can(SpecialPermission::BYPASS_API_RATE_LIMITER->value))) { if (($isLocal && ! $forwardedIp) || ($user instanceof User && $user->can(SpecialPermission::BYPASS_API_RATE_LIMITER->value))) {
return Limit::none(); return Limit::none();
} }
// Check if request is from client to prevent users from using forwarded ip // Check if request is from client to prevent users from using forwarded ip
if ($ip === '127.0.0.1' && $forwardedIp) { if ($isLocal && $forwardedIp) {
$ip = $forwardedIp; $ip = $forwardedIp;
} }
@@ -52,16 +53,17 @@ class RouteServiceProvider extends ServiceProvider
RateLimiter::for('graphql', function (Request $request) { RateLimiter::for('graphql', function (Request $request) {
$user = $request->user(); $user = $request->user();
$ip = $request->ip(); $ip = $request->ip();
$isLocal = in_array($ip, Config::array('app.local_ips'), true);
$forwardedIp = $request->header('x-forwarded-ip'); $forwardedIp = $request->header('x-forwarded-ip');
// (If request is from client and no forwarded ip) or (the user logged in has permission to bypass GraphQL rate limiting) // (If request is from client and no forwarded ip) or (the user logged in has permission to bypass GraphQL rate limiting)
/** @phpstan-ignore-next-line */ /** @phpstan-ignore-next-line */
if (($ip === '127.0.0.1' && ! $forwardedIp) || ($user instanceof User && $user->can(SpecialPermission::BYPASS_GRAPHQL_RATE_LIMITER->value))) { if (($isLocal && ! $forwardedIp) || ($user instanceof User && $user->can(SpecialPermission::BYPASS_GRAPHQL_RATE_LIMITER->value))) {
return Limit::none(); return Limit::none();
} }
// Check if request is from client to prevent users from using forwarded ip // Check if request is from client to prevent users from using forwarded ip
if ($ip === '127.0.0.1' && $forwardedIp) { if ($isLocal && $forwardedIp) {
$ip = $forwardedIp; $ip = $forwardedIp;
} }
+5
View File
@@ -251,4 +251,9 @@ return [
// ... // ...
])->toArray(), ])->toArray(),
'local_ips' => [
'127.0.0.1',
'172.19.0.1',
...explode(',', env('APP_LOCAL_IPS', '')),
],
]; ];
+2 -2
View File
@@ -24,7 +24,7 @@ return [
'name' => 'graphiql', 'name' => 'graphiql',
'middleware' => ['web'], 'middleware' => ['web'],
'prefix' => env('GRAPHQL_PREFIX', null), 'prefix' => env('GRAPHQL_PREFIX', null),
'domain' => env('GRAPHQL_URL', env('APP_URL')), 'domain' => env('GRAPHIQL_URL'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@@ -37,7 +37,7 @@ return [
| |
*/ */
'endpoint' => env('GRAPHQL_URL', env('APP_URL')).'/'.env('GRAPHQL_PATH'), 'endpoint' => env('GRAPHIQL_GRAPHQL_ENDPOINT', 'GRAPHQL_URL').'/'.env('GRAPHQL_PATH', ''),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
+1
View File
@@ -556,6 +556,7 @@ return [
[ [
'name' => 'entries', 'name' => 'entries',
'type' => 'object[]', 'type' => 'object[]',
'optional' => true,
], ],
], ],
], ],
+45 -7
View File
@@ -1,18 +1,18 @@
services: services:
laravel.test: laravel.test:
build: build:
context: ./docker/8.4 context: ./vendor/laravel/sail/runtimes/8.5
dockerfile: Dockerfile dockerfile: Dockerfile
args: args:
WWWGROUP: '${WWWGROUP}' WWWGROUP: '${WWWGROUP:-1000}'
image: sail-8.4/app image: sail-8.5/app
extra_hosts: extra_hosts:
- 'host.docker.internal:host-gateway' - 'host.docker.internal:host-gateway'
ports: ports:
- '${APP_PORT:-80}:80' - '${APP_PORT:-80}:80'
- '${VITE_PORT:-5173}:${VITE_PORT:-5173}' - '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
environment: environment:
WWWUSER: '${WWWUSER}' WWWUSER: '${WWWUSER:-1000}'
LARAVEL_SAIL: 1 LARAVEL_SAIL: 1
XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
@@ -26,7 +26,7 @@ services:
- redis - redis
- mailpit - mailpit
mysql: mysql:
image: 'mysql/mysql-server:8.0' image: 'mysql:8.4'
ports: ports:
- '${FORWARD_DB_PORT:-3306}:3306' - '${FORWARD_DB_PORT:-3306}:3306'
environment: environment:
@@ -36,6 +36,7 @@ services:
MYSQL_USER: '${DB_USERNAME}' MYSQL_USER: '${DB_USERNAME}'
MYSQL_PASSWORD: '${DB_PASSWORD}' MYSQL_PASSWORD: '${DB_PASSWORD}'
MYSQL_ALLOW_EMPTY_PASSWORD: 1 MYSQL_ALLOW_EMPTY_PASSWORD: 1
MYSQL_EXTRA_OPTIONS: '${MYSQL_EXTRA_OPTIONS:-}'
volumes: volumes:
- 'sail-mysql:/var/lib/mysql' - 'sail-mysql:/var/lib/mysql'
- './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh' - './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh'
@@ -72,17 +73,52 @@ services:
networks: networks:
- sail - sail
elasticsearch: elasticsearch:
image: 'elasticsearch:8.12.2' image: 'elasticsearch:9.4.0'
profiles:
- elastic
ports: ports:
- '9200:9200' - '9200:9200'
- '9300:9300' - '9300:9300'
environment: environment:
discovery.type: 'single-node' discovery.type: single-node
xpack.security.enabled: 'false' xpack.security.enabled: 'false'
volumes: volumes:
- 'sail-elasticsearch:/usr/share/elasticsearch/data' - 'sail-elasticsearch:/usr/share/elasticsearch/data'
networks: networks:
- sail - sail
typesense:
image: 'typesense/typesense:27.1'
ports:
- '${FORWARD_TYPESENSE_PORT:-8108}:8108'
environment:
TYPESENSE_DATA_DIR: '${TYPESENSE_DATA_DIR:-/typesense-data}'
TYPESENSE_API_KEY: '${TYPESENSE_API_KEY:-xyz}'
TYPESENSE_ENABLE_CORS: '${TYPESENSE_ENABLE_CORS:-true}'
volumes:
- 'sail-typesense:/typesense-data'
networks:
- sail
healthcheck:
test:
- CMD
- bash
- '-c'
- 'exec 3<>/dev/tcp/localhost/8108 && printf ''GET /health HTTP/1.1\r\nConnection: close\r\n\r\n'' >&3 && head -n1 <&3 | grep ''200'' && exec 3>&-'
retries: 5
timeout: 7s
phpmyadmin:
image: phpmyadmin/phpmyadmin
profiles:
- local
ports:
- '8080:80'
environment:
PMA_HOST: mysql
PMA_PORT: 3306
depends_on:
- mysql
networks:
- sail
networks: networks:
sail: sail:
driver: bridge driver: bridge
@@ -93,3 +129,5 @@ volumes:
driver: local driver: local
sail-elasticsearch: sail-elasticsearch:
driver: local driver: local
sail-typesense:
driver: local
-71
View File
@@ -1,71 +0,0 @@
FROM ubuntu:24.04
LABEL maintainer="Taylor Otwell"
ARG WWWGROUP
ARG NODE_VERSION=22
ARG MYSQL_CLIENT="mysql-client"
ARG POSTGRES_VERSION=17
WORKDIR /var/www/html
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=UTC
ENV SUPERVISOR_PHP_COMMAND="/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80"
ENV SUPERVISOR_PHP_USER="sail"
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN echo "Acquire::http::Pipeline-Depth 0;" > /etc/apt/apt.conf.d/99custom && \
echo "Acquire::http::No-Cache true;" >> /etc/apt/apt.conf.d/99custom && \
echo "Acquire::BrokenProxy true;" >> /etc/apt/apt.conf.d/99custom
RUN apt-get update && apt-get upgrade -y \
&& mkdir -p /etc/apt/keyrings \
&& apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python3 dnsutils librsvg2-bin fswatch ffmpeg nano \
&& curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xb8dc7e53946656efbce4c1dd71daeaab4ad4cab6' | gpg --dearmor | tee /etc/apt/keyrings/ppa_ondrej_php.gpg > /dev/null \
&& echo "deb [signed-by=/etc/apt/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \
&& apt-get update \
&& apt-get install -y php8.4-cli php8.4-dev \
php8.4-pgsql php8.4-sqlite3 php8.4-gd \
php8.4-curl php8.4-mongodb \
php8.4-imap php8.4-mysql php8.4-mbstring \
php8.4-xml php8.4-zip php8.4-bcmath php8.4-soap \
php8.4-intl php8.4-readline \
php8.4-ldap \
php8.4-msgpack php8.4-igbinary php8.4-redis php8.4-swoole \
php8.4-memcached php8.4-pcov php8.4-imagick php8.4-xdebug \
&& curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_VERSION.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \
&& apt-get update \
&& apt-get install -y nodejs \
&& npm install -g npm \
&& npm install -g pnpm \
&& npm install -g bun \
&& curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /etc/apt/keyrings/yarn.gpg >/dev/null \
&& echo "deb [signed-by=/etc/apt/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \
&& curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/keyrings/pgdg.gpg >/dev/null \
&& echo "deb [signed-by=/etc/apt/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt noble-pgdg main" > /etc/apt/sources.list.d/pgdg.list \
&& apt-get update \
&& apt-get install -y yarn \
&& apt-get install -y $MYSQL_CLIENT \
&& apt-get install -y postgresql-client-$POSTGRES_VERSION \
&& apt-get -y autoremove \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.4
RUN userdel -r ubuntu
RUN groupadd --force -g $WWWGROUP sail
RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail
COPY start-container /usr/local/bin/start-container
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY php.ini /etc/php/8.4/cli/conf.d/99-sail.ini
RUN chmod +x /usr/local/bin/start-container
EXPOSE 80/tcp
ENTRYPOINT ["start-container"]
-8
View File
@@ -1,8 +0,0 @@
[PHP]
post_max_size = 100M
upload_max_filesize = 100M
variables_order = EGPCS
pcov.directory = .
[xdebug]
xdebug.mode=${XDEBUG_MODE}
-26
View File
@@ -1,26 +0,0 @@
#!/usr/bin/env bash
if [ "$SUPERVISOR_PHP_USER" != "root" ] && [ "$SUPERVISOR_PHP_USER" != "sail" ]; then
echo "You should set SUPERVISOR_PHP_USER to either 'sail' or 'root'."
exit 1
fi
if [ ! -z "$WWWUSER" ]; then
usermod -u $WWWUSER sail
fi
if [ ! -d /.composer ]; then
mkdir /.composer
fi
chmod -R ugo+rw /.composer
if [ $# -gt 0 ]; then
if [ "$SUPERVISOR_PHP_USER" = "root" ]; then
exec "$@"
else
exec gosu $WWWUSER "$@"
fi
else
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
fi
-14
View File
@@ -1,14 +0,0 @@
[supervisord]
nodaemon=true
user=root
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid
[program:php]
command=%(ENV_SUPERVISOR_PHP_COMMAND)s
user=%(ENV_SUPERVISOR_PHP_USER)s
environment=LARAVEL_SAIL="1"
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
+1 -2
View File
@@ -21,8 +21,7 @@
<env name="APP_ENV" value="testing"/> <env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/> <env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/> <env name="CACHE_DRIVER" value="array"/>
<env name="DB_CONNECTION" value="sqlite"/> <env name="DB_DATABASE" value="testing"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="MAIL_FROM_ADDRESS" value="admin@example.com"/> <env name="MAIL_FROM_ADDRESS" value="admin@example.com"/>
<env name="MAIL_MAILER" value="array"/> <env name="MAIL_MAILER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/> <env name="QUEUE_CONNECTION" value="sync"/>