Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP: pecl install is still slow and still produces massive binaries #34278

Open
BHSPitMonkey opened this issue Sep 7, 2023 · 13 comments
Open

Comments

@BHSPitMonkey
Copy link

What version of gRPC and what language are you using?

  • All versions of gRPC
  • PHP

What operating system (Linux, Windows,...) and version?

  • Linux (all versions)

What runtime / compiler are you using (e.g. python version or version of gcc)

  • pecl (all versions)

What did you do?

Please provide either 1) A unit test for reproducing the bug or 2) Specific steps for us to follow to reproduce the bug. If there’s not enough information to debug the problem, gRPC team may close the issue at their discretion. You’re welcome to re-open the issue once you have a reproduction.

time sudo pecl install grpc

What did you expect to see?

The extension install in a reasonable timeframe and at a reasonable size

What did you see instead?

The extension install takes on the order of 30 minutes, and produces a ~50MB binary that is ~10x larger than intended due to the inclusion of debug symbols (which should not be present in builds created or distributed this way).

Make sure you include information that can help us debug (full error message, exception listing, stack trace, logs).

See TROUBLESHOOTING.md for how to diagnose problems better.

Anything else we should know about your project / environment?

Please see the existing discussion at #23626.

I'm opening this as a new Issue because the previous one was closed seemingly by accident (and I lack the permissions to reopen it). If that Issue can be reopened, this one can be closed as a duplicate. Until then, the problem risks not being tracked or mitigated.

@mcandylab
Copy link

I confirm. The problem is relevant. I get 30 minutes to install the extension. Exactly because of this problem, I’m already thinking about rewriting my application into another programming language, just so as not to encounter this extension again.

@grassdionera
Copy link

grassdionera commented Oct 23, 2023

i confirm too. Install grpc with pecl takes more then 30 Minutes. in Docker environment.
But even the build from source, explained here https://github.com/grpc/grpc/tree/master/src/php#build-from-source takes about 20 Minutes with make -j 4 in a docker environment.

So i thinks its not only with pecl.

during build i can see that the most time is used by building all the third_party extensions

the library is really big i think:

ls -lah /usr/local/lib/php/extensions/no-debug-non-zts-20210902/grpc.so
-rw-r--r--    1 root     root      217.3M Oct 23 11:14 /usr/local/lib/php/extensions/no-debug-non-zts-20210902/grpc.so

@grassdionera
Copy link

setting ENV MAKEFLAGS=" -j 4" with pecl speeds it up to about 15 Minutes build time

@pfuhrmann
Copy link

pfuhrmann commented Nov 1, 2023

