diff --git a/Dockerfile b/Dockerfile index 56e197c830..b1936099e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,174 +1,14 @@ ############################################################################### -# EspoCRM - Minimal Secure Build from Source -# Multi-stage build with Alpine base images +# EspoCRM - Development Server for Extensions +# Based on official image, overlays custom code on each deploy ############################################################################### -# Stage 1: Build frontend assets -FROM node:20-alpine AS frontend -WORKDIR /build -COPY package.json package-lock.json ./ -RUN npm ci --ignore-scripts -COPY . . -RUN npx grunt offline +FROM espocrm/espocrm:latest -# Stage 2: Install PHP dependencies -FROM composer:2 AS composer -WORKDIR /build -COPY composer.json composer.lock ./ -COPY dev/ ./dev/ -RUN composer install \ - --no-dev \ - --no-interaction \ - --no-progress \ - --prefer-dist \ - --optimize-autoloader \ - --ignore-platform-reqs +# Copy custom extensions and modifications +COPY custom/ /var/www/html/custom/ -# Stage 3: Minimal runtime -FROM php:8.4-fpm-alpine +# Ensure correct permissions for custom dir +RUN chown -R www-data:www-data /var/www/html/custom -RUN set -ex; \ - apk add --no-cache \ - nginx \ - freetype \ - libjpeg-turbo \ - libwebp \ - libpng \ - libzip \ - libpq \ - libldap \ - icu-libs \ - unzip \ - ; \ - apk add --no-cache --virtual .build-deps \ - freetype-dev \ - libjpeg-turbo-dev \ - libwebp-dev \ - libpng-dev \ - libzip-dev \ - postgresql-dev \ - openldap-dev \ - icu-dev \ - ; \ - docker-php-ext-configure gd \ - --with-freetype --with-jpeg --with-webp \ - ; \ - docker-php-ext-install -j$(nproc) \ - gd pdo_mysql pdo_pgsql zip ldap \ - exif pcntl posix bcmath intl \ - ; \ - apk del .build-deps; \ - rm -rf /tmp/* /var/cache/apk/* - -# PHP hardened config -RUN { \ - echo 'expose_php = Off'; \ - echo 'display_errors = Off'; \ - echo 'display_startup_errors = Off'; \ - echo 'log_errors = On'; \ - echo 'memory_limit = 256M'; \ - echo 'max_execution_time = 180'; \ - echo 'max_input_time = 180'; \ - echo 'post_max_size = 50M'; \ - echo 'upload_max_filesize = 50M'; \ - echo 'session.cookie_httponly = 1'; \ - echo 'session.cookie_secure = 1'; \ - echo 'session.use_strict_mode = 1'; \ -} > "$PHP_INI_DIR/conf.d/espocrm.ini" - -# Nginx config -RUN cat > /etc/nginx/http.d/default.conf <<'NGINX' -server { - listen 80; - server_name _; - root /var/www/html; - index index.php index.html; - - server_tokens off; - add_header X-Content-Type-Options "nosniff" always; - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-XSS-Protection "1; mode=block" always; - add_header Referrer-Policy "same-origin" always; - - client_max_body_size 50M; - - location / { - try_files $uri $uri/ /index.php?$query_string; - } - - location ~ \.php$ { - fastcgi_pass 127.0.0.1:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - include fastcgi_params; - fastcgi_read_timeout 180; - } - - location ~ /\. { deny all; } - location ~ ^/(data|application|custom|vendor)/ { deny all; } - location = /data/config.php { deny all; } -} -NGINX - -WORKDIR /var/www/html - -# Copy application -COPY --chown=82:82 . . -COPY --chown=82:82 --from=composer /build/vendor ./vendor -COPY --chown=82:82 --from=frontend /build/client ./client - -# Remove dev/build files -RUN rm -rf node_modules .git .github tests dev \ - Gruntfile.js package.json package-lock.json \ - phpstan.neon phpunit.xml .idea .vscode \ - .editorconfig .gitattributes .gitignore .npmrc \ - diff.js lang.js po.js jsconfig.json - -# Set permissions -RUN set -ex; \ - find . -type d -exec chmod 755 {} +; \ - find . -type f -exec chmod 644 {} +; \ - chmod 754 bin/command 2>/dev/null || true; \ - for dir in data custom client/custom; do \ - mkdir -p "$dir"; \ - chown -R 82:82 "$dir"; \ - done - -# Entrypoint -COPY --chmod=755 <<'EOF' /entrypoint.sh -#!/bin/sh -set -e - -if [ -n "$ESPOCRM_DATABASE_HOST" ] && [ ! -f "data/config.php" ]; then - echo "Waiting for database..." - i=0 - while [ $i -lt 30 ]; do - if php -r "new PDO('mysql:host=${ESPOCRM_DATABASE_HOST};port=${ESPOCRM_DATABASE_PORT:-3306}','${ESPOCRM_DATABASE_USER:-root}','${ESPOCRM_DATABASE_PASSWORD}');" 2>/dev/null; then - echo "Database ready. Running installer..." - php bin/command install \ - --databasePlatform="${ESPOCRM_DATABASE_PLATFORM:-Mysql}" \ - --databaseHost="$ESPOCRM_DATABASE_HOST" \ - --databasePort="${ESPOCRM_DATABASE_PORT:-3306}" \ - --databaseName="${ESPOCRM_DATABASE_NAME:-espocrm}" \ - --databaseUser="${ESPOCRM_DATABASE_USER:-root}" \ - --databasePassword="$ESPOCRM_DATABASE_PASSWORD" \ - --adminUsername="${ESPOCRM_ADMIN_USERNAME:-admin}" \ - --adminPassword="${ESPOCRM_ADMIN_PASSWORD:-admin}" \ - --siteUrl="${ESPOCRM_SITE_URL:-http://localhost}" \ - && echo "Install complete." \ - || echo "CLI install failed. Use web installer." - break - fi - i=$((i + 1)) - sleep 2 - done -fi - -php-fpm -D -exec nginx -g 'daemon off;' -EOF - -VOLUME /var/www/html/data EXPOSE 80 - -ENTRYPOINT ["/entrypoint.sh"]