canonical / chisel

GNU Affero General Public License v3.0
270 stars 42 forks source link

How do I get required ubuntu commands while building distroless ubuntu image using chisel #117

Closed Mahesha999 closed 3 months ago

Mahesha999 commented 8 months ago

I created docker image for my app using official ubuntu:20.04 docker image as base image. It consumed 300 MBs. I started exploring if I can reduce the image size further I came across chiesel by canonical. Following are some tutorial / links regarding chiesel. 1, 2, 3, 4. 5, 6 So, I started preparing distroless ubuntu 20.04 image for my app using chisel.

I tried following dockerfile:

ARG UBUNTU_RELEASE=20.04 CHISEL_VERSION=v0.9.0

FROM ubuntu:$UBUNTU_RELEASE AS chisel_ubuntu_builder

ARG TARGETARCH UBUNTU_RELEASE CHISEL_VERSION

RUN apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates git \
    && apt-get clean -y \
    && rm -rf /var/lib/apt/lists/*

ADD "https://github.com/canonical/chisel/releases/download/${CHISEL_VERSION}/chisel_${CHISEL_VERSION}_linux_${TARGETARCH}.tar.gz" chisel.tar.gz
RUN tar -xvf chisel.tar.gz -C /usr/bin/

RUN mkdir /rootfs

RUN chisel cut --release "${UBUNTU_RELEASE}" --root /rootfs base-files_base

FROM scratch
COPY --from=chisel_ubuntu_builder /rootfs /

I was able to build above image. But it contained empty file system. I realised that I need at least bash. But then I found that there is no chisel slice for bash for ubuntu 20.04 as can be cheched here. There is one for ubuntu 22.04 as can be checked here.

So I tried source bash from other ubuntu library as follows:

ARG UBUNTU_RELEASE=20.04 CHISEL_VERSION=v0.9.0

FROM ubuntu:$UBUNTU_RELEASE AS chisel_ubuntu_builder
# ... same as earlier dockerfile ...

FROM scratch
COPY --from=chisel_ubuntu_builder /rootfs /
# copy bash from bash_source
COPY --from=chisel_ubuntu_builder /rootfs /
COPY --from=chisel_ubuntu_builder /bin/bash /bin/bash
COPY --from=chisel_ubuntu_builder /bin/apt /bin/apt
COPY --from=chisel_ubuntu_builder /bin/apt-get /bin/apt-get
COPY --from=chisel_ubuntu_builder /usr/bin/bash /usr/bin/bash
COPY --from=chisel_ubuntu_builder /usr/bin/apt /usr/bin/apt
COPY --from=chisel_ubuntu_builder /usr/bin/apt-get /usr/bin/apt-get

I was able to build this image. But, I got following error while building my app image using above image as base image:

#5 [baseenv 2/4] RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then     add-apt-repository -y "deb  xenial-security main"; fi
#0 0.031 /bin/bash: if [ "$TARGETPLATFORM" = "linux/amd64" ]; then     add-apt-repository -y "deb  xenial-security main"; fi: No such file or directory
#5 ERROR: process "/bin/bash if [ \"$TARGETPLATFORM\" = \"linux/amd64\" ]; then     add-apt-repository -y \"deb  xenial-security main\"; fi" did not complete successfully: exit code: 127http://security.ubuntu.com/ubuntuhttp://security.ubuntu.com/ubuntuhttp://security.ubuntu.com/ubuntu

I guess, it now contains bash but now does not contain add-apt-repository. Do I need to copy this library too to my base image? I then quickly went through my app dockerfile based on ubuntu:20.04 image. It contained various other commands like apt, apt-get, add-apt-repository, chmod, cd. Do I have to copy them individually from other base image the way I am copying bash from ? Also, for my app, I am cloning various third party libraries and then running their files. Those files themselves might require other ubuntu commands.

Q1. Do I have to copy all such required commands from other base image?

This will be tedious since I will come to know what all things I required as and when image build fails. Then add COPY command to dockerfile and rebuild the image. So I want to know the recommeded procedure to build the distroless image for my app.

Q2. Also, is it fine to install libraries using apt-get install while building distroless image or it basically makes it not-so-distroless? If I should not be using apt-get to build distroless image, then how should I install all necessary dependency packages?

PS: The second image does not contain the bash also. I get following error while running it:

$ docker run -it myimage /bin/bash
exec /bin/bash: no such file or directory

Same for /usr/bin/bash:

$ docker run -it myimage /usr/bin/bash
exec /bin/bash: no such file or directory
rebornplusplus commented 8 months ago

Hi!

Indeed the bash slices are missing for focal. I added a PR: https://github.com/canonical/chisel-releases/pull/103. Hopefully, it will get merged soon! After that, you should be able to install the bash (and coreutils if you need) slices.

Regarding your questions, I can tell you that the chisel-releases repository is far from complete. Ideally, you would figure out what packages you may need to build your chiselled application container since there is an emphasis on size. Then, see if the relevant slices are in the repo; if not, PRs are more than welcome! Please note that, you may not need to wait for the PRs to get merged, you can chisel the slice using your changes in your chisel-releases fork. (chisel cut--release option is useful for this.) But it's always best to get the PR merged through reviews.

tuapuikia commented 3 months ago

Bash can be included using this slice

chisel cut --release ubuntu-${UBUNTU_RELEASE} --root /rootfs coreutils_bins coreutils_libs bash_bins

cjdcordeiro commented 3 months ago

Thanks for the comment @tuapuikia .

@Mahesha999 I hope this is no longer an issue for you. But please feel free to re-open if needed.