Recent runs on this repo: 15.3 min (pull request), 18.3 min (push). The
image is built twice, in full, and the second build is pure waste.
Phase
Time
docker build --target test (daemon)
~5 min
setup-buildx-action booting buildkit
75.8s
build-push-action --target runtime (buildx)
~7 min
The second build re-pulls the base, then runs apk add --no-cache ffmpeg
(~110s) and pip install (~101s) again, producing nothing the first build had
not already made. setup-buildx-action creates a builder in its own container
with its own cache, so it shares nothing with the daemon that just built the
test stage -- despite the comment above that step claiming the layers were
shared. That comment is why this looked fine.
buildx earns its overhead when producing several architectures. This workflow
produces linux/amd64 only, by an explicit decision recorded in it.
Change
Plain docker build against the same daemon that ran the tests, then docker push. --target runtime is a strict prefix of the test stage, so
every layer is a cache hit.
Measured locally on this repo: 1.3 seconds, against roughly eight minutes
in CI for buildkit boot plus a full rebuild including ffmpeg.
Identical to lyrathorpe/music-curator#7, whose workflow this one was copied
from -- the defect travelled with it.
What this does not fix
The runner is slow in absolute terms: pip install pytest takes 28 seconds,
layer export 31 seconds. There is also no cross-run cache, so the base image
and ffmpeg are fetched fresh every job. Fixing that needs a registry-backed
cache and is worth doing only if the remaining time still hurts.
## Measured
Recent runs on this repo: **15.3 min** (pull request), **18.3 min** (push). The
image is built twice, in full, and the second build is pure waste.
| Phase | Time |
| ------------------------------------------- | ------- |
| `docker build --target test` (daemon) | ~5 min |
| `setup-buildx-action` booting buildkit | 75.8s |
| `build-push-action --target runtime` (buildx) | ~7 min |
The second build re-pulls the base, then runs `apk add --no-cache ffmpeg`
(~110s) and `pip install` (~101s) again, producing nothing the first build had
not already made. `setup-buildx-action` creates a builder in its own container
with its own cache, so it shares nothing with the daemon that just built the
test stage -- despite the comment above that step claiming the layers were
shared. That comment is why this looked fine.
buildx earns its overhead when producing several architectures. This workflow
produces `linux/amd64` only, by an explicit decision recorded in it.
## Change
Plain `docker build` against the same daemon that ran the tests, then
`docker push`. `--target runtime` is a strict prefix of the test stage, so
every layer is a cache hit.
Measured locally on this repo: **1.3 seconds**, against roughly eight minutes
in CI for buildkit boot plus a full rebuild including ffmpeg.
Identical to lyrathorpe/music-curator#7, whose workflow this one was copied
from -- the defect travelled with it.
## What this does not fix
The runner is slow in absolute terms: `pip install pytest` takes 28 seconds,
layer export 31 seconds. There is also no cross-run cache, so the base image
and ffmpeg are fetched fresh every job. Fixing that needs a registry-backed
cache and is worth doing only if the remaining time still hurts.
Runs take fifteen to eighteen minutes, and the log shows why: the image is
built twice, in full.
The test stage is built by the runner's docker daemon. The runtime stage was
then built by docker/build-push-action, which runs under a buildx builder that
setup-buildx-action creates in its own container with its own cache. The two
share nothing, so the second build spent seventy-six seconds booting buildkit
and then installed ffmpeg and the package all over again -- around a hundred
and ten seconds for the apk and another hundred for pip, neither of which
produced anything the first build had not already made. The comment above the
test step claimed those layers were shared, which is what made this look
reasonable.
buildx earns that overhead when producing several architectures. This produces
linux/amd64 only, by an explicit decision recorded in the workflow, so it earns
nothing here. Use plain docker build against the same daemon that ran the
tests, and push with docker push. The runtime stage is a strict prefix of the
test stage, so every layer is a cache hit: measured at 1.3 seconds locally.
Identical to the change made in music-curator, whose workflow this one was
copied from.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Measured
Recent runs on this repo: 15.3 min (pull request), 18.3 min (push). The
image is built twice, in full, and the second build is pure waste.
docker build --target test(daemon)setup-buildx-actionbooting buildkitbuild-push-action --target runtime(buildx)The second build re-pulls the base, then runs
apk add --no-cache ffmpeg(~110s) and
pip install(~101s) again, producing nothing the first build hadnot already made.
setup-buildx-actioncreates a builder in its own containerwith its own cache, so it shares nothing with the daemon that just built the
test stage -- despite the comment above that step claiming the layers were
shared. That comment is why this looked fine.
buildx earns its overhead when producing several architectures. This workflow
produces
linux/amd64only, by an explicit decision recorded in it.Change
Plain
docker buildagainst the same daemon that ran the tests, thendocker push.--target runtimeis a strict prefix of the test stage, soevery layer is a cache hit.
Measured locally on this repo: 1.3 seconds, against roughly eight minutes
in CI for buildkit boot plus a full rebuild including ffmpeg.
Identical to lyrathorpe/music-curator#7, whose workflow this one was copied
from -- the defect travelled with it.
What this does not fix
The runner is slow in absolute terms:
pip install pytesttakes 28 seconds,layer export 31 seconds. There is also no cross-run cache, so the base image
and ffmpeg are fetched fresh every job. Fixing that needs a registry-backed
cache and is worth doing only if the remaining time still hurts.