Deploy a Laravel application on Google Cloud Run with PHP 8.5, connect to Cloud SQL PostgreSQL, and scale to zero when idle. A practical guide covering containerization, deployment to the africa-south1 region, and tips for handling storage, sessions, and queues in a serverless environment.
Google Cloud Run is a serverless platform that lets you run containerized applications without managing any infrastructure. You push a container, Cloud Run handles scaling — including scaling to zero when there's no traffic, which means you only pay for what you use.
For someone like me who has been deploying Laravel applications on traditional Compute Engine instances and Kubernetes clusters, Cloud Run feels like a breath of fresh air for certain workloads. Not everything needs a full-blown GKE cluster or a dedicated VM running 24/7. Sometimes you just need your app to be available, scale when needed, and not cost you anything when it's idle.
What makes this particularly interesting right now is that Google Cloud has made the PHP 8.5 runtime generally available on Cloud Run. If you're running Laravel 12 on PHP 8.5 — as I am — this is great news.
Laravel is traditionally deployed on a web server like Nginx or Apache, sitting behind PHP-FPM, on a Linux server you manage yourself. That's perfectly fine for production workloads that need full control. But for staging environments, internal tools, API backends, or even personal projects, Cloud Run removes a lot of the operational overhead.
Key advantages that stand out for me:
africa-south1 (Johannesburg) is supported, which means latency from Mauritius is reasonable thanks to the submarine cable connectivity.Before deploying to Cloud Run, your Laravel application needs to be containerized. If you've worked with Docker before — and if you're deploying Laravel in 2026, you probably have — this is straightforward.
Create a Dockerfile in the root of your Laravel project:
FROM php:8.5-apache
RUN apt-get update && apt-get install -y \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip \
&& docker-php-ext-install pdo_pgsql mbstring exif pcntl bcmath gd
RUN a2enmod rewrite
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY . .
RUN composer install --no-dev --optimize-autoloader
RUN php artisan config:cache && php artisan route:cache && php artisan view:cache
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
EXPOSE 8080
RUN sed -i 's/80/8080/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
CMD ["apache2-foreground"]A couple of things to note here. Cloud Run expects your container to listen on port 8080 by default — that's why we're modifying the Apache configuration. I'm using pdo_pgsql because I connect to Cloud SQL PostgreSQL, but swap that for pdo_mysql if you're on MySQL.
With the Dockerfile ready, deploying is a single gcloud command. First, make sure you have the Google Cloud SDK installed and authenticated.
gcloud run deploy my-laravel-app \
--source . \
--region africa-south1 \
--allow-unauthenticated \
--set-env-vars APP_KEY=base64:YOUR_APP_KEY_HERE \
--set-env-vars APP_ENV=production \
--set-env-vars LOG_CHANNEL=stderr \
--set-env-vars DB_CONNECTION=pgsql \
--set-env-vars DB_HOST=/cloudsql/PROJECT_ID:africa-south1:INSTANCE_NAME \
--add-cloudsql-instances PROJECT_ID:africa-south1:INSTANCE_NAME \
--memory 512Mi \
--cpu 1 \
--min-instances 0 \
--max-instances 5The --source . flag tells Cloud Run to build the container image for you using Cloud Build — so you don't even need to push to Artifact Registry manually. Google handles the build and deployment in one step.
Notice the --min-instances 0 — this is what enables scale-to-zero. For a staging environment or a low-traffic application, this keeps your costs minimal. For production, you might want to set --min-instances 1 to avoid cold starts.
The LOG_CHANNEL=stderr setting is important. Cloud Run captures stderr output and sends it to Cloud Logging, so you get your Laravel logs in the Google Cloud Console without any additional configuration.
If you're using Cloud SQL — and I've written about scaling Laravel with Cloud SQL read replicas before — Cloud Run has built-in support for connecting through the Cloud SQL Auth Proxy. The --add-cloudsql-instances flag in the deploy command sets this up automatically.
The connection happens over a Unix socket, which is why the DB_HOST is set to /cloudsql/PROJECT_ID:REGION:INSTANCE_NAME rather than an IP address. This is secure by default — no public IP required on your Cloud SQL instance.
Laravel's default file storage driver writes to the local filesystem. That won't work on Cloud Run because the container filesystem is ephemeral — it gets wiped on every new deployment or instance scale event. For file uploads and storage, switch to Google Cloud Storage using the league/flysystem-google-cloud-storage package:
composer require league/flysystem-google-cloud-storageConfigure a gcs disk in your config/filesystems.php and set FILESYSTEM_DISK=gcs in your environment variables. Cloud Run's service account will handle authentication automatically if you've granted it the Storage Object Admin role — no API keys needed.
Cloud Run is stateless. This means you cannot rely on the local filesystem for sessions or cache. Use Redis (via Memorystore) or database sessions instead. Similarly, Laravel's scheduler (php artisan schedule:run) doesn't work in Cloud Run's request-driven model. For scheduled tasks, pair Cloud Scheduler with Cloud Run by having the scheduler trigger an HTTP endpoint on your application.
Queue workers are another consideration. Cloud Run isn't designed for long-running processes, so running php artisan queue:work inside a Cloud Run container isn't ideal. Instead, use Cloud Tasks to dispatch jobs to a dedicated Cloud Run endpoint, or run your workers on a Compute Engine instance or GKE.
Cloud Run sits in a sweet spot between the full control of a Compute Engine VM and the abstraction of a purely serverless function. For Laravel applications that don't need persistent background processes or filesystem state, it's an excellent deployment target — especially now that PHP 8.5 is fully supported.
I've been using it for a couple of internal tools and staging environments, and the cost savings alone from scale-to-zero make it worth exploring. If you're already on Google Cloud and deploying Laravel, it's worth giving Cloud Run a try on your next project.