Search code examples
dockerdockerfiledocker-multi-stage-build

Dockerfile: Copy files from parent image


I'm building a multistage docker image where we have a base image that will be extended to build the actual final image. However I can't seem to copy files that are coming from the parent image into the child.

Base image

FROM debian:10.9-slim AS base

# PHP Version
ONBUILD ARG PHP_VERSION
ONBUILD ENV PHP_VERSION=${PHP_VERSION:-7.4}

# More stuff.
...

# Copy PHP settings into the image
COPY ./php/pool.d/*.conf /build-php/pool.d/
COPY ./php/conf.d/*.ini /build-php/conf.d/

# Onbuild copy the settings to the correct PHP version
ONBUILD COPY /build-php/pool.d/*.conf /etc/php/${PHP_VERSION}/fpm/pool.d/
ONBUILD COPY /build-php/conf.d/*.ini /etc/php/${PHP_VERSION}/fpm/conf.d/
ONBUILD COPY /build-php/conf.d/*.ini /etc/php/${PHP_VERSION}/cli/conf.d/

Specific image

ARG PHP_VERSION=8.0

FROM abcdef.amazonaws.com/php-base:v1.14.0 AS base

When building the secondary image I get the following error

$ docker build -t php8.0:base .
...
 => ERROR [7/1] COPY /build-php/pool.d/*.conf /etc/php/8.0/fpm/pool.d/                                                                                                                                   0.0s
------
 > [7/1] COPY /build-php/pool.d/*.conf /etc/php/8.0/fpm/pool.d/:
------
lstat /var/lib/docker/tmp/buildkit-mount474178567/build-php/pool.d: no such file or directory

I checked the parent image and the files are copied fine into /build-php. Also when building the child image (with the onbuild copy disabled) the files are present at /build-php. I don't understand why the onbuild copy can't find the files.


Solution

  • COPY always copies files from the host system (more specifically from the Docker build context); if it's run ONBUILD then it forces the derived image's build context (source tree) to have a specific layout.

    In this setup, the files are already in the base image (in /build-php) and so you need to RUN cp /build-php/... /etc/php/... to move the files within the image.

    Using ONBUILD, in general, can make it hard to reason about what steps are happening when, and can lead to confusing side effects. Rather than having one base image, which eventually will install and configure some version of PHP, the setup might be easier if you have a fully-configured base image for each version of the interpreter you use.

    # For simplicity, use the Docker Hub base image
    # (There can be good reasons to build your own)
    ARG PHP_VERSION=7.4
    FROM php:${PHP_VERSION}
    
    ARG PHP_VERSION
    
    # Copy PHP settings into the image
    COPY ./php/pool.d/*.conf /etc/php/${PHP_VERSION}/fpm/pool.d/
    COPY ./php/conf.d/*.ini /etc/php/${PHP_VERSION}/fpm/conf.d/
    COPY ./php/conf.d/*.ini /etc/php/${PHP_VERSION}/cli/conf.d/
    
    docker build \
      --build-arg PHP_VERSION=8.0 \
      -t abcdef.amazonaws.com/php-80-base:v1.14.0 \
      .