casey / just

🤖 Just a command runner
https://just.systems
Creative Commons Zero v1.0 Universal
21.1k stars 466 forks source link

Container image #1497

Open benatkin opened 1 year ago

benatkin commented 1 year ago

A multi-stage build could be used to install this, no?

FROM just as just

FROM python

COPY --from=just /bin/just /bin/just

# Copy everything in the current directory - use .containerignore / .dockerignore
COPY . .

just

Has the added benefit of being able to try out just.

It probably shouldn't be recommended as the base, but perhaps having some common distros like alpine, debian, and ubuntu would be nice for those trying it out or not wanting to pull down layers.

A con is the overhead of having other stuff in the image but it seems like it would be better than downloading it in a podman/docker command. Or maybe some are distributing container images that can only be used for copying like above.

My current suggestion is just to have a bare distroless container containing just so you can use the above commands to add the just static binary to any container.

casey commented 1 year ago

Would this be much easier than downloading a prebuilt binary?

benatkin commented 1 year ago

I think so – because downloading a prebuilt binary is something I might use just to do. But of course if I don't have just I can't use just to download it.

benatkin commented 1 year ago

I did some research and this is solved:

A con is the overhead of having other stuff in the image

...by https://github.com/GoogleContainerTools/distroless

I found it by checking gojq: https://hub.docker.com/r/itchyny/gojq https://github.com/itchyny/gojq/blob/main/Dockerfile https://github.com/itchyny/gojq

casey commented 1 year ago

I did some research and this is solved:

A con is the overhead of having other stuff in the image

...by https://github.com/GoogleContainerTools/distroless

But if there's no distro in the container, then wouldn't you not be able to call any commands in just recipes?

benatkin commented 1 year ago

Right, so "Has the added benefit of being able to try out just." goes away since it doesn't even have sh which just requires.

Maybe it would be nice to have both, but I think a distroless (non-runnable) just would be the most useful because it could be used to install just, so the version with a distro could be omitted.

polarathene commented 1 year ago

You could just use ADD with remote URL to the Github releases, then a RUN to extract .tar.gz content? It's a lot less work for maintainers, especially if the main motivation is to try just without downloading a local file to COPY, when you still have to write a Dockerfile anyway, is it really that much more work?

With BuildKit, you can also do this (Docker Engine v23 released recently should support this out of the box, make sure you include the syntax line): https://github.com/moby/moby/issues/2369#issuecomment-457219856

# syntax=docker/dockerfile:1
FROM python
ARG JUST_VERSION=1.13.0

# Temporarily replace `/bin` content from busybox:latest image (to run wget and tar):
RUN --mount=type=bind,from=busybox:latest,source=/bin/,target=/bin/ \
  wget -O - https://github.com/casey/just/releases/download/${JUST_VERSION}/just-${JUST_VERSION}-x86_64-unknown-linux-musl.tar.gz \
  | tar --directory /usr/local/bin --extract --gzip --file - just

# Copy everything in the current directory - use .containerignore / .dockerignore
COPY . .

just

I've adapted the linked advice to your earlier example:

The RUN --mount syntax was experimental back then, but is now documented officially.

The python image already has both tar and wget available in /usr/bin (not /bin), so you don't actually need RUN --mount in this case :+1: (linked example did this for a scratch image, you could probably do similar with distroless images)

FROM python
ARG JUST_VERSION=1.13.0

RUN \
  wget -O - https://github.com/casey/just/releases/download/${JUST_VERSION}/just-${JUST_VERSION}-x86_64-unknown-linux-musl.tar.gz \
  | tar --directory /usr/local/bin --extract --gzip --file - just

# Copy everything in the current directory - use .containerignore / .dockerignore
COPY . .

just

So I doubt there is much benefit publishing a container image just for experimenting, beyond a little convenience (avoiding the noisier wget + tar lines). Likewise if you wanted to avoid specifying the version that can be done too, but has minimal benefit.

benatkin commented 1 year ago

