Search code examples
dockerdockerfilepodman

Dockerfile: Copy dependency install files, install them, remove install files to reduce image size


I'm working on building an image that will serve as a base image for a build and run container for software running in an offline environment.

I have a folder that has subdirectories <yum_dependencies> and <other_dependencies>

In the <yum_dependencies> sub directory I have .rpms for all the dependencies that were obtained from yum --downloadonly commands, allowing a completely offline install of all the packages.

In the <other_dependencies> folder I have a few install binaries and source .tar.gz that have to be decompressed/moved/built/installed.

Currently my Dockerfile looks something like this:

FROM <centos7 base image>
COPY <dependencies> /app/dependencies
RUN yum --disablerepo=* -y localinstall /app/dependencies/yum_dependencies/*.rpm

...
<several binary executions and installations of <other_dependencies>
...

WORKDIR /app
RUN rm -rf /app/dependencies

When I run the resulting image, the /app/dependencies folder is gone, but I've noticed that the image size is the same whether I have the last RUN rm command or not.

I know technically I could use --squash in my build command to reduce it down to one simple layer (and it does work in reducing the size), but that means that absolutely nothing is cached anymore. Is there anyway to preserve the caching layers without them bloating the final image?


Solution

  • You can take advantage of using RUN with mount and it will look like

    RUN --mount=type=bind,source=<dependencies>,target=/app/dependencies yum --disablerepo=* -y localinstall /app/dependencies/yum_dependencies/*.rpm
    

    If you have to call multiple command on files from /app/dependencies you have to add --mount=type=bind,source=<dependencies>,target=/app/dependencies to each RUN command

    Or you can merge all those command into one

    RUN --mount=type=bind,source=<dependencies>,target=/app/dependencies \
        yum --disablerepo=* -y localinstall /app/dependencies/yum_dependencies/dep1.rpm &&\
        yum --disablerepo=* -y localinstall /app/dependencies/yum_dependencies/dep2.rpm &&\
        yum --disablerepo=* -y localinstall /app/dependencies/yum_dependencies/dep3.rpm &&\
        /app/dependencies/final_installer_script.sh
    

    It will generate only one layer and files from /app/dependencies won't be a part of the final image, so you don't need to call rm