Skip to content

Commit e424e7f

Browse files
dotMavriQclaude
andcommitted
feat: add Docker production deployment for teal.dotmavriq.life
Multi-stage Dockerfile (Node + Composer + FrankenPHP), docker-compose with app/db/queue services, Traefik routing with TLS, entrypoint scripts with env validation/migration/caching, and deploy helper script. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 503fd3c commit e424e7f

8 files changed

Lines changed: 879 additions & 0 deletions

File tree

.dockerignore

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Version control
2+
.git
3+
.gitignore
4+
.gitattributes
5+
6+
# Dependencies (rebuilt in Docker)
7+
node_modules
8+
vendor
9+
10+
# Build artifacts (rebuilt in Docker)
11+
public/build
12+
public/hot
13+
14+
# Environment files (injected at runtime)
15+
.env
16+
.env.*
17+
!.env.example
18+
19+
# Development/testing
20+
.phpunit.result.cache
21+
.phpunit.cache
22+
phpunit.xml
23+
tests
24+
.editorconfig
25+
.styleci.yml
26+
27+
# Docker meta (prevent recursive context)
28+
docker-compose*.yml
29+
Dockerfile*
30+
.dockerignore
31+
32+
# IDE
33+
.idea
34+
.vscode
35+
*.swp
36+
*.swo
37+
38+
# OS
39+
.DS_Store
40+
Thumbs.db
41+
42+
# Runtime data (persisted via volumes)
43+
storage/logs/*
44+
storage/framework/cache/*
45+
storage/framework/sessions/*
46+
storage/framework/views/*
47+
storage/app/public/covers/*
48+
49+
# Old deployment files
50+
docker-compose.dotmavriq.fixed.yml
51+
docker-compose.frankenphp.yml

.env.production.example

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# =============================================================================
2+
# TEAL Production Environment (.env.production)
3+
# Copy this to .env.production and fill in the secrets
4+
# On gerty: /opt/teal/.env.production (chmod 600, owned by root)
5+
# =============================================================================
6+
7+
# ---- Application ----
8+
APP_NAME=TEAL
9+
APP_ENV=production
10+
APP_KEY= # Generate: php artisan key:generate --show
11+
APP_DEBUG=false
12+
APP_URL=https://teal.dotmavriq.life
13+
14+
# ---- Database ----
15+
DB_CONNECTION=pgsql
16+
DB_HOST=db
17+
DB_PORT=5432
18+
DB_DATABASE=teal
19+
DB_USERNAME=teal
20+
DB_PASSWORD= # Use: openssl rand -base64 32
21+
22+
# ---- Drivers (all database — no Redis needed) ----
23+
SESSION_DRIVER=database
24+
SESSION_LIFETIME=120
25+
SESSION_ENCRYPT=true
26+
SESSION_SECURE_COOKIE=true
27+
SESSION_DOMAIN=teal.dotmavriq.life
28+
CACHE_STORE=database
29+
QUEUE_CONNECTION=database
30+
BROADCAST_CONNECTION=log
31+
FILESYSTEM_DISK=local
32+
33+
# ---- Logging (stderr → Docker log driver) ----
34+
LOG_CHANNEL=stderr
35+
LOG_LEVEL=warning
36+
37+
# ---- Security ----
38+
BCRYPT_ROUNDS=12
39+
40+
# ---- Octane / FrankenPHP ----
41+
OCTANE_SERVER=frankenphp
42+
OCTANE_HTTPS=true
43+
44+
# ---- API Keys ----
45+
TMDB_API_KEY= # From themoviedb.org
46+
TMDB_ACCESS_TOKEN= # From themoviedb.org
47+
TRAKT_CLIENT_ID= # From trakt.tv
48+
49+
# ---- Mail (log only — no outbound email) ----
50+
MAIL_MAILER=log

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@ goodreads.txt
4040
IMDBEXPORT.csv
4141
theplan.txt
4242
frankenphp
43+
backups/

Dockerfile

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# =============================================================================
2+
# TEAL Production Dockerfile
3+
# Multi-stage build: Node (frontend) → Composer (PHP deps) → FrankenPHP runtime
4+
# =============================================================================
5+
6+
# ---------------------------------------------------------------------------
7+
# Stage 1: Build frontend assets with Vite
8+
# ---------------------------------------------------------------------------
9+
FROM node:22-alpine AS node-builder
10+
11+
WORKDIR /build
12+
13+
# Copy dependency manifests first for layer caching
14+
COPY package.json package-lock.json ./
15+
RUN npm ci --no-audit --no-fund \
16+
&& echo "[node-builder] npm dependencies installed"
17+
18+
# Copy frontend source files needed for the build
19+
COPY vite.config.js tailwind.config.js postcss.config.js ./
20+
COPY resources/ resources/
21+
22+
# Build production assets
23+
RUN npm run build \
24+
&& echo "[node-builder] Vite build complete" \
25+
&& ls -la public/build/ \
26+
&& echo "[node-builder] Manifest:" \
27+
&& cat public/build/manifest.json
28+
29+
# ---------------------------------------------------------------------------
30+
# Stage 2: Install PHP dependencies with Composer
31+
# ---------------------------------------------------------------------------
32+
FROM composer:2 AS composer-builder
33+
34+
WORKDIR /build
35+
36+
# Copy dependency manifests
37+
COPY composer.json composer.lock ./
38+
39+
# Install production dependencies only (no scripts — avoids needing artisan)
40+
RUN composer install \
41+
--no-dev \
42+
--no-scripts \
43+
--no-interaction \
44+
--prefer-dist \
45+
--optimize-autoloader \
46+
&& echo "[composer-builder] PHP dependencies installed" \
47+
&& echo "[composer-builder] Vendor size:" \
48+
&& du -sh vendor/
49+
50+
# ---------------------------------------------------------------------------
51+
# Stage 3: Production runtime image
52+
# ---------------------------------------------------------------------------
53+
FROM serversideup/php:8.4-frankenphp AS production
54+
55+
LABEL maintainer="dotmavriq" \
56+
app="TEAL" \
57+
description="TEAL - Track Everything About Life"
58+
59+
# ---- Install additional PHP extensions ----
60+
# pgsql/pdo_pgsql: PostgreSQL
61+
# gd: Image processing (intervention/image)
62+
# intl: Unicode/i18n support
63+
# opcache: Production PHP performance
64+
# pcntl: Process control for Octane graceful shutdown
65+
# bcmath: Precision math (Laravel dependency)
66+
RUN install-php-extensions \
67+
pdo_pgsql \
68+
pgsql \
69+
gd \
70+
intl \
71+
opcache \
72+
pcntl \
73+
bcmath \
74+
&& echo "[production] PHP extensions installed:" \
75+
&& php -m | sort
76+
77+
# ---- Set environment defaults ----
78+
ENV APP_ENV=production \
79+
APP_DEBUG=false \
80+
OCTANE_SERVER=frankenphp \
81+
SERVER_NAME=":8080" \
82+
LOG_CHANNEL=stderr \
83+
LOG_LEVEL=warning \
84+
AUTORUN_ENABLED=false
85+
86+
# ---- Set working directory ----
87+
WORKDIR /var/www/html
88+
89+
# ---- Copy application source ----
90+
COPY --chown=www-data:www-data . .
91+
92+
# ---- Copy built vendor directory from composer stage ----
93+
COPY --from=composer-builder --chown=www-data:www-data /build/vendor ./vendor
94+
95+
# ---- Copy built frontend assets from node stage ----
96+
COPY --from=node-builder --chown=www-data:www-data /build/public/build ./public/build
97+
98+
# ---- Run composer post-install scripts (package discovery, etc.) ----
99+
RUN composer dump-autoload --optimize --no-dev \
100+
&& echo "[production] Autoloader optimized"
101+
102+
# ---- Ensure storage directories and permissions ----
103+
RUN mkdir -p \
104+
storage/app/public/covers \
105+
storage/framework/cache/data \
106+
storage/framework/sessions \
107+
storage/framework/views \
108+
storage/logs \
109+
bootstrap/cache \
110+
&& chown -R www-data:www-data storage bootstrap/cache \
111+
&& chmod -R 775 storage bootstrap/cache \
112+
&& echo "[production] Storage directories created"
113+
114+
# ---- Copy entrypoint scripts ----
115+
COPY docker/entrypoint.sh /usr/local/bin/docker-entrypoint.sh
116+
COPY docker/queue-entrypoint.sh /usr/local/bin/docker-queue-entrypoint.sh
117+
RUN chmod +x /usr/local/bin/docker-entrypoint.sh /usr/local/bin/docker-queue-entrypoint.sh
118+
119+
# ---- Healthcheck ----
120+
HEALTHCHECK --interval=15s --timeout=5s --retries=3 --start-period=20s \
121+
CMD php artisan octane:status --server=frankenphp || exit 1
122+
123+
EXPOSE 8080
124+
125+
ENTRYPOINT ["docker-entrypoint.sh"]

0 commit comments

Comments
 (0)