8

I am new to Docker. I want to build a docker image by building a c++ library using make command. The way I am doing it in Dockerfile is that

  • copy the source code from host
  • install required packages
  • run make
  • copy the libraries (.so) into different folder inside the image
  • delete the source code

The Dockerfile code is written below.

The problem I am facing is that even after deleting the source code the final image size is big.

Since each line of Dockerfile creates a different layer, there is a way to download the source code using curl or wget and later delete the source code in the same layer. But I don't like the solution.

FROM alpine

RUN apk update && apk add <required_packages>

COPY source_code /tmp/source_code

RUN make -C /tmp/source_code && \
        mkdir /libraries/
        cp /tmp/lib/* /libraries/
        rm -rf /tmp/*

I just want to minimize the final image size. Is it the right way I am doing this or is there any better way? Please help.

shubham pagui
  • 145
  • 1
  • 6

2 Answers2

12

You can do a multi-stage build and copy the artifacts on a new image from the previous one. Also install any required runtime dependencies (if any).

FROM alpine AS builder

RUN apk add --no-cache <build_dependencies>

COPY source_code /tmp/source_code

RUN make -C /tmp/source_code && \
        mkdir /libraries/
        cp /tmp/lib/* /libraries/
        rm -rf /tmp/*

FROM alpine

RUN apk add --no-cache <runtime_dependencies>

COPY --from=builder /libraries/ /libraries/
Tanja
  • 41
  • 2
  • 3
  • 11
codestation
  • 2,938
  • 1
  • 22
  • 22
  • 1
    But with "make install", there might be lots of artifacts spread all over the places. – Zhaolin Feng Apr 19 '21 at 05:22
  • 1
    I found a solution. With `DESTDIR` and `stow` or `rsync`, the artifacts can be safely collected and installed. For example: `DESTDIR=/usr/local/stow/xxx ninja install`, and then `cd usr/local/stow && stow xxx`. I believe `make` and `cmake` also support DESTDIR. – Zhaolin Feng Apr 19 '21 at 06:00
7

Another way for compacting the resulting image, aside from using a multistage Docker build, is using the --squash build option. Example image build command line:

docker image build --squash -t your-image .

When deleting files in the Docker image, the files themselves aren't truly gone, but remain in previous Docker filesystem layers, so they still take up space.

Squashing collapses all filesystem layers of your image, so files that are deleted with rmwill be removed from the resulting single layer. This is an effective way for removing the source code from your image and compacting it.

Note that, squashing in an experimental Docker feature, and has to be enabled in Docker configuration.

For more details on docker build --squash, see:

valiano
  • 16,433
  • 7
  • 64
  • 79