@polarathene The trouble is that the Dockerfile becomes about downloading just. Dockerfiles tend to be short, and a package that just happens to use just shouldn't have all that stuff. You have a line that goes off the screen. My example doesn't. There are no URLs in my file. Plus what if a container doesn't even have curl/wget installed? That's actually somewhat common.

benatkin commented 1 year ago

Updated the body of the issue. Just suggesting doing the same thing as gojq.

polarathene commented 1 year ago

The trouble is that the Dockerfile becomes about downloading just. Dockerfiles tend to be short, and a package that just happens to use just shouldn't have all that stuff.

You have a FROM + a COPY vs a ARG + RUN.

Yours:

FROM just as just

FROM python

COPY --from=just /bin/just /bin/just

# Copy everything in the current directory - use .containerignore / .dockerignore
COPY . .

just

vs solution I provided:

FROM python
ARG JUST_VERSION=1.13.0

RUN \
  wget -O - https://github.com/casey/just/releases/download/${JUST_VERSION}/just-${JUST_VERSION}-x86_64-unknown-linux-musl.tar.gz \
  | tar --directory /usr/local/bin --extract --gzip --file - just

# Copy everything in the current directory - use .containerignore / .dockerignore
COPY . .

just

You have a line that goes off the screen. My example doesn't.

Correct. What you're asking for is convenience, less verbose.

What I've suggested isn't complicated to implement or maintain though. It's a RUN with a URL to fetch from official releases + extracting the binary.

Pragmatically, you could view the Dockerfile with word-wrap enabled in an editor - or acknowledge that you'd rarely read such a line (or a small Dockerfile) that it'd be a legitimate maintenance concern.

If the length is a deal-breaker, here you go (1 line only, simpler / shorter than any other example here):

FROM python
RUN wget -O - shorturl.at/cCF39 | tar -C /usr/local/bin -zxf - just

# Copy everything in the current directory - use .containerignore / .dockerignore
COPY . .

just

There are no URLs in my file.

Not sure why that's relevant? You'd need the network to retrieve the remote image or file, it's just a different way to get that.

Plus what if a container doesn't even have curl/wget installed? That's actually somewhat common.

If you read my previous comment, it specifically addressed this with the first snippet using RUN --mount.


Here is your example Dockerfile, but with one extra line (RUN) - this time instead of a long URL with wget+ tar which you were opposed to, we just install the latest just.

FROM rust as builder
RUN cargo install just

FROM python
COPY --from=builder /usr/local/cargo/bin/just /usr/local/bin/just

# Copy everything in the current directory - use .containerignore / .dockerignore
COPY . .

just

Obviously this takes longer the first time until it's cached. If you just want to try it out quickly, you can use the earlier approach to get a pre-built binary, otherwise here is your simple / terse version that suits your preferences if you're using it repeatedly.


Just suggesting doing the same thing as gojq.

Your request to simplify that further, offloads the burden to maintainers instead:

It's up to maintainers here, but if they feel that is a burden on their time, and there isn't sufficient demand for it, you have a variety of viable solutions shared here.

After all, your original request was only interested in trying just in Docker (which presumably didn't seem easy?), so I thought I'd share how easy that can be without requiring a maintainer to go through the extra effort to service a niche request.

Beyond the convenience of getting the binary in a slightly more terse manner, I don't see the benefit of just being published as an image to a registry? It's not like gojq where it's practical as a standalone image?


I get why as a user that you're asking for just to be published as a Docker image for the convenience of distribution. I am just contributing a perspective as a maintainer (of other open-source projects), where your request seems to lack context to justify the value.

You could contribute a PR with the Dockerfile and update the Github Actions workflow to support the request better, but I think approval is more to do with what you're asking of others to take on beyond that.

polarathene commented 1 year ago

BTW, you already have a few options that can just use RUN to install a package for that distro, including the common and popular Alpine:

FROM python:alpine
RUN apk add just

# Copy everything in the current directory - use .containerignore / .dockerignore
COPY . .

just

So the original question "Would this be much easier than downloading a prebuilt binary?" is fairly valid.