Use multi-stage build in Dockerfile (#142)

This resolves the conversation at https://github.com/llvm/llvm-lnt/pull/117#discussion_r2470969562

Currently we install the build dependencies like g++ (`RUN apk add...`)  in a separate layer. We try and purge them in a later step but this doesn't achieve anything because docker caches everything on a layer by layer basis, i.e. the previous layer will still contain them and hang around.

This PR fixes it by using a multi-stage build which reduces the image size by ~90%:

```
$ docker image ls
REPOSITORY              TAG         IMAGE ID       CREATED          SIZE
lnt-new-dockerfile     latest      22cfaa9c28b0   14 minutes ago   88MB
lnt-old-dockerfile      <none>      76a17f3f65ed   5 seconds ago       797MB
```

This patch also only copies over the minimal source files required so as to make sure the dependencies layer is invalidated as infrequently as possible. E.g. here is an example of building the image after touching a regular python source file. We no longer need to rebuild or redownload the dependencies, that layer is cached:

```
$ docker build -f docker/lnt.dockerfile .
[+] Building 22.0s (15/15) FINISHED                                                                      docker:default
 => [internal] load build definition from lnt.dockerfile                                                           0.0s
 => => transferring dockerfile: 1.73kB                                                                             0.0s
 => [internal] load metadata for docker.io/library/python:3.10-alpine                                              0.4s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load build context                                                                                  0.5s
 => => transferring context: 562.77kB                                                                              0.4s
 => CACHED [builder 1/7] FROM docker.io/library/python:3.10-alpine@sha256:b4da816c29d5d3067a979e299ea3e4856476a2b  0.0s
 => [final 2/4] RUN apk update && apk add --no-cache libpq                                                         2.8s
 => CACHED [builder 2/7] RUN apk update && apk add --no-cache g++ postgresql-dev yaml-dev git libpq                0.0s
 => CACHED [builder 3/7] COPY pyproject.toml .                                                                     0.0s
 => CACHED [builder 4/7] COPY lnt/testing/profile lnt/testing/profile                                              0.0s
 => CACHED [builder 5/7] RUN pip install --user ".[server]"                                                        0.0s
 => [builder 6/7] COPY . .                                                                                         2.1s
 => [builder 7/7] RUN pip install --user .                                                                        17.0s
 => [final 3/4] COPY --from=builder /root/.local /root/.local                                                      0.9s 
 => [final 4/4] COPY docker/docker-entrypoint.sh docker/docker-entrypoint-log.sh docker/lnt-wait-db /usr/local/bi  0.0s 
 => exporting to image                                                                                             0.6s 
 => => exporting layers                                                                                            0.6s 
 => => writing image sha256:527e0140763072f26d84ef42b0bb9dda9857625acb3474ac5f159960c8d20bc4                       0.0s
```

We need to use a mock version for setuptools_scm, since it looks for a .git folder and we want to avoid copying that. That would cause the build dependency layers to be invalidated on every commit. 

1 file changed
tree: 033fbc5c8e2933ee42e02e81abc8ed54d0309b09
  1. .github/
  2. deployment/
  3. docker/
  4. docs/
  5. examples/
  6. lnt/
  7. schemas/
  8. tests/
  9. utils/
  10. .gitignore
  11. LICENSE.TXT
  12. MANIFEST.in
  13. pyproject.toml
  14. README.md
  15. requirements.client.txt
  16. requirements.server.txt
  17. requirements.txt
README.md

LNT: LLVM Nightly Test Infrastructure

About

LNT is an infrastructure for performance testing. The software itself consists of two main parts, a web application for accessing and visualizing performance data, and command line utilities to allow users to generate and submit test results to the server.

The package was originally written for use in testing LLVM compiler technologies, but is designed to be usable for the performance testing of any software.

Documentation

The official LNT documentation is available online at: https://llvm.org/docs/lnt

Source

The LNT source is available in the llvm-lnt repository: https://github.com/llvm/llvm-lnt

Contributing

To get started, please look at the Developer Guide in the official documentation.