Skip to content

Lock dependencies and reduce final docker image size (fixes markdownlint CI runs) #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

Ocramius
Copy link
Member

Q A
Documentation no
Bugfix yes
BC Break no
New Feature yes
RFC no
QA yes

Description

This change attempts to fix an underlying design issue with this image, since we were using:

  • composer global require
  • npm install -g

Both of the above lead to massive downstream problems, because dependencies keep shifting all the time. This change makes sure that all installed dependencies are fairly locked (package-lock.json and composer.lock), and cleaned up some multi-stage build issues in the process.

Specifically:

  • removed cleverness around setup.sh scripts, which made builds much slower, and produced multiple wasteful layers
  • separated installation of markdownlint to its own build stage, to prevent polluting final image with npm artifacts/caches
  • separated installation of cs2pr to its own build stage, to prevent polluting final image with composer artifacts/caches
  • reduced overall image size by ~400Mb, which should speed up CI builds downstream in a considerable way

It is endorsed to run DOCKER_BUILDKIT=1 docker build, when using this locally, or else multi-stage builds will never cache intermediate layers properly.

… and locked it to a specific version

Note: `markdownlint-cli2:0.4.0` broke our entire CI, hence why we're using an older version here.

This also means that the final CI container no longer contains `npm`, but just `nodejs`.
…er layer

This ensures:

 * `cs2pr` is installed (with all its dependencies) according to `composer.lock`
 * we can upgrade `composer.lock` in an automated way, in future
 * we don't pollute composer installation caches with artifacts coming from CI binaries (which would bloat final image)
…es: committing to local repo

While it is true that `problem-matcher.json` will change in future, we want to be able to run a
`docker build` without cache-slamming our layers for tiny remote file changes all the time, and
maintaining the `problem-matcher.json` ourselves is no big deal (as long as we have the original
file references).
…` step

Previously, each `/setup` script was run sequentially, in a separate `RUN` step of the `Dockerfile`.

While that removes some cache slamming problems when developing the image, it is much more efficient
to run the whole `apt install` operation in a single docker layer, therefore removing any potential
layer shifting that leads to many more layers, and much larger final docker image.

In practice, we only expect to change this section rarely, and relying on the built-in `apt` sources
is sufficient, for now.

For comparison, `ghcr.io/laminas/laminas-continuous-integration:1.15.0` is `1.4Gb` in size,
while the new image is `1.1Gb`, shaving off 300Mb of unused dependencies.
@Ocramius Ocramius added Bug Something isn't working Enhancement labels Jan 24, 2022
@Ocramius Ocramius added this to the 1.16.0 milestone Jan 24, 2022
@Ocramius Ocramius requested a review from boesing January 24, 2022 12:35
@Ocramius
Copy link
Member Author

TIL: swoole.so and openswoole.so are almost half the size of this docker image, and it's all in the final .so files :O

@Ocramius Ocramius changed the title Lock dependencies and reduce final docker image size Lock dependencies and reduce final docker image size (fixes markdownlint CI runs) Jan 24, 2022
@weierophinney
Copy link
Member

TIL: swoole.so and openswoole.so are almost half the size of this docker image, and it's all in the final .so files :O

I... have an idea about this.

I could likely do a pre-install script in the mezzio-swoole repo that unzips the extension .so files and installs the config files. That would reduce the overhead for the main CI container.

If that sounds reasonable to you, I'd argue we should do that as part of this commit or at least part of the same release. As soon as it's done, I can update the mezzio-swoole repo.

@Ocramius
Copy link
Member Author

Ocramius commented Jan 24, 2022

We should probably discuss doing that (swoole custom installation) in #72 - for now, this patch should already provide mitigation for current woes

@Xerkus
Copy link
Member

Xerkus commented Jan 24, 2022

It is endorsed to run DOCKER_BUILDKIT=1 docker build, when using this locally, or else multi-stage builds will never cache intermediate layers properly.

Unless docker version is ancient, there is a docker buildx command to use moby buildkit builder. docker buildx install will make docker build command also use buildkit

@Ocramius Ocramius self-assigned this Jan 24, 2022
@Ocramius Ocramius merged commit 3ba21d8 into laminas:1.16.x Jan 24, 2022
@Ocramius Ocramius deleted the feature/lock-dependencies-and-reduce-final-image-layer-size branch January 24, 2022 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working Enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants