1

I have a dockerfile in which i am using python:3.9.2-slim-buster as base image and i am doing the following stuff.

FROM lab.com:5000/python:3.9.2-slim-buster
ENV PYTHONPATH=base_platform_update
RUN apt-get update && apt-get install -y curl && apt-get clean
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
RUN chmod +x ./kubectl
RUN mv ./kubectl /usr/local/bin
WORKDIR /script
RUN pip install SomePackage
COPY base_platform_update ./base_platform_update
ENTRYPOINT ["python3", "base_platform_update/core/main.py"]

I want to convert this to use distroless image. I tried but its not working. I found these resources

I know this is not correct but this is what i came up with after following these resources

# first stage
FROM lab.com:5000/python:3.9.2-slim-buster AS build-env
WORKDIR /script
COPY base_platform_update ./base_platform_update
RUN apt-get update && apt-get install -y curl && apt-get clean
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
RUN mv ./kubectl /usr/local/bin

# second stage
FROM gcr.io/distroless/python3
WORKDIR /script
COPY --from=build-env /script/base_platform_update ./base_platform_update
COPY --from=build-env /usr/local/bin/kubectl /usr/local/bin/kubectl
COPY --from=build-env /bin/chmod /bin/chmod
COPY --from=build-env /usr/local/bin/pip /usr/local/bin/pip
RUN chmod +x  /usr/local/bin/kubectl
ENV PYTHONPATH=base_platform_update
RUN pip install SomePackage
ENTRYPOINT ["python3", "base_platform_update/core/main.py"]

it gives the following error:

/bin/sh: 1: pip: not found
The command '/bin/sh -c pip install SomePackage' returned a non-zero code: 127

I also thought of moving RUN pip install SomePackage to first stage but the couldn't figure out how to do that.

Any help would be appreciated. Thanks

EDIT: docker images output

gcr.io/distroless/python3                                latest              7f711ebcfe29   51 years ago     52.2MB
gcr.io/distroless/python3                                debug               7c587fbe3d02   51 years ago     53.3MB
ray an
  • 1,132
  • 3
  • 17
  • 42

1 Answers1

1

It could be that you need to add that dir to the PATH.

ENV PATH="/usr/local/bin:$PATH" 

consider though the final image size difference after adding all those dependencies, it might not be worth all the hassle.

the latest image tagged as python:3.8.5-alpine is 42.7MB while gcr.io/distroless/python3 as of writing this is 52.2MB, after adding the binaries, the script, and nonetheless the package you want to install you may surpass that figure at the end. If pull time is important and network bandwidth usage is expensive that might be a thought to have, otherwise for the current use case seems like too much.

Distroless images are meant only for runtime, as a result, you can't (by default) use the python package manager to install packages, see Google GitHub project readme

"Distroless" images contain only your application and its runtime dependencies. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution.

you could install the packages in a second new stage and copy the installed packages from it to the third but that's not bound to work cause of target OS the package was meant for, incompatibility between the second and third stage etc`.

Here's an exame Dockerfile for that:

# first stage
FROM python:3.8 AS builder
COPY requirements.txt .

# install dependencies to the local user directory (eg. /root/.local)
RUN pip install --user -r requirements.txt

# second unnamed stage
FROM python:3.8-slim
WORKDIR /code

# copy only the dependencies installation from the 1st stage image
COPY --from=builder /root/.local /root/.local
COPY ./src .

# update PATH environment variable
ENV PATH=/root/.local:$PATH

CMD [ "python", "./server.py" ]

Dockerfile credits

You could package your application to a binary using any number of python libs but that depends on how much you need it. You can do that with packages like pyinstaller though it mainly packages the project rather than turning it to a single binary, nuitka which is a rising option and very popular along with cx_Freeze.

Here's a relevant thread on the topic if you're interested.

There's also this article.

Noam Yizraeli
  • 4,446
  • 18
  • 35
  • hey, if possible, could you share some resources(for reference) for: 1) that shows installing packages in the second stage and then copying them to the final image. 2) and how to create a binary from my application? Thanks – ray an Sep 18 '21 at 18:42
  • Updated answer ☺️ – Noam Yizraeli Sep 18 '21 at 19:46
  • just one more thing which i noticed, u said the distroless size is 20.4. But for some reason, when i run docker images command, its showing around 50MB. (i have added the command output in the question) – ray an Sep 19 '21 at 19:49
  • yeah sorry about that it was virtual size from [here](https://console.cloud.google.com/gcr/images/distroless/GLOBAL/python3) I'll update the answer – Noam Yizraeli Sep 19 '21 at 20:20