From 4ecfa9f3343672857fffef4c58c7b0d526b71457 Mon Sep 17 00:00:00 2001 From: Connor Abbas Date: Sun, 29 Jun 2025 02:39:05 +0000 Subject: [PATCH 1/7] new docker setup --- .devcontainer/.bashrc | 7 ++ .devcontainer/devcontainer.json | 7 +- .devcontainer/xdebug.ini | 6 ++ .dockerignore | 6 ++ .env.example | 8 +-- Dockerfile | 31 ++++++++ Dockerfile.dev | 35 +++++++++ app/Providers/AppServiceProvider.php | 5 +- bootstrap/app.php | 8 +++ .../create-pg-testing-database.sql | 1 + docker-compose.dev.yml | 56 +++++++++++++++ docker-compose.local.yml | 60 ---------------- docker-compose.yml | 60 ++++++++++++++++ .../database/mysql/create-testing-database.sh | 6 -- docker/local/web/Dockerfile | 71 ------------------- docker/local/web/php.ini | 5 -- docker/local/web/start-container | 26 ------- docker/local/web/supervisord.conf | 14 ---- 18 files changed, 222 insertions(+), 190 deletions(-) create mode 100644 .devcontainer/.bashrc create mode 100644 .devcontainer/xdebug.ini create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 Dockerfile.dev rename docker/local/database/pgsql/create-testing-database.sql => database/create-pg-testing-database.sql (65%) create mode 100644 docker-compose.dev.yml delete mode 100644 docker-compose.local.yml create mode 100644 docker-compose.yml delete mode 100644 docker/local/database/mysql/create-testing-database.sh delete mode 100644 docker/local/web/Dockerfile delete mode 100644 docker/local/web/php.ini delete mode 100644 docker/local/web/start-container delete mode 100644 docker/local/web/supervisord.conf diff --git a/.devcontainer/.bashrc b/.devcontainer/.bashrc new file mode 100644 index 00000000..12e4a4ee --- /dev/null +++ b/.devcontainer/.bashrc @@ -0,0 +1,7 @@ +# Get current Git branch +parse_git_branch() { + git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/' +} + +# Custom PS1 prompt: green user@host, blue directory, yellow git branch +export PS1='\[\e[32m\]\u@\h\[\e[m\]:\[\e[34m\]\w\[\e[33m\]$(parse_git_branch)\[\e[m\]\$ ' \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 9c378021..09c0c24a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,18 +2,19 @@ { "name": "PrimeVue Inertia", "dockerComposeFile": [ - "../docker-compose.local.yml" + "../docker-compose.dev.yml" ], "service": "laravel", "workspaceFolder": "/var/www/html", "mounts": [ - "type=bind,source=/home/${localEnv:USER}/.ssh,target=/home/sail/.ssh,readonly" + "type=bind,source=/home/${localEnv:USER}/.ssh,target=/home/www-data/.ssh,readonly" ], "customizations": { "vscode": { "extensions": [ "DEVSENSE.phptools-vscode", "MehediDracula.php-namespace-resolver", + "xdebug.php-debug", "laravel.vscode-laravel", "Vue.volar", "hollowtree.vue-snippets", @@ -35,7 +36,7 @@ } } }, - "remoteUser": "sail", + "remoteUser": "www-data", "postCreateCommand": "chown -R 1000:1000 /var/www/html 2>/dev/null || true" // "forwardPorts": [], // "runServices": [], diff --git a/.devcontainer/xdebug.ini b/.devcontainer/xdebug.ini new file mode 100644 index 00000000..e8980cf4 --- /dev/null +++ b/.devcontainer/xdebug.ini @@ -0,0 +1,6 @@ +[xdebug] +zend_extension=xdebug.so +xdebug.start_with_request=yes +xdebug.client_host=host.docker.internal +xdebug.client_port=9003 +xdebug.log=/tmp/xdebug.log \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..c209d6de --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.git +tests +.env* +Dockerfile* +docker-*.yml +*.md \ No newline at end of file diff --git a/.env.example b/.env.example index 69b07f55..d8c7b13f 100644 --- a/.env.example +++ b/.env.example @@ -26,7 +26,7 @@ DB_CONNECTION=sqlite #DB_USERNAME= #DB_PASSWORD= -SESSION_DRIVER=file +SESSION_DRIVER=database SESSION_LIFETIME=120 SESSION_ENCRYPT=false SESSION_PATH=/ @@ -63,9 +63,9 @@ AWS_USE_PATH_STYLE_ENDPOINT=false VITE_APP_NAME="${APP_NAME}" -WWWGROUP=1000 -WWWUSER=1000 +USER_ID=1000 +GROUP_ID=1000 +#XDEBUG_MODE=debug -APP_PORT=8000 VITE_PORT=5173 FORWARD_DB_PORT= diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..83d1ce20 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +ARG NODE_VERSION=22 + +# Base Image +# https://serversideup.net/open-source/docker-php/docs +FROM serversideup/php:8.4-fpm-nginx-alpine AS base +USER root +RUN install-php-extensions bcmath gd pgsql + +# Composer Stage +FROM base AS composer +WORKDIR /var/www/html +COPY composer.json composer.lock ./ +RUN composer install --no-dev --optimize-autoloader --no-scripts --no-interaction + +# Assets Stage +FROM node:${NODE_VERSION}-alpine AS build-assets +WORKDIR /var/www/html +COPY package*.json ./ +RUN npm ci +COPY --from=composer /var/www/html/vendor/tightenco/ziggy ./vendor/tightenco/ziggy +COPY vite.config.js ./ +COPY resources ./resources +RUN npm run build + +# Production Image +FROM base AS release +WORKDIR /var/www/html +COPY --chown=www-data:www-data --from=composer /var/www/html/vendor ./vendor +COPY --chown=www-data:www-data --from=build-assets /var/www/html/public/build ./public/build +COPY --chown=www-data:www-data . . +USER www-data \ No newline at end of file diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 00000000..d8fd2e6f --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,35 @@ +ARG NODE_VERSION=22 + +# Base Image +# https://serversideup.net/open-source/docker-php/docs +FROM serversideup/php:8.4-fpm-nginx-alpine AS base +USER root +RUN install-php-extensions bcmath gd pgsql + +# Node Image +FROM node:${NODE_VERSION}-alpine AS node + +# Development Image +FROM base AS development +ARG USER_ID +ARG GROUP_ID +USER root +RUN apk add --no-cache curl git bash gnupg postgresql-client openssh-client \ + && apk add --no-cache --virtual .build-deps build-base autoconf \ + && install-php-extensions xdebug \ + && rm -rf /var/cache/apk/* \ + && apk del .build-deps +COPY --from=node /usr/lib /usr/lib +COPY --from=node /usr/local/lib /usr/local/lib +COPY --from=node /usr/local/include /usr/local/include +COPY --from=node /usr/local/bin /usr/local/bin +COPY .devcontainer/.bashrc /home/www-data/.bashrc +COPY .devcontainer/xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +RUN usermod -s /bin/bash www-data \ + && git config --global --add safe.directory /var/www/html \ + && mkdir -p /home/www-data/.ssh \ + && chown www-data:www-data /home/www-data/.ssh \ + && chown www-data:www-data /home/www-data/.bashrc \ + && docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID \ + && docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID --service nginx +USER www-data \ No newline at end of file diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 452e6b65..9ff88320 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,6 +2,7 @@ namespace App\Providers; +use Illuminate\Support\Facades\URL; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider @@ -19,6 +20,8 @@ public function register(): void */ public function boot(): void { - // + if ($this->app->environment('production')) { + URL::forceScheme('https'); + } } } diff --git a/bootstrap/app.php b/bootstrap/app.php index a8386b03..68565dc0 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -29,6 +29,14 @@ BaseEncryptCookies::class => EncryptCookies::class ], ); + // TrustProxies middleware for Traefik handling assets over https + $middleware->trustProxies( + at: '*', + headers: Request::HEADER_X_FORWARDED_FOR + | Request::HEADER_X_FORWARDED_HOST + | Request::HEADER_X_FORWARDED_PORT + | Request::HEADER_X_FORWARDED_PROTO + ); }) ->withExceptions(function (Exceptions $exceptions) { $exceptions->respond(function (Response $response, Throwable $exception, Request $request) { diff --git a/docker/local/database/pgsql/create-testing-database.sql b/database/create-pg-testing-database.sql similarity index 65% rename from docker/local/database/pgsql/create-testing-database.sql rename to database/create-pg-testing-database.sql index d84dc07b..5698e801 100644 --- a/docker/local/database/pgsql/create-testing-database.sql +++ b/database/create-pg-testing-database.sql @@ -1,2 +1,3 @@ +-- create a PostgreSQL testing db for PHPUnit test suite SELECT 'CREATE DATABASE testing' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'testing')\gexec diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 00000000..f2104aa2 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,56 @@ +services: + laravel: + build: + context: . + dockerfile: Dockerfile.dev + target: development + args: + USER_ID: '${USER_ID:-1000}' + GROUP_ID: '${GROUP_ID:-1000}' + extra_hosts: + - 'host.docker.internal:host-gateway' + ports: + - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' # Not required if using dev containers (auto port forwarding) + environment: + PHP_OPCACHE_ENABLE: '1' + PHP_OPCACHE_REVALIDATE_FREQ: '0' + XDEBUG_MODE: '${XDEBUG_MODE:-off}' + volumes: + - '.:/var/www/html' + labels: + - 'traefik.enable=true' + - 'traefik.http.routers.laravel-primevue.rule=Host(`laravel-primevue.localhost`)' + - 'traefik.http.services.laravel-primevue.loadbalancer.server.port=8080' # exposed http port from serversideup image + networks: + - proxy + - laravel + depends_on: + - pgsql + + pgsql: + image: 'postgres:17' + ports: + - '${FORWARD_DB_PORT:-5432}:5432' + environment: + PGPASSWORD: '${DB_PASSWORD:-secret}' + POSTGRES_DB: '${DB_DATABASE}' + POSTGRES_USER: '${DB_USERNAME}' + POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}' + volumes: + - 'postgres-data:/var/lib/postgresql/data' + - './database/create-pg-testing-database.sql:/docker-entrypoint-initdb.d/10-create-testing-database.sql' + networks: + - laravel + healthcheck: + test: [ "CMD", "pg_isready", "-q", "-d", "${DB_DATABASE}", "-U", "${DB_USERNAME}" ] + retries: 3 + timeout: 5s + +volumes: + postgres-data: + +networks: + laravel: + proxy: + name: traefik_network + external: true diff --git a/docker-compose.local.yml b/docker-compose.local.yml deleted file mode 100644 index 1df2471c..00000000 --- a/docker-compose.local.yml +++ /dev/null @@ -1,60 +0,0 @@ -services: - laravel: - build: - context: ./docker/local/web - dockerfile: Dockerfile - args: - WWWGROUP: '${WWWGROUP}' - image: sail-8.4/app - extra_hosts: - - 'host.docker.internal:host-gateway' - #ports: - #- '${APP_PORT:-80}:80' not required using Traefik - #- '${VITE_PORT:-5173}:${VITE_PORT:-5173}' Not required if using dev containers (auto forwards port to localhost) - environment: - WWWUSER: '${WWWUSER}' - LARAVEL_SAIL: 1 - XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' - XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' - IGNITION_LOCAL_SITES_PATH: '${PWD}' - volumes: - - '.:/var/www/html' - labels: - - "traefik.enable=true" - - "traefik.http.routers.laravel-primevue.rule=Host(`laravel-primevue.localhost`)" - - "traefik.http.services.laravel-primevue.loadbalancer.server.port=80" - networks: - - sail - - proxy - depends_on: - - pgsql - - pgsql: - image: 'postgres:17' - ports: - - '${FORWARD_DB_PORT:-5432}:5432' - environment: - PGPASSWORD: '${DB_PASSWORD:-secret}' - POSTGRES_DB: '${DB_DATABASE}' - POSTGRES_USER: '${DB_USERNAME}' - POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}' - volumes: - - 'laravel-primevue-pgsql:/var/lib/postgresql/data' - - './docker/local/database/pgsql/create-testing-database.sql:/docker-entrypoint-initdb.d/10-create-testing-database.sql' - networks: - - sail - healthcheck: - test: [ "CMD", "pg_isready", "-q", "-d", "${DB_DATABASE}", "-U", "${DB_USERNAME}" ] - retries: 3 - timeout: 5s - -volumes: - laravel-primevue-pgsql: - driver: local - -networks: - sail: - driver: bridge - proxy: - name: traefik_network - external: true diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..b3ff387c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,60 @@ +services: + laravel: + build: + context: . + dockerfile: Dockerfile + target: release + restart: always + env_file: '.env' + environment: + PHP_OPCACHE_ENABLE: '1' + SSL_MODE: 'mixed' + volumes: + - 'storage-public:/var/www/html/storage/app/public/' + - 'storage-sessions:/var/www/html/storage/framework/sessions' + - 'storage-logs:/var/www/html/storage/logs' + labels: + - 'traefik.enable=true' + - 'traefik.http.routers.your-app-name.rule=Host(`your-domain.com`)' + - 'traefik.http.routers.your-app-name.entrypoints=websecure' + - 'traefik.http.routers.your-app-name.tls=true' + - 'traefik.http.routers.your-app-name.tls.certresolver=letsencrypt' + - 'traefik.http.services.your-app-name.loadbalancer.server.port=8080' # exposed http port from serversideup image + # Health check + - 'traefik.http.services.your-app-name.loadbalancer.healthcheck.path=/healthcheck' + - 'traefik.http.services.your-app-name.loadbalancer.healthcheck.interval=30s' + - 'traefik.http.services.your-app-name.loadbalancer.healthcheck.timeout=5s' + - 'traefik.http.services.your-app-name.loadbalancer.healthcheck.scheme=http' + networks: + - proxy + depends_on: + - pgsql + + pgsql: + image: postgres:17 + restart: always + ports: + - '${FORWARD_DB_PORT:-5432}:5432' + environment: + POSTGRES_DB: '${DB_DATABASE}' + POSTGRES_USER: '${DB_USERNAME}' + POSTGRES_PASSWORD: '${DB_PASSWORD}' + volumes: + - postgres-data:/var/lib/postgresql/data + networks: + - proxy + healthcheck: + test: ['CMD', 'pg_isready', '-q', '-d', '${DB_DATABASE}', '-U', '${DB_USERNAME}'] + retries: 3 + timeout: 5s + +volumes: + postgres-data: + storage-public: + storage-sessions: + storage-logs: + +networks: + proxy: + name: traefik_network + external: true \ No newline at end of file diff --git a/docker/local/database/mysql/create-testing-database.sh b/docker/local/database/mysql/create-testing-database.sh deleted file mode 100644 index aeb1826f..00000000 --- a/docker/local/database/mysql/create-testing-database.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -mysql --user=root --password="$MYSQL_ROOT_PASSWORD" <<-EOSQL - CREATE DATABASE IF NOT EXISTS testing; - GRANT ALL PRIVILEGES ON \`testing%\`.* TO '$MYSQL_USER'@'%'; -EOSQL diff --git a/docker/local/web/Dockerfile b/docker/local/web/Dockerfile deleted file mode 100644 index cb0fbdc1..00000000 --- a/docker/local/web/Dockerfile +++ /dev/null @@ -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"] diff --git a/docker/local/web/php.ini b/docker/local/web/php.ini deleted file mode 100644 index 0d8ce9e2..00000000 --- a/docker/local/web/php.ini +++ /dev/null @@ -1,5 +0,0 @@ -[PHP] -post_max_size = 100M -upload_max_filesize = 100M -variables_order = EGPCS -pcov.directory = . diff --git a/docker/local/web/start-container b/docker/local/web/start-container deleted file mode 100644 index 40c55dfe..00000000 --- a/docker/local/web/start-container +++ /dev/null @@ -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 diff --git a/docker/local/web/supervisord.conf b/docker/local/web/supervisord.conf deleted file mode 100644 index 656da8a9..00000000 --- a/docker/local/web/supervisord.conf +++ /dev/null @@ -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 From 3df02d8ae88de845dd45f40380471e69b38b6c2e Mon Sep 17 00:00:00 2001 From: Connor Abbas Date: Sun, 29 Jun 2025 11:51:49 -0500 Subject: [PATCH 2/7] updates: use one dockerfile --- Dockerfile | 29 +++++++++++++++++++++++++++++ Dockerfile.dev | 35 ----------------------------------- docker-compose.dev.yml | 2 +- 3 files changed, 30 insertions(+), 36 deletions(-) delete mode 100644 Dockerfile.dev diff --git a/Dockerfile b/Dockerfile index 83d1ce20..29f7a761 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,9 @@ FROM serversideup/php:8.4-fpm-nginx-alpine AS base USER root RUN install-php-extensions bcmath gd pgsql +# Node Image +FROM node:${NODE_VERSION}-alpine AS node + # Composer Stage FROM base AS composer WORKDIR /var/www/html @@ -22,6 +25,32 @@ COPY vite.config.js ./ COPY resources ./resources RUN npm run build +# Development Image +FROM base AS development +ARG USER_ID +ARG GROUP_ID +USER root +RUN apk add --no-cache curl git bash gnupg postgresql-client openssh-client \ + && apk add --no-cache --virtual .build-deps build-base autoconf \ + && install-php-extensions xdebug \ + && rm -rf /var/cache/apk/* \ + && apk del .build-deps +COPY --from=node /usr/lib /usr/lib +COPY --from=node /usr/local/lib /usr/local/lib +COPY --from=node /usr/local/include /usr/local/include +COPY --from=node /usr/local/bin /usr/local/bin +COPY .devcontainer/.bashrc /home/www-data/.bashrc +COPY .devcontainer/xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +RUN usermod -s /bin/bash www-data \ + && git config --global --add safe.directory /var/www/html \ + && mkdir -p /home/www-data/.ssh \ + && chown www-data:www-data /home/www-data/.ssh \ + && chown www-data:www-data /home/www-data/.bashrc \ + && docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID \ + && docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID --service nginx +WORKDIR /var/www/html +USER www-data + # Production Image FROM base AS release WORKDIR /var/www/html diff --git a/Dockerfile.dev b/Dockerfile.dev deleted file mode 100644 index d8fd2e6f..00000000 --- a/Dockerfile.dev +++ /dev/null @@ -1,35 +0,0 @@ -ARG NODE_VERSION=22 - -# Base Image -# https://serversideup.net/open-source/docker-php/docs -FROM serversideup/php:8.4-fpm-nginx-alpine AS base -USER root -RUN install-php-extensions bcmath gd pgsql - -# Node Image -FROM node:${NODE_VERSION}-alpine AS node - -# Development Image -FROM base AS development -ARG USER_ID -ARG GROUP_ID -USER root -RUN apk add --no-cache curl git bash gnupg postgresql-client openssh-client \ - && apk add --no-cache --virtual .build-deps build-base autoconf \ - && install-php-extensions xdebug \ - && rm -rf /var/cache/apk/* \ - && apk del .build-deps -COPY --from=node /usr/lib /usr/lib -COPY --from=node /usr/local/lib /usr/local/lib -COPY --from=node /usr/local/include /usr/local/include -COPY --from=node /usr/local/bin /usr/local/bin -COPY .devcontainer/.bashrc /home/www-data/.bashrc -COPY .devcontainer/xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini -RUN usermod -s /bin/bash www-data \ - && git config --global --add safe.directory /var/www/html \ - && mkdir -p /home/www-data/.ssh \ - && chown www-data:www-data /home/www-data/.ssh \ - && chown www-data:www-data /home/www-data/.bashrc \ - && docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID \ - && docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID --service nginx -USER www-data \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index f2104aa2..eaafaad7 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -2,7 +2,7 @@ services: laravel: build: context: . - dockerfile: Dockerfile.dev + dockerfile: Dockerfile target: development args: USER_ID: '${USER_ID:-1000}' From 8b04064b8f90cf27b49d5ae54a73f277b1a8ccdb Mon Sep 17 00:00:00 2001 From: Connor Abbas Date: Sun, 29 Jun 2025 21:55:28 -0500 Subject: [PATCH 3/7] feature: SSR via S-6 overlay process, improvements --- .../s6-overlay/inertia-ssr/dependencies | 1 + .infrastructure/s6-overlay/inertia-ssr/run | 2 + .infrastructure/s6-overlay/inertia-ssr/type | 1 + Dockerfile | 17 ++++++ docker-compose.dev.yml | 2 +- docker-deploy.sh | 56 +++++++++++++++++++ 6 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 .infrastructure/s6-overlay/inertia-ssr/dependencies create mode 100644 .infrastructure/s6-overlay/inertia-ssr/run create mode 100644 .infrastructure/s6-overlay/inertia-ssr/type create mode 100755 docker-deploy.sh diff --git a/.infrastructure/s6-overlay/inertia-ssr/dependencies b/.infrastructure/s6-overlay/inertia-ssr/dependencies new file mode 100644 index 00000000..54f9367c --- /dev/null +++ b/.infrastructure/s6-overlay/inertia-ssr/dependencies @@ -0,0 +1 @@ +php-fpm \ No newline at end of file diff --git a/.infrastructure/s6-overlay/inertia-ssr/run b/.infrastructure/s6-overlay/inertia-ssr/run new file mode 100644 index 00000000..a3c4275b --- /dev/null +++ b/.infrastructure/s6-overlay/inertia-ssr/run @@ -0,0 +1,2 @@ +#!/bin/sh +exec php /var/www/html/artisan inertia:start-ssr \ No newline at end of file diff --git a/.infrastructure/s6-overlay/inertia-ssr/type b/.infrastructure/s6-overlay/inertia-ssr/type new file mode 100644 index 00000000..1780f9f4 --- /dev/null +++ b/.infrastructure/s6-overlay/inertia-ssr/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 29f7a761..0bc330ba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,4 +57,21 @@ WORKDIR /var/www/html COPY --chown=www-data:www-data --from=composer /var/www/html/vendor ./vendor COPY --chown=www-data:www-data --from=build-assets /var/www/html/public/build ./public/build COPY --chown=www-data:www-data . . +USER www-data + +# SSR Node Production Image +FROM base AS ssr-release +COPY --from=node /usr/lib /usr/lib +COPY --from=node /usr/local/lib /usr/local/lib +COPY --from=node /usr/local/include /usr/local/include +COPY --from=node /usr/local/bin /usr/local/bin +COPY --chown=www-data:www-data --chmod=755 .infrastructure/s6-overlay/inertia-ssr /etc/s6-overlay/s6-rc.d/inertia-ssr +RUN touch /etc/s6-overlay/s6-rc.d/user/contents.d/inertia-ssr \ + && chown www-data:www-data /etc/s6-overlay/s6-rc.d/user/contents.d/inertia-ssr \ + && chmod 755 /etc/s6-overlay/s6-rc.d/user/contents.d/inertia-ssr +WORKDIR /var/www/html +COPY --chown=www-data:www-data --from=composer /var/www/html/vendor ./vendor +COPY --chown=www-data:www-data --from=build-assets /var/www/html/public/build ./public/build +COPY --chown=www-data:www-data --from=build-assets /var/www/html/bootstrap/ssr ./bootstrap/ssr +COPY --chown=www-data:www-data . . USER www-data \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index eaafaad7..2be407c5 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -10,7 +10,7 @@ services: extra_hosts: - 'host.docker.internal:host-gateway' ports: - - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' # Not required if using dev containers (auto port forwarding) + - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' # Not necessarily required for dev containers (auto port forwarding) environment: PHP_OPCACHE_ENABLE: '1' PHP_OPCACHE_REVALIDATE_FREQ: '0' diff --git a/docker-deploy.sh b/docker-deploy.sh new file mode 100755 index 00000000..b9c7bb94 --- /dev/null +++ b/docker-deploy.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Usage: chmod +x docker-deploy.sh && ./docker-deploy.sh + +# Make sure we're in the project root +cd "$(dirname "$0")" + +# Maintenance mode +echo ":: Entering maintenance mode" +docker compose exec laravel php artisan down || true + +# Pull latest code +echo ":: Fetching latest from Git" +git pull origin master + +# Rebuild & restart container +echo ":: Rebuilding app image & restarting" +docker compose up -d --build --force-recreate laravel + +# Wait for successful health check +echo ":: Waiting for app to report healthy..." +until docker compose ps laravel | grep -q "(healthy)"; do + sleep 3 +done + +# Clear out cached data +echo ":: Clearing cache" +docker compose exec laravel php artisan optimize:clear +docker compose exec laravel php artisan cache:clear + +# Run database migrations +echo ":: Running migrations" +docker compose exec laravel php artisan migrate --force + +# Optimize +echo ":: Caching config, routes, and views" +docker compose exec laravel php artisan optimize + +# Live again +echo ":: Bringing application back up" +docker compose exec laravel php artisan up || true + +# Prune dangling image builds +echo "Prune dangling images" +docker image prune -a -f \ + --filter "label=com.docker.compose.project=$(basename $(pwd))" \ + --filter "label=com.docker.compose.service=laravel" + +echo ":: Docker disk space summary" +docker system df + +#echo ":: Prune build cache" +#docker builder prune -f + +echo "✅ Deployment complete!" \ No newline at end of file From 5d3b71baf29199651fc34849fdfc6c54e58934f6 Mon Sep 17 00:00:00 2001 From: Connor Abbas Date: Mon, 30 Jun 2025 12:22:37 -0500 Subject: [PATCH 4/7] ssr fix --- vite.config.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vite.config.js b/vite.config.js index ac810ca6..23056156 100644 --- a/vite.config.js +++ b/vite.config.js @@ -45,5 +45,8 @@ export default ({ mode }) => { preview: { port: devPort, }, + ssr: { + noExternal: true, // bundle node server related files, so we don't need node_modules in production + }, }); }; From 351e8fecee3fd65b662732db3492d3c0edd29382 Mon Sep 17 00:00:00 2001 From: Connor Abbas Date: Mon, 30 Jun 2025 21:13:06 -0500 Subject: [PATCH 5/7] improvement: better Dockerfile comments --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0bc330ba..e806cccb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,13 +9,13 @@ RUN install-php-extensions bcmath gd pgsql # Node Image FROM node:${NODE_VERSION}-alpine AS node -# Composer Stage +# Install Composer packages FROM base AS composer WORKDIR /var/www/html COPY composer.json composer.lock ./ RUN composer install --no-dev --optimize-autoloader --no-scripts --no-interaction -# Assets Stage +# Install and bundle NPM packages FROM node:${NODE_VERSION}-alpine AS build-assets WORKDIR /var/www/html COPY package*.json ./ @@ -59,7 +59,7 @@ COPY --chown=www-data:www-data --from=build-assets /var/www/html/public/build ./ COPY --chown=www-data:www-data . . USER www-data -# SSR Node Production Image +# SSR Production Image FROM base AS ssr-release COPY --from=node /usr/lib /usr/lib COPY --from=node /usr/local/lib /usr/local/lib From a14ce2843c2a644f6cc9261f4af4535610323263 Mon Sep 17 00:00:00 2001 From: Connor Abbas Date: Mon, 30 Jun 2025 21:17:09 -0500 Subject: [PATCH 6/7] fix: remove deploy script, out of scope --- docker-deploy.sh | 56 ------------------------------------------------ 1 file changed, 56 deletions(-) delete mode 100755 docker-deploy.sh diff --git a/docker-deploy.sh b/docker-deploy.sh deleted file mode 100755 index b9c7bb94..00000000 --- a/docker-deploy.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Usage: chmod +x docker-deploy.sh && ./docker-deploy.sh - -# Make sure we're in the project root -cd "$(dirname "$0")" - -# Maintenance mode -echo ":: Entering maintenance mode" -docker compose exec laravel php artisan down || true - -# Pull latest code -echo ":: Fetching latest from Git" -git pull origin master - -# Rebuild & restart container -echo ":: Rebuilding app image & restarting" -docker compose up -d --build --force-recreate laravel - -# Wait for successful health check -echo ":: Waiting for app to report healthy..." -until docker compose ps laravel | grep -q "(healthy)"; do - sleep 3 -done - -# Clear out cached data -echo ":: Clearing cache" -docker compose exec laravel php artisan optimize:clear -docker compose exec laravel php artisan cache:clear - -# Run database migrations -echo ":: Running migrations" -docker compose exec laravel php artisan migrate --force - -# Optimize -echo ":: Caching config, routes, and views" -docker compose exec laravel php artisan optimize - -# Live again -echo ":: Bringing application back up" -docker compose exec laravel php artisan up || true - -# Prune dangling image builds -echo "Prune dangling images" -docker image prune -a -f \ - --filter "label=com.docker.compose.project=$(basename $(pwd))" \ - --filter "label=com.docker.compose.service=laravel" - -echo ":: Docker disk space summary" -docker system df - -#echo ":: Prune build cache" -#docker builder prune -f - -echo "✅ Deployment complete!" \ No newline at end of file From 87f93ef0ca9e1be5c92fb84b6f2e96b5ba59c6ec Mon Sep 17 00:00:00 2001 From: Connor Abbas Date: Sat, 5 Jul 2025 18:28:40 +0000 Subject: [PATCH 7/7] vite port --- docker-compose.dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 2be407c5..f3caea09 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -9,8 +9,8 @@ services: GROUP_ID: '${GROUP_ID:-1000}' extra_hosts: - 'host.docker.internal:host-gateway' - ports: - - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' # Not necessarily required for dev containers (auto port forwarding) + #ports: + #- '${VITE_PORT:-5173}:${VITE_PORT:-5173}' # Not necessarily required for dev containers (auto port forwarding) environment: PHP_OPCACHE_ENABLE: '1' PHP_OPCACHE_REVALIDATE_FREQ: '0'