You can strip the debug symbols using strip --strip-debug /usr/local/lib/php/extensions/*/grpc.so, which will reduce the size of the binary considerably. Make sure to do it in the same container layer where you built the binary, to get the benefits.

I can also confirm we are dealing with 30 min. build times. However, we are extending FROM base image, which is also built by us. This way, it's not affecting the actual SDLC of applications.

@AndrewCustomSumIT
Copy link

I would also like to say we are experiencing 30 minute build times when installing into Docker and running on Bitbucket Pipelines. Current Dockerfile uses the commands:

FROM php:8.2.12-fpm
RUN pecl install grpc \
  && docker-php-ext-enable grpc

@gplanchat
Copy link

gplanchat commented Dec 22, 2023

I have the same issue here, the build process takes ~2 hours and produces a 235MB binary.

I am using API Platform 2.7.

Counter measures I used are in the following Dockerfile (I followed solutions in previous comments):

ARG PHP_VERSION=8.2

FROM php:${PHP_VERSION}-fpm-alpine

RUN set -eux; \
	apk add --no-cache --virtual .build-deps \
		$PHPIZE_DEPS \
		zlib-dev \
		linux-headers \
	;

# isolate gRPC as the build times are problematic, see https://github.com/grpc/grpc/issues/34278
RUN set -eux; \
	MAKEFLAGS="-j $(nproc)" pecl install \
		grpc \
	;

RUN set -eux; \
    apk add --no-cache \
        libstdc++  \
    ;

# strip php extensions to decrease container size
RUN set -eux; \
    find "$(php-config --extension-dir)" -name '*.so' -type f -exec strip --strip-all {} ';' \
    ;

RUN set -eux; \
    pecl clear-cache \
    ; \
    docker-php-ext-enable \
        grpc \
    ;

RUN set -eux; \
    runDeps="$( \
        scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
            | tr ',' '\n' \
            | sort -u \
            | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
    )" \
    ; \
    apk add --no-cache --virtual .api-phpexts-rundeps $runDeps \
    ; \
    apk del .build-deps

@shyim
Copy link

shyim commented Dec 28, 2023

If you are using alpine with Docker. Checkout this:

RUN apk add --no-cache git grpc-cpp grpc-dev $PHPIZE_DEPS && \
    GRPC_VERSION=$(apk info grpc -d | grep grpc | cut -d- -f2) && \
    git clone --depth 1 -b v${GRPC_VERSION} https://github.com/grpc/grpc /tmp/grpc && \
    cd /tmp/grpc/src/php/ext/grpc && \
    phpize && \
    ./configure && \
    make && \
    make install && \
    rm -rf /tmp/grpc && \
    apk del --no-cache git grpc-dev $PHPIZE_DEPS && \
    echo "extension=grpc.so" > /usr/local/etc/php/conf.d/grpc.ini

It installs in few seconds

@luishgp
Copy link

luishgp commented Feb 8, 2024

If you are using alpine with Docker. Checkout this:

RUN apk add --no-cache git grpc-cpp grpc-dev $PHPIZE_DEPS && \
    GRPC_VERSION=$(apk info grpc -d | grep grpc | cut -d- -f2) && \
    git clone --depth 1 -b v${GRPC_VERSION} https://github.com/grpc/grpc /tmp/grpc && \
    cd /tmp/grpc/src/php/ext/grpc && \
    phpize && \
    ./configure && \
    make && \
    make install && \
    rm -rf /tmp/grpc && \
    apk del --no-cache git grpc-dev $PHPIZE_DEPS && \
    echo "extension=grpc.so" > /usr/local/etc/php/conf.d/grpc.ini

It installs in few seconds

It worked nicely! ❤️

@shyim Do you know of any way to work with a multi-stage build? I'm building gRPC in one stage and copying the binary result, but I'm facing an issue with Unable to load dynamic library 'grpc' even though the library path is correct and the binary was successfully copied.

FROM php:8.2-fpm-alpine AS php-ext

# Install packages and remove default server definition
RUN apk update && apk add --no-cache --virtual \
    build-essentials \
    linux-headers \
    curl \
    git \
    grep \
    build-base \
    imagemagick-dev \
    pcre-dev \
    libtool \
    make \
    autoconf \
    g++ \
    libpq-dev \
    icu-dev \
    icu-libs \
    zlib-dev \
    automake \
    libzip-dev \
    libpng-dev \
    libwebp-dev \
    libjpeg-turbo-dev \
    freetype-dev \
    libxml2-dev

RUN apk add --no-cache git grpc-cpp grpc-dev $PHPIZE_DEPS && \
    git clone --depth 1 -b v1.59.4 https://github.com/grpc/grpc /tmp/grpc && \
    cd /tmp/grpc/src/php/ext/grpc && \
    phpize && \
    ./configure && \
    make && \
    make install && \
    rm -rf /tmp/grpc && \
    apk del --no-cache git grpc-dev $PHPIZE_DEPS

RUN docker-php-source extract \
    # ext-opache
    && docker-php-ext-enable opcache \
    # ext-igbinary
    && mkdir -p /usr/src/php/ext/igbinary \
    &&  curl -fsSL https://github.com/igbinary/igbinary/archive/refs/tags/3.2.15.tar.gz | tar xvz -C /usr/src/php/ext/igbinary --strip 1 \
    && docker-php-ext-install igbinary \
    # ext-redis
    && mkdir -p /usr/src/php/ext/redis \
    && curl -fsSL https://github.com/phpredis/phpredis/archive/refs/tags/6.0.2.tar.gz | tar xvz -C /usr/src/php/ext/redis --strip 1 \
    && docker-php-ext-configure redis --enable-redis-igbinary \
    && docker-php-ext-install redis \
    # ext-apcu
    && mkdir -p /usr/src/php/ext/apcu \
    && curl -fsSL https://github.com/krakjoe/apcu/archive/refs/tags/v5.1.23.tar.gz | tar xvz -C /usr/src/php/ext/apcu --strip 1 \
    && docker-php-ext-install apcu \
    # ext-bcmath, ext-sockets
    && docker-php-ext-install bcmath sockets \
    ## cleanup
    && docker-php-source delete

RUN docker-php-source extract \
    && git clone --branch 1.17.2 --depth 1 https://github.com/mongodb/mongo-php-driver.git /usr/src/php/ext/mongodb \
    && cd /usr/src/php/ext/mongodb && git submodule update --init \
    && docker-php-ext-install mongodb

RUN docker-php-ext-configure gd --enable-gd --with-freetype --with-jpeg --with-webp \
    && docker-php-ext-install gd

RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \
    && docker-php-ext-install pdo pdo_pgsql pgsql

RUN docker-php-ext-install xml soap exif

RUN pecl install imagick \
    && docker-php-ext-enable imagick

FROM php:8.2-fpm-alpine

WORKDIR /var/www/html

ARG USERNAME=pilot
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Install packages and remove default server definition
RUN apk update && apk add --no-cache --virtual \
    curl \
    git \
    supervisor \
    openssh \
    nginx

# Create system user to run Composer and Artisan Commands
RUN addgroup -g $USER_GID $USERNAME \
    && adduser -u $USER_UID -G $USERNAME -s /bin/bash -h /home/$USERNAME -D $USERNAME

RUN mkdir -p /home/$USERNAME/.composer && \
    chown -R $USERNAME:$USERNAME /home/$USERNAME

# Setup document root
RUN mkdir -p /var/www/html \
    && mkdir -p /var/lib/nginx \
    && mkdir -p /var/lib/nginx/tmp \
    && mkdir -p /var/log/nginx

# Make sure files/folders needed by the processes are accessable when they run under the nobody user
RUN chown -R $USERNAME:$USERNAME /var/www/html \
    && chown -R $USERNAME:$USERNAME /run \
    && chown -R $USERNAME:$USERNAME /var/lib/nginx \
    && chown -R $USERNAME:$USERNAME /var/log/nginx

# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Copy grpc extension from php-ext stage
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/grpc.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/grpc.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/apcu.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/apcu.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/igbinary.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/igbinary.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/opcache.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/opcache.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/redis.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sockets.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sockets.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sodium.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sodium.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/mongodb.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/mongodb.so

# Enable grpc extension
RUN docker-php-ext-enable grpc apcu igbinary opcache redis sockets sodium mongodb

# Configure nginx
COPY config/nginx.conf /etc/nginx/nginx.conf

# Configure PHP-FPM
COPY config/fpm-pool.conf /etc/php8/php-fpm.d/www.conf
COPY config/php.ini "$PHP_INI_DIR/php.ini"

# Configure supervisord
COPY config/supervisord.conf /etc/supervisord.conf

# Add application
COPY --chown=$USERNAME:$USERNAME src/ /var/www/html/

# Switch to use a non-root user from here on
USER $USERNAME

# Expose the port nginx is reachable on
EXPOSE 8080

# Let supervisord start nginx & php-fpm
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

# Configure a healthcheck to validate that everything is up&running
HEALTHCHECK --timeout=10s CMD curl --silent --fail http://127.0.0.1:8080/fpm-ping

@shyim
Copy link

shyim commented Feb 8, 2024

I would try to install grpc-cpp package with apk and try out if that helps

@jay-steyn
Copy link

If you are using alpine with Docker. Checkout this:

RUN apk add --no-cache git grpc-cpp grpc-dev $PHPIZE_DEPS && \
    GRPC_VERSION=$(apk info grpc -d | grep grpc | cut -d- -f2) && \
    git clone --depth 1 -b v${GRPC_VERSION} https://github.com/grpc/grpc /tmp/grpc && \
    cd /tmp/grpc/src/php/ext/grpc && \
    phpize && \
    ./configure && \
    make && \
    make install && \
    rm -rf /tmp/grpc && \
    apk del --no-cache git grpc-dev $PHPIZE_DEPS && \
    echo "extension=grpc.so" > /usr/local/etc/php/conf.d/grpc.ini

It installs in few seconds

It worked nicely! ❤️

@shyim Do you know of any way to work with a multi-stage build? I'm building gRPC in one stage and copying the binary result, but I'm facing an issue with Unable to load dynamic library 'grpc' even though the library path is correct and the binary was successfully copied.

FROM php:8.2-fpm-alpine AS php-ext

# Install packages and remove default server definition
RUN apk update && apk add --no-cache --virtual \
    build-essentials \
    linux-headers \
    curl \
    git \
    grep \
    build-base \
    imagemagick-dev \
    pcre-dev \
    libtool \
    make \
    autoconf \
    g++ \
    libpq-dev \
    icu-dev \
    icu-libs \
    zlib-dev \
    automake \
    libzip-dev \
    libpng-dev \
    libwebp-dev \
    libjpeg-turbo-dev \
    freetype-dev \
    libxml2-dev

RUN apk add --no-cache git grpc-cpp grpc-dev $PHPIZE_DEPS && \
    git clone --depth 1 -b v1.59.4 https://github.com/grpc/grpc /tmp/grpc && \
    cd /tmp/grpc/src/php/ext/grpc && \
    phpize && \
    ./configure && \
    make && \
    make install && \
    rm -rf /tmp/grpc && \
    apk del --no-cache git grpc-dev $PHPIZE_DEPS

RUN docker-php-source extract \
    # ext-opache
    && docker-php-ext-enable opcache \
    # ext-igbinary
    && mkdir -p /usr/src/php/ext/igbinary \
    &&  curl -fsSL https://github.com/igbinary/igbinary/archive/refs/tags/3.2.15.tar.gz | tar xvz -C /usr/src/php/ext/igbinary --strip 1 \
    && docker-php-ext-install igbinary \
    # ext-redis
    && mkdir -p /usr/src/php/ext/redis \
    && curl -fsSL https://github.com/phpredis/phpredis/archive/refs/tags/6.0.2.tar.gz | tar xvz -C /usr/src/php/ext/redis --strip 1 \
    && docker-php-ext-configure redis --enable-redis-igbinary \
    && docker-php-ext-install redis \
    # ext-apcu
    && mkdir -p /usr/src/php/ext/apcu \
    && curl -fsSL https://github.com/krakjoe/apcu/archive/refs/tags/v5.1.23.tar.gz | tar xvz -C /usr/src/php/ext/apcu --strip 1 \
    && docker-php-ext-install apcu \
    # ext-bcmath, ext-sockets
    && docker-php-ext-install bcmath sockets \
    ## cleanup
    && docker-php-source delete

RUN docker-php-source extract \
    && git clone --branch 1.17.2 --depth 1 https://github.com/mongodb/mongo-php-driver.git /usr/src/php/ext/mongodb \
    && cd /usr/src/php/ext/mongodb && git submodule update --init \
    && docker-php-ext-install mongodb

RUN docker-php-ext-configure gd --enable-gd --with-freetype --with-jpeg --with-webp \
    && docker-php-ext-install gd

RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \
    && docker-php-ext-install pdo pdo_pgsql pgsql

RUN docker-php-ext-install xml soap exif

RUN pecl install imagick \
    && docker-php-ext-enable imagick

FROM php:8.2-fpm-alpine

WORKDIR /var/www/html

ARG USERNAME=pilot
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Install packages and remove default server definition
RUN apk update && apk add --no-cache --virtual \
    curl \
    git \
    supervisor \
    openssh \
    nginx

# Create system user to run Composer and Artisan Commands
RUN addgroup -g $USER_GID $USERNAME \
    && adduser -u $USER_UID -G $USERNAME -s /bin/bash -h /home/$USERNAME -D $USERNAME

RUN mkdir -p /home/$USERNAME/.composer && \
    chown -R $USERNAME:$USERNAME /home/$USERNAME

# Setup document root
RUN mkdir -p /var/www/html \
    && mkdir -p /var/lib/nginx \
    && mkdir -p /var/lib/nginx/tmp \
    && mkdir -p /var/log/nginx

# Make sure files/folders needed by the processes are accessable when they run under the nobody user
RUN chown -R $USERNAME:$USERNAME /var/www/html \
    && chown -R $USERNAME:$USERNAME /run \
    && chown -R $USERNAME:$USERNAME /var/lib/nginx \
    && chown -R $USERNAME:$USERNAME /var/log/nginx

# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Copy grpc extension from php-ext stage
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/grpc.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/grpc.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/apcu.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/apcu.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/igbinary.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/igbinary.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/opcache.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/opcache.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/redis.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sockets.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sockets.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sodium.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sodium.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/mongodb.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/mongodb.so

# Enable grpc extension
RUN docker-php-ext-enable grpc apcu igbinary opcache redis sockets sodium mongodb

# Configure nginx
COPY config/nginx.conf /etc/nginx/nginx.conf

# Configure PHP-FPM
COPY config/fpm-pool.conf /etc/php8/php-fpm.d/www.conf
COPY config/php.ini "$PHP_INI_DIR/php.ini"

# Configure supervisord
COPY config/supervisord.conf /etc/supervisord.conf

# Add application
COPY --chown=$USERNAME:$USERNAME src/ /var/www/html/

# Switch to use a non-root user from here on
USER $USERNAME

# Expose the port nginx is reachable on
EXPOSE 8080

# Let supervisord start nginx & php-fpm
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

# Configure a healthcheck to validate that everything is up&running
HEALTHCHECK --timeout=10s CMD curl --silent --fail http://127.0.0.1:8080/fpm-ping

Also had the same errors on build - felt like it was all to good to be true.. did you figure out a fix?

@luishgp
Copy link

luishgp commented Feb 24, 2024

If you are using alpine with Docker. Checkout this:

RUN apk add --no-cache git grpc-cpp grpc-dev $PHPIZE_DEPS && \
    GRPC_VERSION=$(apk info grpc -d | grep grpc | cut -d- -f2) && \
    git clone --depth 1 -b v${GRPC_VERSION} https://github.com/grpc/grpc /tmp/grpc && \
    cd /tmp/grpc/src/php/ext/grpc && \
    phpize && \
    ./configure && \
    make && \
    make install && \
    rm -rf /tmp/grpc && \
    apk del --no-cache git grpc-dev $PHPIZE_DEPS && \
    echo "extension=grpc.so" > /usr/local/etc/php/conf.d/grpc.ini

It installs in few seconds

It worked nicely! ❤️
@shyim Do you know of any way to work with a multi-stage build? I'm building gRPC in one stage and copying the binary result, but I'm facing an issue with Unable to load dynamic library 'grpc' even though the library path is correct and the binary was successfully copied.

FROM php:8.2-fpm-alpine AS php-ext

# Install packages and remove default server definition
RUN apk update && apk add --no-cache --virtual \
    build-essentials \
    linux-headers \
    curl \
    git \
    grep \
    build-base \
    imagemagick-dev \
    pcre-dev \
    libtool \
    make \
    autoconf \
    g++ \
    libpq-dev \
    icu-dev \
    icu-libs \
    zlib-dev \
    automake \
    libzip-dev \
    libpng-dev \
    libwebp-dev \
    libjpeg-turbo-dev \
    freetype-dev \
    libxml2-dev

RUN apk add --no-cache git grpc-cpp grpc-dev $PHPIZE_DEPS && \
    git clone --depth 1 -b v1.59.4 https://github.com/grpc/grpc /tmp/grpc && \
    cd /tmp/grpc/src/php/ext/grpc && \
    phpize && \
    ./configure && \
    make && \
    make install && \
    rm -rf /tmp/grpc && \
    apk del --no-cache git grpc-dev $PHPIZE_DEPS

RUN docker-php-source extract \
    # ext-opache
    && docker-php-ext-enable opcache \
    # ext-igbinary
    && mkdir -p /usr/src/php/ext/igbinary \
    &&  curl -fsSL https://github.com/igbinary/igbinary/archive/refs/tags/3.2.15.tar.gz | tar xvz -C /usr/src/php/ext/igbinary --strip 1 \
    && docker-php-ext-install igbinary \
    # ext-redis
    && mkdir -p /usr/src/php/ext/redis \
    && curl -fsSL https://github.com/phpredis/phpredis/archive/refs/tags/6.0.2.tar.gz | tar xvz -C /usr/src/php/ext/redis --strip 1 \
    && docker-php-ext-configure redis --enable-redis-igbinary \
    && docker-php-ext-install redis \
    # ext-apcu
    && mkdir -p /usr/src/php/ext/apcu \
    && curl -fsSL https://github.com/krakjoe/apcu/archive/refs/tags/v5.1.23.tar.gz | tar xvz -C /usr/src/php/ext/apcu --strip 1 \
    && docker-php-ext-install apcu \
    # ext-bcmath, ext-sockets
    && docker-php-ext-install bcmath sockets \
    ## cleanup
    && docker-php-source delete

RUN docker-php-source extract \
    && git clone --branch 1.17.2 --depth 1 https://github.com/mongodb/mongo-php-driver.git /usr/src/php/ext/mongodb \
    && cd /usr/src/php/ext/mongodb && git submodule update --init \
    && docker-php-ext-install mongodb

RUN docker-php-ext-configure gd --enable-gd --with-freetype --with-jpeg --with-webp \
    && docker-php-ext-install gd

RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \
    && docker-php-ext-install pdo pdo_pgsql pgsql

RUN docker-php-ext-install xml soap exif

RUN pecl install imagick \
    && docker-php-ext-enable imagick

FROM php:8.2-fpm-alpine

WORKDIR /var/www/html

ARG USERNAME=pilot
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Install packages and remove default server definition
RUN apk update && apk add --no-cache --virtual \
    curl \
    git \
    supervisor \
    openssh \
    nginx

# Create system user to run Composer and Artisan Commands
RUN addgroup -g $USER_GID $USERNAME \
    && adduser -u $USER_UID -G $USERNAME -s /bin/bash -h /home/$USERNAME -D $USERNAME

RUN mkdir -p /home/$USERNAME/.composer && \
    chown -R $USERNAME:$USERNAME /home/$USERNAME

# Setup document root
RUN mkdir -p /var/www/html \
    && mkdir -p /var/lib/nginx \
    && mkdir -p /var/lib/nginx/tmp \
    && mkdir -p /var/log/nginx

# Make sure files/folders needed by the processes are accessable when they run under the nobody user
RUN chown -R $USERNAME:$USERNAME /var/www/html \
    && chown -R $USERNAME:$USERNAME /run \
    && chown -R $USERNAME:$USERNAME /var/lib/nginx \
    && chown -R $USERNAME:$USERNAME /var/log/nginx

# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Copy grpc extension from php-ext stage
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/grpc.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/grpc.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/apcu.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/apcu.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/igbinary.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/igbinary.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/opcache.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/opcache.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/redis.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sockets.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sockets.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sodium.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/sodium.so
COPY --from=php-ext /usr/local/lib/php/extensions/no-debug-non-zts-20220829/mongodb.so /usr/local/lib/php/extensions/no-debug-non-zts-20220829/mongodb.so

# Enable grpc extension
RUN docker-php-ext-enable grpc apcu igbinary opcache redis sockets sodium mongodb

# Configure nginx
COPY config/nginx.conf /etc/nginx/nginx.conf

# Configure PHP-FPM
COPY config/fpm-pool.conf /etc/php8/php-fpm.d/www.conf
COPY config/php.ini "$PHP_INI_DIR/php.ini"

# Configure supervisord
COPY config/supervisord.conf /etc/supervisord.conf

# Add application
COPY --chown=$USERNAME:$USERNAME src/ /var/www/html/

# Switch to use a non-root user from here on
USER $USERNAME

# Expose the port nginx is reachable on
EXPOSE 8080

# Let supervisord start nginx & php-fpm
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

# Configure a healthcheck to validate that everything is up&running
HEALTHCHECK --timeout=10s CMD curl --silent --fail http://127.0.0.1:8080/fpm-ping

Also had the same errors on build - felt like it was all to good to be true.. did you figure out a fix?

This is what my Dockerfile looks like.

https://gist.github.com/luishgp/873a9b4759457169b6c6cd7aaea19707

Hope it helps you

@jay-steyn
Copy link

jay-steyn commented Feb 24, 2024

@luishgp I did try that, but this morning, I figured it out. I removed grpc-dev from apk del .. it seems without it the so file doesn't load

@CRC-Mismatch
Copy link

CRC-Mismatch commented Mar 21, 2024

I have the same issue here, the build process takes ~2 hours and produces a 235MB binary.

I am using API Platform 2.7.

Counter measures I used are in the following Dockerfile (I followed solutions in previous comments):

ARG PHP_VERSION=8.2

FROM php:${PHP_VERSION}-fpm-alpine

RUN set -eux; \
	apk add --no-cache --virtual .build-deps \
		$PHPIZE_DEPS \
		zlib-dev \
		linux-headers \
	;

# isolate gRPC as the build times are problematic, see https://github.com/grpc/grpc/issues/34278
RUN set -eux; \
	MAKEFLAGS="-j $(nproc)" pecl install \
		grpc \
	;

RUN set -eux; \
    apk add --no-cache \
        libstdc++  \
    ;

# strip php extensions to decrease container size
RUN set -eux; \
    find "$(php-config --extension-dir)" -name '*.so' -type f -exec strip --strip-all {} ';' \
    ;

RUN set -eux; \
    pecl clear-cache \
    ; \
    docker-php-ext-enable \
        grpc \
    ;

RUN set -eux; \
    runDeps="$( \
        scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
            | tr ',' '\n' \
            | sort -u \
            | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
    )" \
    ; \
    apk add --no-cache --virtual .api-phpexts-rundeps $runDeps \
    ; \
    apk del .build-deps

I'd guess that unless you're using that in a multi-stage build and copying things over, the final image's layers sum up to the layer size from that step alone + whatever size differences before and after it... If you want the image pullers to have a "good time", you'll either need to split it in a multi-stage build and include the specific files via COPY, or use a single RUN command doing all the dependency-installs, compiling, cleanup. Keep in mind that every Dockerfile RUN or COPY directive produces a new layer ON TOP of the previous ones, containing the differences - it doesn't affect whatever differences were added by previous layers, and when one pulls an image's tag or version, the container engine also has to pull all the previous layers that lead to it!

@grassdionera I think I may be doing something wrong, on my part... I've tried RUN export MAKEFLAGS="-j 8"; pecl install grpc (and also $(nproc) in place of a static 8 for this and all other cases) and RUN MAKEFLAGS="-j 8" pecl install grpc, but both gave me the same final build time as a plain pecl install grpc on a 4-core builder...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests