From 5ef73a8041baa8612b83210941bb3b1aa86a3985 Mon Sep 17 00:00:00 2001 From: zino Date: Wed, 19 Nov 2025 16:03:36 +0100 Subject: [PATCH] Add Docker-based dev/prod setup with zail helper scripts --- .dockerignore | 47 +++++++++++ .env.example | 17 ++-- app/Jobs/TestLogJob.php | 21 +++++ compose.yaml | 130 +++++++++++++++++++++++++++++++ composer.json | 2 +- docker/bin/zail | 63 +++++++++++++++ docker/common/php-fpm/Dockerfile | 97 +++++++++++++++++++++++ docker/php-fpm/entrypoint.sh | 23 ++++++ docker/workspace/Dockerfile | 84 ++++++++++++++++++++ package-lock.json | 2 +- 10 files changed, 479 insertions(+), 7 deletions(-) create mode 100644 .dockerignore create mode 100644 app/Jobs/TestLogJob.php create mode 100644 compose.yaml create mode 100755 docker/bin/zail create mode 100644 docker/common/php-fpm/Dockerfile create mode 100644 docker/php-fpm/entrypoint.sh create mode 100644 docker/workspace/Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4876d51 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,47 @@ +# Include any files or directories that you don't want to be copied to your +# container here (e.g., local build artifacts, temporary files, etc.). +# +# For more help, visit the .dockerignore file reference guide at +# https://docs.docker.com/go/build-context-dockerignore/ + +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.gitattributes +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.next +**/.cache +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/charts +**/docker-compose* +**/compose.y*ml +**/compose.*.y*ml +!**/composer.json +!**/composer.lock +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +**/vendor +**/.DS_Store +.editorconfig +.env.example +LICENSE +README.md + +# Ignore development-related files and directories +# For development environment, we will use mount bind to mount the source code to the container +# So we don't need to copy the source code to the container for development +tests/ +phpunit.xml +phpunit.xml.dist \ No newline at end of file diff --git a/.env.example b/.env.example index adc461c..7525956 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,5 @@ -APP_NAME=Laravel +APP_NAME="Laravel Starter Kit" +APP_NAME_SLUG=laravel-starter-kit APP_ENV=local APP_KEY= APP_DEBUG=true @@ -21,11 +22,11 @@ LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug DB_CONNECTION=mariadb -DB_HOST=127.0.0.1 +DB_HOST=mariadb DB_PORT=3306 DB_DATABASE=laravel-starter-kit -DB_USERNAME=root -DB_PASSWORD=password +DB_USERNAME=laravel +DB_PASSWORD=starter-secret SESSION_DRIVER=database SESSION_LIFETIME=120 @@ -37,7 +38,7 @@ BROADCAST_CONNECTION=log FILESYSTEM_DISK=local QUEUE_CONNECTION=database -CACHE_STORE=database +CACHE_STORE=file # CACHE_PREFIX= MEMCACHED_HOST=127.0.0.1 @@ -63,3 +64,9 @@ AWS_BUCKET= AWS_USE_PATH_STYLE_ENDPOINT=false VITE_APP_NAME="${APP_NAME}" + +# Docker: Sync user ID and group ID to avoid permission issues on development +UID=1000 +GID=1000 + +XDEBUG_ENABLED=false diff --git a/app/Jobs/TestLogJob.php b/app/Jobs/TestLogJob.php new file mode 100644 index 0000000..d88752d --- /dev/null +++ b/app/Jobs/TestLogJob.php @@ -0,0 +1,21 @@ +...]" + exit 1 +fi + +CMD="$1" +shift || true + +case "$CMD" in + up) + dc up "$@" + ;; + down) + dc down "$@" + ;; + stop) + # Entspricht in etwa "sail stop" + dc stop "$@" + ;; + restart) + dc down + dc up "$@" + ;; + ps) + dc ps "$@" + ;; + logs) + # Logs aller Services folgen + dc logs -f "$@" + ;; + bash|shell|sh) + dc exec "$SERVICE" bash + ;; + artisan) + dc exec "$SERVICE" php artisan "$@" + ;; + composer) + dc exec "$SERVICE" composer "$@" + ;; + npm|yarn|pnpm) + dc exec "$SERVICE" "$CMD" "$@" + ;; + *) + # Fallback: beliebigen Befehl im Standard-Service ausführen + dc exec "$SERVICE" "$CMD" "$@" + ;; +esac diff --git a/docker/common/php-fpm/Dockerfile b/docker/common/php-fpm/Dockerfile new file mode 100644 index 0000000..8554228 --- /dev/null +++ b/docker/common/php-fpm/Dockerfile @@ -0,0 +1,97 @@ +# docker/common/php-fpm/Dockerfile + +# Stage 1: Build environment and Composer dependencies +FROM php:8.4-fpm AS builder + +# Install system dependencies and PHP extensions required for Laravel + MySQL/PostgreSQL support +RUN apt-get update && apt-get install -y --no-install-recommends \ + curl \ + unzip \ + libpq-dev \ + libonig-dev \ + libssl-dev \ + libxml2-dev \ + libcurl4-openssl-dev \ + libicu-dev \ + libzip-dev \ + && docker-php-ext-install -j"$(nproc)" \ + pdo_mysql \ + pdo_pgsql \ + pgsql \ + opcache \ + intl \ + zip \ + bcmath \ + soap \ + && pecl install redis \ + && docker-php-ext-enable redis \ + && apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# Arbeitsverzeichnis +WORKDIR /var/www + +# Kompletten Code kopieren (für composer-Skripte wie artisan package:discover) +COPY . /var/www + +# Composer installieren und Dependencies holen +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \ + && composer install --no-dev --optimize-autoloader --no-interaction --no-progress --prefer-dist + + +# Stage 2: Development image (einziger Runtime-Stage) +FROM builder AS development + +# Xdebug / Dev-Settings +ARG XDEBUG_ENABLED=true +ARG XDEBUG_MODE=develop,coverage,debug,profile +ARG XDEBUG_HOST=host.docker.internal +ARG XDEBUG_IDE_KEY=DOCKER +ARG XDEBUG_LOG=/dev/stdout +ARG XDEBUG_LOG_LEVEL=0 + +# User/Group-IDs für die Rechte-Synchronisierung +ARG UID=1000 +ARG GID=1000 + +USER root + +# Xdebug konfigurieren, falls aktiviert +RUN if [ "${XDEBUG_ENABLED}" = "true" ]; then \ + pecl install xdebug && \ + docker-php-ext-enable xdebug && \ + { \ + echo "xdebug.mode=${XDEBUG_MODE}"; \ + echo "xdebug.idekey=${XDEBUG_IDE_KEY}"; \ + echo "xdebug.log=${XDEBUG_LOG}"; \ + echo "xdebug.log_level=${XDEBUG_LOG_LEVEL}"; \ + echo "xdebug.client_host=${XDEBUG_HOST}"; \ + echo "xdebug.start_with_request=yes"; \ + } >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \ + fi + +# User/Gruppe anlegen (oder existierende Gruppe wiederverwenden) +RUN if getent group "${GID}" >/dev/null; then \ + group_name="$(getent group "${GID}" | cut -d: -f1)"; \ + useradd -m -u "${UID}" -g "${GID}" -s /bin/bash www; \ + else \ + groupadd -g "${GID}" www && \ + useradd -m -u "${UID}" -g www -s /bin/bash www; \ + group_name=www; \ + fi \ + && sed -i "s/user = www-data/user = www/g" /usr/local/etc/php-fpm.d/www.conf \ + && sed -i "s/group = www-data/group = ${group_name}/g" /usr/local/etc/php-fpm.d/www.conf + +# Arbeitsverzeichnis +WORKDIR /var/www + +# neuen Entry-Point für Dev-Container verwenden +COPY ./docker/php-fpm/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Zurück auf unprivilegierten User +USER www + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] + +EXPOSE 9000 +CMD ["php-fpm"] diff --git a/docker/php-fpm/entrypoint.sh b/docker/php-fpm/entrypoint.sh new file mode 100644 index 0000000..39a03c6 --- /dev/null +++ b/docker/php-fpm/entrypoint.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -e + +APP_DIR=/var/www + +if [ -n "${UID}" ] && [ -n "${GID}" ]; then + echo "Fixing file permissions with UID=${UID} and GID=${GID}..." + + for path in storage bootstrap/cache; do + if [ -d "${APP_DIR}/${path}" ]; then + chown -R "${UID}:${GID}" "${APP_DIR}/${path}" || true + fi + done +fi + +if [ -f "${APP_DIR}/artisan" ]; then + echo "Clearing configurations..." + php "${APP_DIR}/artisan" config:clear || true + php "${APP_DIR}/artisan" route:clear || true + php "${APP_DIR}/artisan" view:clear || true +fi + +exec "$@" diff --git a/docker/workspace/Dockerfile b/docker/workspace/Dockerfile new file mode 100644 index 0000000..b6df532 --- /dev/null +++ b/docker/workspace/Dockerfile @@ -0,0 +1,84 @@ +# docker/workspace/Dockerfile +# Use the official PHP CLI image as the base +FROM php:8.4-cli + +# Set environment variables for user and group ID +ARG UID=1000 +ARG GID=1000 +ARG NODE_VERSION=22.0.0 + +# Install system dependencies and build libraries +RUN apt-get update && apt-get install -y --no-install-recommends \ + curl \ + unzip \ + libpq-dev \ + libonig-dev \ + libssl-dev \ + libxml2-dev \ + libcurl4-openssl-dev \ + libicu-dev \ + libzip-dev \ + && docker-php-ext-install -j"$(nproc)" \ + pdo_mysql \ + pdo_pgsql \ + pgsql \ + opcache \ + intl \ + zip \ + bcmath \ + soap \ + && pecl install redis xdebug \ + && docker-php-ext-enable redis xdebug \ + && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \ + && apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# Xdebug-Args +ARG XDEBUG_ENABLED +ARG XDEBUG_MODE +ARG XDEBUG_HOST +ARG XDEBUG_IDE_KEY +ARG XDEBUG_LOG +ARG XDEBUG_LOG_LEVEL + +# Configure Xdebug if enabled +RUN if [ "${XDEBUG_ENABLED}" = "true" ]; then \ + docker-php-ext-enable xdebug && \ + { \ + echo "xdebug.mode=${XDEBUG_MODE}"; \ + echo "xdebug.idekey=${XDEBUG_IDE_KEY}"; \ + echo "xdebug.log=${XDEBUG_LOG}"; \ + echo "xdebug.log_level=${XDEBUG_LOG_LEVEL}"; \ + echo "xdebug.client_host=${XDEBUG_HOST}"; \ + echo "xdebug.start_with_request=yes"; \ + } >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \ + fi + +# User/Gruppe anlegen +RUN if getent group "${GID}" >/dev/null; then \ + useradd -m -u "${UID}" -g "${GID}" -s /bin/bash www; \ + else \ + groupadd -g "${GID}" www && \ + useradd -m -u "${UID}" -g www -s /bin/bash www; \ + fi \ + && usermod -aG sudo www \ + && echo 'www ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +USER www + +# NVM + Node installieren +RUN export NVM_DIR="$HOME/.nvm" && \ + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash && \ + [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" && \ + nvm install "${NODE_VERSION}" && \ + nvm alias default "${NODE_VERSION}" && \ + nvm use default + +RUN echo 'export NVM_DIR="$HOME/.nvm"' >> /home/www/.bashrc && \ + echo '[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"' >> /home/www/.bashrc && \ + echo '[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"' >> /home/www/.bashrc + +WORKDIR /var/www + +ENTRYPOINT [] + +CMD ["bash"] diff --git a/package-lock.json b/package-lock.json index a17ce7a..184e2a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "laravel-starter-kit", + "name": "www", "lockfileVersion": 3, "requires": true, "packages": {