# ---------------------------------------------- Build Time Arguments -------------------------------------------------- ARG PHP_VERSION="8.2" ARG PHP_ALPINE_VERSION="3.16" ARG COMPOSER_VERSION="2" ARG COMPOSER_AUTH ARG APP_BASE_DIR="." # -------------------------------------------------- Composer Image ---------------------------------------------------- FROM composer:${COMPOSER_VERSION} as composer # ====================================================================================================================== # --- Base --- # --------------- This stage install needed extenstions, plugins and add all needed configurations ------------------- # ====================================================================================================================== FROM php:${PHP_VERSION}-fpm-alpine${PHP_ALPINE_VERSION} AS base # Maintainer label LABEL maintainer="sherifabdlnaby@gmail.com" # Set SHELL flags for RUN commands to allow -e and pipefail # Rationale: https://github.com/hadolint/hadolint/wiki/DL4006 SHELL ["/bin/ash", "-eo", "pipefail", "-c"] # ------------------------------------- Install Packages Needed Inside Base Image -------------------------------------- RUN RUNTIME_DEPS="tini fcgi"; \ SECURITY_UPGRADES="curl"; \ apk add --no-cache --upgrade ${RUNTIME_DEPS} ${SECURITY_UPGRADES} # ---------------------------------------- Install / Enable PHP Extensions --------------------------------------------- RUN apk add --no-cache --virtual .build-deps \ $PHPIZE_DEPS \ libzip-dev \ icu-dev \ # PHP Extensions --------------------------------- \ && docker-php-ext-install -j$(nproc) \ intl \ opcache \ zip \ # Pecl Extensions -------------------------------- \ && pecl install apcu && docker-php-ext-enable apcu \ # Cleanup ---------------------------------------- \ && rm -r /tmp/pear; \ # - Detect Runtime Dependencies of the installed extensions. \ # - src: https://github.com/docker-library/wordpress/blob/master/latest/php8.0/fpm-alpine/Dockerfile \ out="$(php -r 'exit(0);')"; \ [ -z "$out" ]; err="$(php -r 'exit(0);' 3>&1 1>&2 2>&3)"; \ [ -z "$err" ]; extDir="$(php -r 'echo ini_get("extension_dir");')"; \ [ -d "$extDir" ]; \ runDeps="$( \ scanelf --needed --nobanner --format '%n#p' --recursive "$extDir" \ | tr ',' '\n' | sort -u | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ )"; \ # Save Runtime Deps in a virtual deps apk add --no-network --virtual .php-extensions-rundeps $runDeps; \ # Uninstall Everything we Installed (minus the runtime Deps) apk del --no-network .build-deps; \ # check for output like "PHP Warning: PHP Startup: Unable to load dynamic library 'foo' (tried: ...) err="$(php --version 3>&1 1>&2 2>&3)"; [ -z "$err" ] # ----------------------------------------------- # Install posgresql RUN apk add libpq-dev \ && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ && docker-php-ext-install pdo pdo_pgsql pgsql # Install redis RUN apk add --no-cache pcre-dev $PHPIZE_DEPS \ && pecl install redis \ && docker-php-ext-enable redis # ------------------------------------------------- Permissions -------------------------------------------------------- # - Clean bundled config/users & recreate them with UID 1000 for docker compatability in dev container. # - Create composer directories (since we run as non-root later) # - Add Default Config RUN deluser --remove-home www-data && adduser -u1000 -D www-data && rm -rf /var/www /usr/local/etc/php-fpm.d/* && \ mkdir -p /var/www/.composer /app && chown -R www-data:www-data /app /var/www/.composer; \ # ------------------------------------------------ PHP Configuration --------------------------------------------------- mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" # Add in Base PHP Config COPY php/base-* $PHP_INI_DIR/conf.d # ---------------------------------------------- PHP FPM Configuration ------------------------------------------------- # PHP-FPM config COPY fpm/*.conf /usr/local/etc/php-fpm.d/ # --------------------------------------------------- Scripts ---------------------------------------------------------- COPY entrypoint/*-base post-build/*-base pre-run/*-base \ fpm/healthcheck-fpm \ scripts/command-loop* \ # to /usr/local/bin/ RUN chmod +x /usr/local/bin/*-base /usr/local/bin/healthcheck-fpm /usr/local/bin/command-loop* # ---------------------------------------------------- Composer -------------------------------------------------------- COPY --from=composer /usr/bin/composer /usr/bin/composer # ----------------------------------------------------- MISC ----------------------------------------------------------- WORKDIR /app USER www-data # Common PHP Frameworks Env Variables ENV APP_ENV prod ENV APP_DEBUG 0 # Validate FPM config (must use the non-root user) RUN php-fpm -t # ---------------------------------------------------- HEALTH ---------------------------------------------------------- HEALTHCHECK CMD ["healthcheck-fpm"] # -------------------------------------------------- ENTRYPOINT -------------------------------------------------------- ENTRYPOINT ["entrypoint-base"] CMD ["php-fpm"] # ====================================================================================================================== # --- Vendor --- # --------------- This stage will install composer runtime dependinces and install app dependinces. ------------------ # ====================================================================================================================== FROM composer as vendor ARG PHP_VERSION ARG COMPOSER_AUTH ARG APP_BASE_DIR # A Json Object with remote repository token to clone private Repos with composer # Reference: https://getcomposer.org/doc/03-cli.md#composer-auth ENV COMPOSER_AUTH $COMPOSER_AUTH WORKDIR /app # Copy Dependencies files COPY $APP_BASE_DIR/composer.json composer.json COPY $APP_BASE_DIR/composer.lock composer.lock # Set PHP Version of the Image RUN composer config platform.php ${PHP_VERSION}; \ # Install Dependencies composer install -n --no-progress --ignore-platform-reqs --no-dev --prefer-dist --no-scripts --no-autoloader # ====================================================================================================================== # ============================================== PRODUCTION IMAGE ==================================================== # --- PROD --- # ====================================================================================================================== FROM base AS app ARG APP_BASE_DIR USER root # Copy PHP Production Configuration COPY php/prod-* $PHP_INI_DIR/conf.d/ COPY entrypoint/*-prod post-build/*-prod pre-run/*-prod \ # to /usr/local/bin/ RUN chmod +x /usr/local/bin/*-prod USER www-data # ----------------------------------------------- Production Config ----------------------------------------------------- # Copy Vendor COPY --chown=www-data:www-data --from=vendor /app/vendor /app/vendor # Copy App Code COPY --chown=www-data:www-data $APP_BASE_DIR/ . ## Run Composer Install again ## ( this time to run post-install scripts, autoloader, and post-autoload scripts using one command ) RUN composer install --optimize-autoloader --apcu-autoloader --no-dev -n --no-progress && \ composer check-platform-reqs && \ post-build-base && post-build-prod ENTRYPOINT ["entrypoint-prod"] CMD ["php-fpm"] # ====================================================================================================================== # ============================================== DEVELOPMENT IMAGE =================================================== # --- DEV --- # ====================================================================================================================== FROM base as app-dev ENV APP_ENV dev ENV APP_DEBUG 1 # Switch root to install stuff USER root # For Composer Installs RUN apk --no-cache add git openssh bash # ---------------------------------------------------- Scripts --------------------------------------------------------- # Copy Dev Scripts COPY php/dev-* $PHP_INI_DIR/conf.d/ COPY entrypoint/*-dev post-build/*-dev pre-run/*-dev \ # to /usr/local/bin/ RUN chmod +x /usr/local/bin/*-dev; \ mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" USER www-data # ------------------------------------------------- Entry Point -------------------------------------------------------- # Entrypoints ENTRYPOINT ["entrypoint-dev"] CMD ["php-fpm"]