That Time Composer's Timeout Drove Me Nuts
- Date
- Takeshi Yu
You know what's frustrating? Spending hours debugging what seems like a simple Docker build issue, only to find out it's something completely unexpected. That's exactly what happened to me recently while working on a Laravel deployment.
Pretty standard stuff - I was building a Docker image for a Laravel app that needed to run on Linode. Nothing fancy, just your typical setup:
- PHP8.3 with all the usual suspects.
- Setting up MongoDB drivers and extensions via PECL.
- Installing Caddy Server.
- Supervisor to keep processes in check.
- Copying files and configuring related services.
The Problem
Everything seemed fine until the build kept failing at exactly 300 seconds. Like clockwork. Here's what I was seeing:
=> CANCELED exporting to image 37.6s
...
The following exception is caused by a process timeout
Check https://getcomposer.org/doc/06-config.md#process-timeout for details
ERROR: failed to solve: Canceled: context canceled
In Process.php line 1205:
The process "DOCKER_BUILDKIT=1 docker 'build' '--no-cache' '-t' 'my/api' '.'" exceeded the timeout of 300 seconds.
build [--dev] [--no-dev] [--] [<args>...]
The Head-Scratching Begins
My first thought? "Oh great, Docker's being Docker again." You know how it goes - you immediately blame the most obvious suspect. I spent a good chunk of time diving into Docker's documentation, looking for some mysterious build timeout setting that I must have missed. But something didn't add up. Many official images take way longer than 300 seconds to build, and they work just fine. Plus, if Docker had a built-in timeout, wouldn't it be, I don't know, documented somewhere?
The Plot Thickens
Being a good developer (or at least trying to be), I figured I'd try to optimize my build with multi-stage builds. Here's what I came up with:
FROM php:8.3-fpm AS mongodb-builder
RUN apt-get update && apt-get install -y \
libssl-dev \
&& pecl install mongodb \
&& docker-php-ext-enable mongodb
# ...
FROM php:8.3-fpm
COPY --from=mongodb-builder /usr/local/lib/php/extensions /usr/local/lib/php/extensions
COPY --from=mongodb-builder /usr/local/etc/php/conf.d/docker-php-ext-mongodb.ini /usr/local/etc/php/conf.d/
RUN apt-get update && apt-get install -y \
curl gnupg gosu zip unzip git supervisor sqlite3 libcap2-bin \
libpng-dev dnsutils librsvg2-bin fswatch vim libzip-dev \
libxml2-dev libcurl4-openssl-dev libssl-dev \
&& docker-php-ext-install zip pdo_mysql bcmath soap intl opcache \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# ...
Did it fix the problem? Nope. But it did make my Dockerfile look prettier, so there's that.
The Lightbulb Moment
Then I noticed something in the error message that I'd glossed over before:
Check https://getcomposer.org/doc/06-config.md#process-timeout for details
Composer? But I'm just installing Composer in my Dockerfile:
&& curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \
That's when it hit me. I had these neat little shortcuts in my composer.json
:
"lint": "pint",
"clear": [
"@php artisan lighthouse:clear-cache",
"@php artisan config:clear",
"@php artisan route:clear",
"@php artisan view:clear",
"@php artisan cache:clear"
],
"test": [
"@lint",
"@clear",
"pest --profile --colors=always"
],
"docker": "DOCKER_BUILDKIT=1 docker",
"build": [
"@clear",
"@docker build --no-cache -t tgk/be .",
"@docker tag tgk/be heytakeshi/tgk-be:latest",
"@docker push heytakeshi/tgk-be"
]
And I was running my Docker builds through Composer with composer build
. Guess what has a 300-second default timeout? Yep, Composer.
The Fix
The solution was embarrassingly simple. Either:
- Tell Composer to chill out a bit ( managing the process timeout ):
"config": {
// ...
"process-timeout": 600
},
- Or move the Docker commands to a shell script where Composer can't boss them around:
#!/bin/bash
DOCKER_BUILDKIT=1 docker build --no-cache -t my/api .
docker tag my/api my/api
docker push my/api
I went with option 1 because I was too lazy to update all my deployment scripts.
The Lesson
Sometimes the problem isn't where you think it is. I spent way too long looking at Docker documentation when the answer was right there in the error message. Also, maybe running everything through Composer scripts isn't always the best idea - but that's a problem for future me.
Next time you hit a weird timeout, check your Composer config. It might just save you a few hours of Docker documentation diving.