PSA: use COPY –chown instead of RUN chown after COPY in Dockerfile

I stumbled upon this when I was containerizing a proprietary web app we're using, in my Dockerfile I copied the app with COPY and chowned it in RUN, wasn't happy with image size, then I found COPY --chown parameter, with it the size of an image was smaller by the size of the directory I was COPYing, of course I know every RUN creates a layer containing all changes made inside of it, kinda like Copy On Write mechanism, but I didn't realized a simple change of file properties like owner makes a whole new copy


FROM alpine:latest AS downloader


RUN wget -q -O- http://www.example.com/app.zip | \
unzip -q -

FROM php:7.2-apache

COPY --chown=www-data:www-data --from=downloader /app /var/www/html/

# build time dependencies needed to build required PHP extensions
ENV EXT_BUILD_DEPS libfreetype6-dev libjpeg62-turbo-dev libpng-dev \
libxmlrpc-epi-dev libxmltok1-dev libxslt1-dev libssl-dev libz-dev libtidy-dev libc-client-dev \
librecode-dev libmariadb-dev libbz2-dev libpspell-dev libkrb5-dev libmemcached-dev libzip-dev \

# run time dependencies needed for PHP the required extensions to run
ENV EXT_RUNTIME_DEPS libpng16-16 libc-client2007e libmemcached11 libaspell15 librecode0 libxslt1.1 \
libzip4 libtidy5deb1 libjpeg62-turbo libmemcachedutil2 libfreetype6 libmagickwand-6.q16-6

RUN export PHP_EXT_DIR=$(php-config --extension-dir) \
&& curl -sSL https://downloads.ioncube.com/loader_downloads/ioncube_loaders_lin_x86-64.tar.gz \
|tar zxv -C$PHP_EXT_DIR/ ioncube/ioncube_loader_lin_7.2.so --strip-components=1 \
&& mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
&& echo "zend_extension = $PHP_EXT_DIR/ioncube_loader_lin_7.2.so" >> "$PHP_INI_DIR/php.ini" \
&& apt-get update && apt-get install --no-install-recommends -y $EXT_BUILD_DEPS $EXT_RUNTIME_DEPS \
&& docker-php-ext-configure gd --with-freetype-dir --with-jpeg-dir \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-configure imap --with-imap-ssl --with-kerberos \
&& docker-php-ext-install -j$(nproc) imap \
&& docker-php-ext-install -j$(nproc) intl \
&& docker-php-ext-install -j$(nproc) mysqli \
&& docker-php-ext-install -j$(nproc) opcache \
&& docker-php-ext-install -j$(nproc) pspell \
&& docker-php-ext-install -j$(nproc) recode \
&& docker-php-ext-install -j$(nproc) tidy \
&& docker-php-ext-install -j$(nproc) xmlrpc \
&& docker-php-ext-install -j$(nproc) xsl \
&& docker-php-ext-configure zip --with-libzip \
&& docker-php-ext-install -j$(nproc) zip \
&& yes "" | pecl install memcached \
&& docker-php-ext-enable memcached \
&& yes "" | pecl install imagick \
&& docker-php-ext-enable imagick \
&& apt-get purge -y -f --force-yes $EXT_BUILD_DEPS \
&& apt-get autoremove -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*


in my case app size is around 160MB, an image is 600MB, with `chown www-data:www-data /var/www/html` in RUN instead as COPY option the image size is around 760MB

Exit mobile version