Files
michaelschiemer/Dockerfile.production

140 lines
3.6 KiB
Docker

# Production Dockerfile - Multi-Stage Build
# Stage: Composer Dependencies (Production)
FROM php:8.5.0RC3-fpm AS composer-deps-production
WORKDIR /app
# Copy composer files
COPY composer.json composer.lock ./
# Install system dependencies for Composer
RUN apt-get update && apt-get install -y \
git \
unzip \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
RUN composer install \
--no-dev \
--no-scripts \
--no-autoloader \
--ignore-platform-reqs \
--prefer-dist
# Copy application code
COPY . .
# Generate optimized autoloader
RUN composer dump-autoload --optimize --classmap-authoritative
# Stage: Frontend Build
FROM node:20-alpine AS frontend-build
WORKDIR /app
# Copy package files
COPY package.json package-lock.json ./
# Install npm dependencies
RUN npm ci --production=false
# Copy source files needed for build
COPY resources ./resources
COPY vite.config.js ./
COPY tsconfig.json ./
# Build production assets
RUN npm run build
# Stage: Production Runtime
FROM php:8.5.0RC3-fpm AS production
# Install system dependencies + nginx for production
RUN apt-get update && apt-get install -y \
nginx \
curl \
libzip-dev \
libpng-dev \
libjpeg-dev \
libfreetype6-dev \
libwebp-dev \
libavif-dev \
libxpm-dev \
libsodium-dev \
libpq-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-configure gd \
--with-freetype \
--with-jpeg \
--with-webp \
--with-avif \
--with-xpm \
&& docker-php-ext-install -j$(nproc) gd
RUN docker-php-ext-install -j$(nproc) \
zip \
pdo \
pdo_mysql \
pdo_pgsql \
pcntl \
posix \
shmop \
bcmath \
sodium
# Install PECL extensions
RUN pecl install apcu redis-6.3.0RC1 \
&& docker-php-ext-enable apcu redis
# Configure APCu
RUN echo "apc.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini \
&& echo "apc.shm_size=128M" >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini
# Set working directory
WORKDIR /var/www/html
# Configure PHP for production
COPY docker/php/php.production.ini /usr/local/etc/php/conf.d/zzz-custom.ini
COPY docker/php/opcache.ini /usr/local/etc/php/conf.d/opcache.ini
# Configure PHP-FPM (clear_env = no for Docker secrets)
COPY docker/php/www.production.conf /usr/local/etc/php-fpm.d/www.conf
# Configure Nginx for Traefik integration
COPY docker/nginx/nginx.production.conf /etc/nginx/nginx.conf
COPY docker/nginx/default.traefik.conf /etc/nginx/sites-available/default
RUN ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
# Copy application code and dependencies
COPY --chown=www-data:www-data . .
COPY --from=composer-deps-production --chown=www-data:www-data /app/vendor ./vendor
COPY --from=frontend-build --chown=www-data:www-data /app/public/assets ./public/assets
COPY --from=frontend-build --chown=www-data:www-data /app/public/.vite ./public/.vite
# Create required directories
RUN mkdir -p storage/logs storage/cache storage/uploads \
&& chown -R www-data:www-data storage \
&& chmod -R 775 storage
# Copy entrypoint script for production
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
# Healthcheck
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD curl -f http://localhost/health || exit 1
# Expose HTTP only (Traefik handles HTTPS)
EXPOSE 80
# Use production entrypoint
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["nginx-php-fpm"]