0

I'm trying to get a PHP FPM application working on Google Cloud Run (Docker), but I'm not sure how to set it up to run with FPM instead of Apache? I've looked all around, but don't see any clear instructions.

I followed the Google PHP Quickstart tutorial, so I have this Dockerfile that works:

# Use the official PHP image.
# https://hub.docker.com/_/php
FROM php:apache

# Configure PHP for Cloud Run.
# Precompile PHP code with opcache.
RUN docker-php-ext-install -j "$(nproc)" opcache
RUN set -ex; \
  { \
    echo "; Cloud Run enforces memory & timeouts"; \
    echo "memory_limit = -1"; \
    echo "max_execution_time = 0"; \
    echo "; File upload at Cloud Run network limit"; \
    echo "upload_max_filesize = 32M"; \
    echo "post_max_size = 32M"; \
    echo "; Configure Opcache for Containers"; \
    echo "opcache.enable = On"; \
    echo "opcache.validate_timestamps = Off"; \
    echo "; Configure Opcache Memory (Application-specific)"; \
    echo "opcache.memory_consumption = 32"; \
  } > "$PHP_INI_DIR/conf.d/cloud-run.ini"

# Copy in custom code from the host machine.
WORKDIR /var/www/html
COPY . ./

# Use the PORT environment variable in Apache configuration files.
# https://cloud.google.com/run/docs/reference/container-contract#port
RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf

# Configure PHP for development.
# Switch to the production php.ini for production operations.
# RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# https://github.com/docker-library/docs/blob/master/php/README.md#configuration
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"

Any ideas on how to get this working with PHP FPM? Thanks so much!

I tried changing FROM php:apache to FROM php:fpm, but it does not work; I believe it must be due to the fact it's still using Apache? Apologies, I'm somewhat new to Docker.

  • 1
    You are correct you will still need apache or some web server in addition to php-fpm. You are simply opting to use fpm over mod_php, suggest reading on that more. Does this help at all in terms of the need for additional/seperate conf? https://stackoverflow.com/questions/54270656/difference-between-apache-vs-fpm-in-php-docker-image – ficuscr May 26 '23 at 21:36
  • 1
    You do not need PHP-FPM for Cloud Run. The additional complexity will not provide any benefits. For most applications, you do not even need Apache provided that your framework provides a simple HTTP server. The functionality that Apache provides (Reverse Proxy) is already provided by the Google Cloud Run Front End. – John Hanley May 26 '23 at 22:51
  • 2
    @JohnHanley the HTTP server that is bundled with PHP is _extremely_ stripped-down, and is strongly recommended _against_ for anything other than limited local testing. A "proper" HTTP server like Apache or Nginx fronting an FPM pool would be the recommended deployment for a PHP app, unless Cloud Run can connect directly to FPM's FCGI interface. – Sammitch May 26 '23 at 23:51
  • @Sammitch - Under Cloud Run, Apache is not required and not needed if the framework has a basic HTTP server. Cloud Run already has a Reverse Proxy front end that protects the application from the same types of issues that Apache does. No, Cloud Run knows nothing about FPM. FPM provides no benefit under Cloud Run for PHP. Under Cloud Run if an application crashed or hanged, Cloud Run would terminate the container and launch a new one. – John Hanley May 27 '23 at 00:29
  • I am not saying that using Apache is a bad decision. Apache makes many applications easier to deploy and is well understood. I am just clarifying what Cloud Run provides and/or requires. There is a negative to using Apache. It will increase the cold start time for Cloud Run containers. Apache needs to be started, configured, etc on each cold start. For busy applications, that is not a problem except for the first request to the container. – John Hanley May 27 '23 at 00:32
  • @JohnHanley Unlike Python/Node/etc PHP applications are generally not persistent or daemonized. Over-generalizing a bit, but when a request is received 100% of the application code is loaded from disk/cache, the app runs and serves the request, and the worker process is functionally restarted from scratch with no knowledge of what it just ran. You can't just bolt on an HTTP server library from the framework because PHP applications are generally not daemons in the first place, so those libs don't really exist. – Sammitch May 27 '23 at 00:52
  • That's not to say that it's not _possible_ to have a persistent app, but it's just inherently at odds with how PHP apps are generally structured, and presents their own set of challenges because PHP itself has never really made a tremendous effort to be good at that sort of thing. On the other hand, the PHP interpreter itself has an HTTP server, but as I said it is very stripped down and limited to handling a _single_ request at a time. Hence, an external HTTP server is all but required for most apps. – Sammitch May 27 '23 at 00:52
  • @Sammitch - your comments generally apply to Apache and PHP. However, regarding PHP apps and Cloud Run, I respectfully disagree with you. Have you studied the design model of Cloud Run and the life cycle of Cloud Run applications? Cloud Run is an HTTP Request and Response system, not a full-blown web application server. – John Hanley May 27 '23 at 01:22
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/253855/discussion-between-sammitch-and-john-hanley). – Sammitch May 27 '23 at 01:49

1 Answers1

0

Apache and FPM are two different things.

In short:

  • Apache is an HTTP server to handle web requests. The rest of the world will talk to it via the HTTP protocol.
  • FPM is an FastCGI Process Manager that manages PHP processes "behind the scenes", and the HTTP server will talk to it via the FCGI protocol.

Thus, you cannot remove Apache from the equation unless you plan to replace it with some other HTTP server.

That said, the php:apache uses the mod_php Apache module to run PHP and you could have a container that ran FPM in the background, but:

  1. Dockerhub's PHP library images do not currently have an image like this, so you'd either have to pick a 3rd-party image or make it yourself.
  2. Running 2 different daemon processes inside a single container is always a bit icky. [Which is likely a factor in there not being a library image for it]
  3. In the best case scenario the end result would be functionally indistinguishable from just using the php:apache image as-is.

As I suggested to @John-Hanley in the comments, if Cloud Run's proxy can speak FCGI it may be possible to connect directly to an FPM container, but I think that it is unlikely that that is the case as FCGI is generally not a protocol you would expose even remotely publicly. Not to mention that you would need to make special accommodations in your app and/or config to serve things like static files [eg: images, css] which is usually handled directly by the HTTP server.

In short: Unless you're ready to put in a lot of legwork for little, if any, discernible difference, then just use the stock php:apache image as recommended.

Sammitch
  • 30,782
  • 7
  • 50
  • 77