修复:保留生产构建基础依赖缓存

This commit is contained in:
WuYongJie 2026-08-26 13:24:59 +08:00
parent 530e32ffc3
commit 4e702bfa45
3 changed files with 75 additions and 14 deletions

View File

@ -1,9 +1,9 @@
# syntax=docker/dockerfile:1.7
FROM php:8.3-apache-bookworm AS php-base
FROM php:8.3-apache-bookworm@sha256:fa8852a2e01747ffe8c8768bfd6bbc2f296f974aa0de90ee157a66664996d263 AS php-base
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
RUN apt-get -o Acquire::Retries=3 update \
&& apt-get -o Acquire::Retries=3 install -y --no-install-recommends \
curl \
libcurl4-openssl-dev \
libfreetype6-dev \
@ -37,22 +37,38 @@ RUN apt-get update \
&& a2enmod expires headers rewrite \
&& rm -rf /var/lib/apt/lists/*
FROM composer:2.8@sha256:5248900ab8b5f7f880c2d62180e40960cd87f60149ec9a1abfd62ac72a02577c AS composer-bin
FROM php-base AS vendor
COPY --from=composer:2.8 /usr/bin/composer /usr/local/bin/composer
COPY --from=composer-bin /usr/bin/composer /usr/local/bin/composer
WORKDIR /build
COPY composer.json composer.lock ./
RUN --mount=type=cache,target=/tmp/composer-cache \
COMPOSER_CACHE_DIR=/tmp/composer-cache composer install \
--prefer-dist \
--no-dev \
--no-interaction \
--no-progress \
--no-scripts \
--optimize-autoloader
set -eu; \
attempt=1; \
while true; do \
if COMPOSER_CACHE_DIR=/tmp/composer-cache \
COMPOSER_MAX_PARALLEL_HTTP=4 \
composer install \
--prefer-dist \
--no-dev \
--no-interaction \
--no-progress \
--no-scripts \
--optimize-autoloader; then \
break; \
fi; \
if [ "$attempt" -ge 3 ]; then \
exit 1; \
fi; \
attempt=$((attempt + 1)); \
echo "Composer install failed; retrying ($attempt/3)." >&2; \
sleep 3; \
done
FROM php-base AS runtime

View File

@ -14,6 +14,10 @@ param(
[string]$DatabaseImage = 'mariadb:11.4',
[string]$DatabaseMirrorImage = 'm.daocloud.io/docker.io/library/mariadb:11.4',
[int]$KeepImages = 2,
[ValidatePattern('^\d+(KB|MB|GB|TB)$')]
[string]$BuildCacheMaxUsedSpace = '24GB',
[ValidateRange(24, 8760)]
[int]$BuildCacheMaxAgeHours = 720,
[switch]$BootstrapServer,
[switch]$ConfigureHttps,
[switch]$AllowNonMain,
@ -536,13 +540,17 @@ finally {
ssh -i $keyFullPath -o BatchMode=yes -o ConnectTimeout=5 $sshTarget "rm -f '$bootstrapRemote'" 2>$null | Out-Null
}
# Keep the compiled PHP base and Composer vendor layers between releases.
# The production build cache is normally about 20 GB; pruning it to 3 GB made
# every deployment rebuild PHP extensions and download all dependencies again.
$pruneHelp = docker buildx prune --help 2>$null | Out-String
docker buildx prune --builder $BuilderName --filter 'until=168h' --force 2>$null | Out-Null
$buildCacheMaxAge = "${BuildCacheMaxAgeHours}h"
docker buildx prune --builder $BuilderName --filter "until=$buildCacheMaxAge" --force 2>$null | Out-Null
if ($pruneHelp -match '--max-used-space') {
docker buildx prune --builder $BuilderName --max-used-space 3GB --force 2>$null | Out-Null
docker buildx prune --builder $BuilderName --max-used-space $BuildCacheMaxUsedSpace --force 2>$null | Out-Null
}
elseif ($pruneHelp -match '--keep-storage') {
docker buildx prune --builder $BuilderName --keep-storage 3GB --force 2>$null | Out-Null
docker buildx prune --builder $BuilderName --keep-storage $BuildCacheMaxUsedSpace --force 2>$null | Out-Null
}
docker system df

View File

@ -0,0 +1,37 @@
<?php
namespace Tests\Unit\Deployment;
use Tests\TestCase;
class ProductionBuildCachePolicyTest extends TestCase
{
public function testProductionDockerfilePinsBaseImagesAndRetriesExternalDownloads(): void
{
$dockerfile = file_get_contents(base_path('deploy/Dockerfile'));
$this->assertStringContainsString(
'FROM php:8.3-apache-bookworm@sha256:fa8852a2e01747ffe8c8768bfd6bbc2f296f974aa0de90ee157a66664996d263 AS php-base',
$dockerfile,
);
$this->assertStringContainsString(
'FROM composer:2.8@sha256:5248900ab8b5f7f880c2d62180e40960cd87f60149ec9a1abfd62ac72a02577c AS composer-bin',
$dockerfile,
);
$this->assertStringContainsString('Acquire::Retries=3', $dockerfile);
$this->assertStringContainsString('COMPOSER_MAX_PARALLEL_HTTP=4', $dockerfile);
$this->assertStringContainsString('if [ "$attempt" -ge 3 ]', $dockerfile);
}
public function testWorkstationDeploymentRetainsReusableBuildLayers(): void
{
$script = file_get_contents(base_path('scripts/deploy-from-workstation.ps1'));
$this->assertStringContainsString("[string]\$BuildCacheMaxUsedSpace = '24GB'", $script);
$this->assertStringContainsString('[int]$BuildCacheMaxAgeHours = 720', $script);
$this->assertStringContainsString('--max-used-space $BuildCacheMaxUsedSpace', $script);
$this->assertStringContainsString('--keep-storage $BuildCacheMaxUsedSpace', $script);
$this->assertStringNotContainsString('--max-used-space 3GB', $script);
$this->assertStringNotContainsString('--keep-storage 3GB', $script);
}
}