implement the Dockerized deployment bundle

This commit is contained in:
2026-05-19 15:00:21 +03:30
parent f535530537
commit 4536ab77ee
12 changed files with 792 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
# syntax=docker/dockerfile:1
FROM node:22-bookworm-slim AS assets
WORKDIR /build
COPY runtime/source/package.json runtime/source/package-lock.json ./
RUN npm ci
COPY runtime/source/ ./
RUN npm run build
FROM php:8.4-apache-bookworm AS app
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public \
COMPOSER_ALLOW_SUPERUSER=1
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
gettext-base \
git \
gosu \
libicu-dev \
libcurl4-openssl-dev \
libonig-dev \
libpq-dev \
libzip-dev \
netcat-openbsd \
unzip \
&& docker-php-ext-install -j"$(nproc)" \
bcmath \
curl \
intl \
mbstring \
opcache \
pcntl \
pdo_pgsql \
pgsql \
zip \
&& pecl install redis \
&& docker-php-ext-enable redis \
&& a2enmod headers proxy proxy_http rewrite setenvif \
&& rm -rf /var/lib/apt/lists/*
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY runtime/source/composer.json runtime/source/composer.lock ./
RUN composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader --no-scripts
COPY runtime/source/ ./
COPY --from=assets /build/public/build ./public/build
COPY docker/app/apache/nyone.conf.template /etc/apache2/sites-available/nyone.conf.template
COPY docker/app/php/production.ini /usr/local/etc/php/conf.d/production.ini
COPY docker/app/entrypoint.sh /usr/local/bin/nyone-entrypoint
RUN composer dump-autoload --optimize --no-dev \
&& php artisan package:discover --ansi \
&& mkdir -p \
storage/app/private/recordings \
storage/app/public \
storage/framework/cache/data \
storage/framework/sessions \
storage/framework/views \
storage/logs \
bootstrap/cache \
&& chown -R www-data:www-data storage bootstrap/cache \
&& chmod +x /usr/local/bin/nyone-entrypoint
ENTRYPOINT ["nyone-entrypoint"]
CMD ["app"]

View File

@@ -0,0 +1,43 @@
ServerName ${APP_DOMAIN}
<VirtualHost *:80>
ServerName ${APP_DOMAIN}
DocumentRoot /var/www/html/public
DirectoryIndex index.php
SetEnvIf X-Forwarded-Proto "^https$" HTTPS=on
SetEnvIf X-Forwarded-Ssl "^on$" HTTPS=on
<Directory /var/www/html/public>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<FilesMatch "\.php$">
SetHandler application/x-httpd-php
</FilesMatch>
ErrorLog /proc/self/fd/2
CustomLog /proc/self/fd/1 combined
</VirtualHost>
<VirtualHost *:80>
ServerName ${HLS_DOMAIN}
ProxyRequests Off
ProxyPreserveHost On
ProxyPass "/" "http://mediamtx:${HLS_INTERNAL_PORT}/" retry=0
ProxyPassReverse "/" "http://mediamtx:${HLS_INTERNAL_PORT}/"
Header always set Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate"
Header always set Access-Control-Allow-Origin "${APP_URL}"
Header always set Access-Control-Allow-Methods "GET, HEAD, OPTIONS"
Header always set Access-Control-Allow-Headers "Range, Origin, Accept, Content-Type"
ErrorLog /proc/self/fd/2
CustomLog /proc/self/fd/1 combined
</VirtualHost>

View File

@@ -0,0 +1,134 @@
#!/usr/bin/env bash
set -euo pipefail
cd /var/www/html
role="${CONTAINER_ROLE:-${1:-app}}"
fail() {
echo "nyone-entrypoint: $*" >&2
exit 1
}
require_env() {
local key="$1"
local value="${!key:-}"
if [[ -z "$value" || "$value" == "change-me"* || "$value" == "base64:change-me"* ]]; then
fail "$key is required. Run dockerized/scripts/deploy.sh or set it in dockerized/.env."
fi
}
wait_for() {
local host="$1"
local port="$2"
local label="$3"
local attempts="${4:-60}"
for ((i = 1; i <= attempts; i++)); do
if nc -z "$host" "$port" >/dev/null 2>&1; then
return 0
fi
sleep 2
done
fail "Timed out waiting for $label at $host:$port."
}
artisan() {
gosu www-data php artisan "$@"
}
render_apache_config() {
export APP_DOMAIN HLS_DOMAIN HLS_INTERNAL_PORT APP_URL
envsubst '${APP_DOMAIN} ${HLS_DOMAIN} ${HLS_INTERNAL_PORT} ${APP_URL}' \
< /etc/apache2/sites-available/nyone.conf.template \
> /etc/apache2/sites-available/000-default.conf
}
prepare_laravel_paths() {
mkdir -p \
storage/app/private/recordings \
storage/app/public \
storage/framework/cache/data \
storage/framework/sessions \
storage/framework/views \
storage/logs \
bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
}
cache_laravel_bootstrap() {
if [[ "${APP_OPTIMIZE_ON_BOOT:-true}" != "true" ]]; then
return 0
fi
artisan config:clear
artisan route:clear
artisan view:clear
artisan event:clear
artisan config:cache
artisan route:cache
artisan view:cache
}
require_env APP_KEY
require_env APP_DOMAIN
require_env HLS_DOMAIN
require_env MEDIAMTX_SHARED_SECRET
require_env DB_DATABASE
require_env DB_USERNAME
require_env DB_PASSWORD
if [[ "${WAIT_FOR_SERVICES:-true}" == "true" ]]; then
wait_for "${DB_HOST:-db}" "${DB_PORT:-5432}" "PostgreSQL"
wait_for "${REDIS_HOST:-redis}" "${REDIS_PORT:-6379}" "Redis"
if [[ "$role" == "viewer-sync" ]]; then
wait_for "${MEDIAMTX_HOST:-mediamtx}" "${MEDIAMTX_API_PORT:-9997}" "MediaMTX API"
fi
fi
prepare_laravel_paths
artisan storage:link --force >/dev/null || true
cache_laravel_bootstrap
case "$role" in
app)
render_apache_config
exec apache2-foreground
;;
migrate)
artisan migrate --force
if [[ "${SEED_DATABASE:-false}" == "true" ]]; then
artisan db:seed --force
fi
;;
queue)
exec gosu www-data php artisan queue:work "${QUEUE_CONNECTION:-database}" \
--queue="${QUEUE_NAMES:-default}" \
--sleep="${QUEUE_SLEEP:-3}" \
--tries="${QUEUE_TRIES:-3}" \
--max-time="${QUEUE_MAX_TIME:-3600}" \
--timeout="${QUEUE_TIMEOUT:-90}"
;;
scheduler)
exec gosu www-data php artisan schedule:work
;;
viewer-sync)
exec gosu www-data php artisan streaming:sync-viewer-counts \
--isolated \
--interval="${STREAMING_VIEWER_SYNC_INTERVAL:-2}"
;;
artisan)
shift || true
exec gosu www-data php artisan "$@"
;;
*)
exec "$@"
;;
esac

View File

@@ -0,0 +1,17 @@
expose_php=Off
memory_limit=512M
upload_max_filesize=100M
post_max_size=100M
max_execution_time=120
max_input_vars=3000
variables_order=EGPCS
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.save_comments=1
opcache.jit=0