docker-compose-wait: Support for docker images that don't have a shell

It’s possible that a docker image is based on SCRATCH, and contains nothing but the executable. In that case, the command part of this image should be somthing like:

command: ["/the_executable", "--foo", "bar"]

There won’t be && available as well without a shell. Could such a thin image have the favor of wait?

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 15 (9 by maintainers)

Commits related to this issue

Most upvoted comments

I work around this issue by copying the busybox sh into the container at a less-common location (to reduce potental exploits). this works in google’s distroless images. here’s an example multi-stage Dockerfile;

FROM busybox:1.31.1-uclibc as builder
RUN wget -O /wait https://github.com/ufoscout/docker-compose-wait/releases/download/2.7.3/wait &&\
    chmod +x /wait 

...

FROM gcr.io/distroless/java:11 as base
COPY --from=builder /bin/sh /sh
USER nonroot
COPY --from=builder --chown=nonroot:nonroot /wait /wait
...
ENTRYPOINT ["/sh", "-c", "/wait && java -jar application.jar"]

After some investigation, I think it could effectively work as you propose. Anyway, I don’t have enough knowledge to implement it in a way that I can guarantee it works. In fact, there are too low-level details that I miss and I would not be able to provide support where needed. So, I keep the task open with a “PR welcome” tag in case someone is willing to attempt a fix; but, honestly, considering that the BusyBox docker image size is only 750Kb, I don’t think it is worth investing much time in this feature.

FYI guys, I have a PR up here that fixes this issue. I ran into the issue recently using distroless and did some research and got a fix in place. One thing that I wanted to prevent was having multiple processes running in the container and wait basically having to act like an init system. I’ve prevented that by making a syscall out to exec so the wait process gets completely replaced by the configured command, whether that’s tini or another static binary. For configuration I added a single new env var, WAIT_COMMAND. The arguments to the command to invoke get properly parsed like they would if they were being processed by a shell using the shell_words crate so any command to run should be copy/pasteable from CMD to WAIT_COMMAND. Hope you have a chance to get 👀 on it @ufoscout and let me know your thoughts

I made it with alpine os image, and alpine itself had /bin/bash. Also the wait shell script I downloaded and added it to the current source file folder.

There as a system call called exec that loads a new process that replaces the current process. I think it’s this: https://docs.rs/exec/0.3.1/exec/

FYI, I do not know Rust.

I report here a proposal of @SamMousa:


It would be nice to support syntax that uses exec instead of a subshell.

The syntax for usage would be simple:

entrypoint: [
    "wait",
    "--",
    "myApp"
]

That way no shell is needed and signal handling becomes easier for the app since there’s no longer a shell in between.