Add shell or bash to a docker image (Distroless based on Debian GNU/Linux)
Asked Answered
F

3

23

I want add shell or bash to my image to execute installation command.

I have copied the /bin/bash on my VM on to my image on Dockerfile:

COPY /bin/bash /bin/

But when I execute the docker command:

 docker run -it --entrypoint "/bin/bash" <my_image>

Then I get the following error :

/bin/bash: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory

Thanks for your help

Fisher answered 5/4, 2020 at 8:25 Comment(2)
Can you expand this question to include a minimal reproducible example, especially including the FROM line of the Dockerfile? (Is it "distroless", or "based on the Debian distribution"?) How would you ordinarily install software into this image? (Does it include some sort of package manager?)Muriate
Hi @DavidMaze, On my Dokerfile, I go from api-gate-way image based on distroless with nginx configurationFisher
G
41

You can do it by copying the statically compiled shell from official busybox image in a multi-stage build in your Dockerfile. Or just COPY --from it.

The static shell doesn't have too many dependencies, so it will work for a range of different base images. It may not work for some advanced cases, but otherwise it gets the job done.

The statically compiled shell is tagged with uclibc. Depending on your base image you may have success with other flavours of busybox as well.

Example:

FROM busybox:1.35.0-uclibc as busybox

FROM gcr.io/distroless/base-debian11

# Now copy the static shell into base image.
COPY --from=busybox /bin/sh /bin/sh

# You may also copy all necessary executables into distroless image.
COPY --from=busybox /bin/mkdir /bin/mkdir
COPY --from=busybox /bin/cat /bin/cat

ENTRYPOINT ["/bin/sh", "/entrypoint.sh"]

The single-line COPY --from directly from image would also work:

FROM gcr.io/distroless/base-debian11

COPY --from=busybox:1.35.0-uclibc /bin/sh /bin/sh

ENTRYPOINT ["/bin/sh", "/entrypoint.sh"]
Gymnasium answered 5/4, 2022 at 17:42 Comment(6)
Brilliant! And you'll also likely win a new Lurker badge for the first time answer being a hit after minimum of 9 years of using SO in stealth mode:)Kaiak
Yeah, Thanks :D The Lurker badge definitely should exist!Gymnasium
Does not seem to work for me: starting container process caused: exec: "/bin/sh": stat /bin/sh: no such file or directory: unknownForesee
@DanielGruszczyk What base and busybox image do you use?Gymnasium
Doesn't work for me either. Busybox: busybox:1.35.0-uclibc & base: gcr.io/distroless/static:nonrootWink
instead of busybox, use the debug image here, it worked for me Example COPY --from=busybox /bin/sh /bin/sh => COPY --from=gcr.io/distroless/base-debian11:bebug /bin/sh /bin/shHeliometer
K
12

Google's distroless images have versions tagged debug, which contain busybox executable (with sh bundled in).

If you have to, you can arguably use them even in production (which defeats the purpose of increased security - such as hiding environment variables and protecting scripted apps code).

Usage example of the distroless/base image with debug tag:

$ docker run -it --rm --name base -u 0 gcr.io/distroless/base:debug
/ # id
uid=0(root) gid=0(root)
Kaiak answered 3/4, 2022 at 8:57 Comment(2)
Actually nowadays base:debug does not contain bash...Pyoid
@WojciechKaczmarek I believe it has never contained bash per se (/usr/bin/bash), just the shells bundled with busybox, i.e. /busybox/sh -> busybox and /busybox/ash -> busyboxKaiak
E
8

That's because you're trying to use dynamic-compiled bash in in docker without glibc support.

TL;DR

  • ... either use bash-static instead of classic bash You may download it or run ./build.sh
  • or add bash for alpine: add this line to your Dockerfile: RUN apk add --no-cache bash

Alpine is a musl-based distro

Many docker images are built with alpine as base image: alpine (usually) is small & fast:

Here are the sizes of the images of popular operating systems.

The difference in image size source: A Breakdown of Operating Systems of Dockerhub

The difference in image size is striking: the range goes from BusyBox at 1MB all the way up to Fedora at 230MB. It’s interesting to see the clustering happening. Alpine and BusyBox are lightweight and right near 0MB, then the midweights like Debian and Ubuntu are around 100MB, and largest are heavyweights such as CentOS and Oracle Linux up by 200MB.

musl doesn't contain libtinfo

See more about difference between glibc and musl Functional differences from glibc

P.S. you can run bash-static even in empty container from scratch

FROM scratch
ADD bash
ENTRYPOINT ['/bash']

You could probably add busybox in now.

Ehman answered 5/4, 2020 at 9:10 Comment(4)
Thank you for your message @Yasen. I will try with this 'RUN apk add --no-cache bash'Fisher
I have added the command on my Dockerfile :'RUN apk add --no-cache bash' but I have this error: Step 4/5 : RUN apk add --no-cache bash ---> Running in 99bf0a92c050 OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"/bin/sh\": stat /bin/sh: no such file or directory": unknownFisher
How do you execute the "apk" command if you can't use a shell? The distroless docker images hasn't shell.Comptom
ADD bash throws ERROR: failed to solve: dockerfile parse error on line 73: ADD requires at least two arguments, but only one was provided. Destination could not be determinedLeatriceleave

© 2022 - 2024 — McMap. All rights reserved.