Add minimal secure Dockerfile for Coolify deployment

This commit is contained in:
2026-03-15 14:11:32 +00:00
parent 501de26774
commit f6c845e627
+173
View File
@@ -0,0 +1,173 @@
###############################################################################
# EspoCRM - Minimal Secure Build from Source
# Multi-stage build with Alpine base images
###############################################################################
# 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
# Stage 2: Install PHP dependencies
FROM composer:2 AS composer
WORKDIR /build
COPY composer.json composer.lock ./
RUN composer install \
--no-dev \
--no-interaction \
--no-progress \
--prefer-dist \
--optimize-autoloader \
--ignore-platform-reqs
# Stage 3: Minimal runtime
FROM php:8.4-fpm-alpine
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"]