Skip to content
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

Enable a variety of Dockerfile.*-driven custom builds #1

Merged
merged 21 commits into from
Jan 21, 2023
Merged

Conversation

benjamn
Copy link
Owner

@benjamn benjamn commented Jan 20, 2023

This branch records my progress towards making custom builds of Deno easily shareable via Docker.

Docker is not the only way to use this fork of Deno. You can, of course, build the project from source locally, and the deno-setup.sh and deno-build.sh scripts are good references for how to do that (at least on a UNIX system).

You can find the Docker-based commands for building these four tagged images in the docker-build-all.sh script:

  • benjamn/deno:unmodified-builder (heavyweight compilation, plain)
    • benjamn/deno:unmodified (derived from builder)
  • benjamn/deno:async-context-builder (heavyweight compilation, custom fork)
    • benjamn/deno:async-context (derived from builder)

If you have Docker installed and running, you can fire up the Deno REPL using these images by running either of the following commands:

docker run -it --rm benjamn/deno:unmodified repl
docker run -it --rm benjamn/deno:async-context repl

With both commands, the -it is necessary for an interactive persistent shell, and --rm helps clean up the images after each one exits. The logged in user is named deno, and does not have root or sudo access, but does have a /home/deno home directory. The default working directory is /deno, which can be overridden using the -v $(pwd):/deno flag, as in

docker run -it --rm -v $(pwd):/deno benjamn/deno:async-context test --allow-read some.tests.ts

where some.tests.ts is a file in whatever local directory docker run was executed in… on the host computer! This directory-mounting ability is remarkably powerful here, since it allows an Ubuntu-built deno binary to read/process/write files checked out on, say, Mac OS X, without me having to publish a bunch of binary builds for different platforms.

With the :async-context image, you'll find a prototype implementation of the AsyncContext proposal available globally, in case you want to play with that. I hope this system proves flexible enough to prototype other ECMAScript and TypeScript extensions as well as AsyncContext.

@benjamn benjamn self-assigned this Jan 20, 2023
Comment on lines 5 to 7
# Since Deno is a single standalone static binary, we can get away with copying
# only that one file (just 89MB) from the benjamn/deno-builder image.
COPY --from=benjamn/deno-unmodified-builder /home/deno/bin/deno /usr/local/bin/deno
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this pattern of multi-stage builds, this final Dockerfile can pick out the single static deno binary file from the builder image, and users of this image only need to pay for downloading that binary (about 89MB on top of the Ubuntu base image, which is even less). Thanks to @ryan-williams for this crucial tip!

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After an epic optimization ride over the last few days (25GB+ Docker image size whittled down to 162MB; see below), my final image ended up a little smaller than the official denoland/deno image, though I'm sure I'm not comparing apples to apples here, and the main reason this works so well is because, as the Deno installation docs make clear, deno is a single static binary:

Deno works on macOS, Linux, and Windows. Deno is a single binary executable. It has no external dependencies.

This means we need literally nothing else from the build besides the binary, which is amazing/convenient.

benjamn:deno-docker-image-optimization

@benjamn benjamn marked this pull request as ready for review January 20, 2023 20:44
benjamn added a commit that referenced this pull request Jan 20, 2023
Once PR #1 is merged, we can switch this back to `main` (or nothing
again, since `main` is default).
To build the Docker image, run

  docker build . -t benjamn/deno

To run the image, starting an interactive Deno shell, run

  docker run -it --rm benjamn/deno

The image is currently ~25GB, which is large by my standards, but I'll
work on getting that size down later.
Everything in each of these scripts runs in a single RUN command, using
only one Docker layer, so the scripts (especially the build.sh script)
have a meaningful chance to clean up after themselves.

These scripts can also serve as documentation for how to build the
project locally, if you prefer not to use Docker.
These images will be published as benjamn/deno:async-context-builder,
benjamn/deno:async-context, benjamn/deno:unmodified-builder, and
benjamn/deno:unmodified.
Once PR #1 is merged, we can switch this back to `main` (or nothing
again, since `main` is default).
@benjamn benjamn merged commit 5c4dd18 into main Jan 21, 2023
@benjamn benjamn deleted the docker-builds branch January 21, 2023 00:57
@benjamn benjamn restored the docker-builds branch January 21, 2023 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant