首页 > 解决方案 > 如何在不使用缓存层但使用前一阶段的缓存的情况下构建多阶段 Docker 构建的每个部分

问题描述

我有一个 4 阶段的 Dockerfile,如下所示,但是当我不想使用缓存时,我无法找到优化构建的最佳方法(以确保使用最新的图像和包) …</p>

FROM composer:latest as api_platform_composer

FROM php:7.4-fpm-alpine AS api_platform_php
RUN apk upgrade --no-cache
RUN apk add --no-cache {some packages}
RUN set -eux; \
    apk add --no-cache --virtual .build-deps $PHPIZE_DEPS {some packages}; \
    docker-php-ext-configure {some packages}; \
    docker-php-ext-install -j$(nproc) {some packages}; \
    pecl install {some packages}; \
    pecl clear-cache; \
    docker-php-ext-enable {some packages}; \
    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 .phpexts-rundeps $runDeps; \
    apk del .build-deps
COPY --from=api_platform_composer /usr/bin/composer /usr/bin/composer
# … various other steps…
# etc.

FROM openresty/openresty:1.17.8.2-alpine AS api_platform_nginx
RUN apk upgrade --no-cache
RUN echo -e "env UPSTREAM;\n$(cat /usr/local/openresty/nginx/conf/nginx.conf)" > /usr/local/openresty/nginx/conf/nginx.conf
COPY src/docker/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
WORKDIR /srv/api/public
COPY --from=api_platform_php /srv/api/public ./

FROM alpine:3 as api_platform_ssh
# No dependencies from above

目前我使用以下命令单独 构建每个php, nginx&容器......</p>ssh

docker build --target api_platform_php \
  --cache-from registry.digitalocean.com/good-technologies/crm:latest-php,registry.digitalocean.com/good-technologies/crm:1.0.0-beta2-php \
  --build-arg BUILDKIT_INLINE_CACHE=1 \
  --build-arg BASE_COMPOSER_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/composer:latest \
  --build-arg BASE_PHP_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/php:7.4-fpm-alpine \
  --build-arg BASE_OPENRESTY_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/openresty/openresty:1.17.8.2-alpine \
  --build-arg BASE_SSH_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/alpine:3 \
  --build-arg BASE_MONGODB_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/mongo:4.4 \
  --build-arg BASE_VARNISH_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/varnish:6.4 \
  --tag registry.digitalocean.com/good-technologies/crm:1.0.0-beta2-php \
  --progress=plain \
  --no-cache \
  --pull \
  --secret id=php-secrets,src=.secrets/php/.secrets \
  .

docker build --target api_platform_nginx \
  --cache-from registry.digitalocean.com/good-technologies/crm:latest-nginx,registry.digitalocean.com/good-technologies/crm:1.0.0-beta2-php,registry.digitalocean.com/good-technologies/crm:1.0.0-beta2-nginx \
  --build-arg BUILDKIT_INLINE_CACHE=1 \
  --build-arg BASE_COMPOSER_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/composer:latest \
  --build-arg BASE_PHP_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/php:7.4-fpm-alpine \
  --build-arg BASE_OPENRESTY_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/openresty/openresty:1.17.8.2-alpine \
  --build-arg BASE_SSH_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/alpine:3 \
  --build-arg BASE_MONGODB_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/mongo:4.4 \
  --build-arg BASE_VARNISH_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/varnish:6.4 \
  --tag registry.digitalocean.com/good-technologies/crm:1.0.0-beta2-nginx \
  --progress=plain \
  --no-cache \
  --pull \
  --secret id=php-secrets,src=.secrets/php/.secrets \
  .

docker build --target api_platform_ssh \
  --cache-from registry.digitalocean.com/good-technologies/crm:latest-ssh,registry.digitalocean.com/good-technologies/crm:1.0.0-beta2-ssh \
  --build-arg BUILDKIT_INLINE_CACHE=1 \
  --build-arg BASE_COMPOSER_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/composer:latest \
  --build-arg BASE_PHP_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/php:7.4-fpm-alpine \
  --build-arg BASE_OPENRESTY_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/openresty/openresty:1.17.8.2-alpine \
  --build-arg BASE_SSH_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/alpine:3 \
  --build-arg BASE_MONGODB_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/mongo:4.4 \
  --build-arg BASE_VARNISH_IMAGE=gitlab.com/good-technologies/dependency_proxy/containers/varnish:6.4 \
  --tag registry.digitalocean.com/good-technologies/crm:1.0.0-beta2-ssh \
  --progress=plain \
  --no-cache \
  --pull \
  --secret id=php-secrets,src=.secrets/php/.secrets \
  .

这样做的问题是,因为我正在使用--no-cache标志,所以每个后续阶段都会重新构建它们所依赖的早期阶段。

有时我可能只想构建容器镜像的一个子集。

我有哪些优化选项?我可以想到以下……</p>

  1. 根据 Dockerfile 中的顺序,找出我们想要构建的最后一个镜像,并首先使用--no-cache标志构建最后一个镜像,然后在没有标志的情况下构建所有其余镜像--no-cache

  2. 在我需要确保不使用缓存的每个步骤中使用随机值构建 arg,就像这样......</p>

    FROM php:7.4-fpm-alpine AS api_platform_php
    ARG TIMESTAMP
    RUN X="${TIMESTAMP}" apk upgrade --no-cache
    # … etc.
    
    FROM openresty/openresty:1.17.8.2-alpine AS api_platform_nginx
    ARG TIMESTAMP
    RUN X="${TIMESTAMP}" apk upgrade --no-cache
    # … etc.
    

    …然后为每个构建命令传递相同的时间戳。

我在其中一个方面走在正确的轨道上,还是有其他更好的选择?

标签: dockerdocker-multi-stage-builddocker-layer

解决方案


推荐阅读