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
The concept of distroless is a popular idea in the world of containers. The idea is to package applications in container images while at the same time removing as much of the operating system as possible (package managers, libraries, shells, etc).
In order to start a Bash shell in a Docker container, execute the “docker exec” command with the “-it” option and specify the container ID as well as the path to the bash shell. If the Bash is part of your PATH, you can simply type “bash” and have a Bash terminal in your container.
That's because you're trying to use dynamic-compiled bash
in in docker
without glibc
support.
bash-static
instead of classic bash
You may download it or run ./build.sh
bash
for alpine
: add this line to your Dockerfile
: RUN apk add --no-cache bash
Alpine
is a musl
-based distroMany 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.
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
bash-static
even in empty container from scratch
FROM scratch
ADD bash
ENTRYPOINT ['/bash']
You could probably add busybox in now.
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)
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 so many dependencies, so it will work for a range of different base images. It may not work for some very 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"]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With