7

I've been playing around with docker images recently. I saw this docker doc on using FROM scratch. I am trying to see how far I can take this just for fun. I program in python. The doc says to compile the example C program to a binary, copy it to the container and then run it. In the container, I can not run python <program_file>. I saw this stack exchange post about compiling a python file to a binary, which meets our test use case here. It mentions using pyinstaller. So I run it on a test hello.py file which justs prints Hello with pyinstaller hello.py and I get a bunch of messages about building the projects. Okay, good. I can run the binary in my local machine by running "dist/hello" (this is the binary program mentioned by the post. So I write my Dockerfile to copy this program over and run it. My Dockerfile is

FROM scratch

ADD dist/hello /
CMD ["./hello"]

I run docker build . -t "hello:1.0" and then docker run hello:1.0 and.... I get an error messgage:

standard_init_linux.go:211: exec user process caused "no such file or directory"

What gives? What did I go wrong? Is it possible to get pyinstaller to compile a binary python project (multiple files, instead of just this one), then use the scratch image to run it. Are there any caveats if this is possible?

6
  • 3
    Just so you are aware, I'm not sure if it matters, but in your linked question, it tells you it doesn't actually produce a binary. pyinstaller simply packages everything, it doesn't produce native code from Python code. Commented Jun 25, 2020 at 18:44
  • @juanpa.arrivillaga well that explains that issue. So is there a way to get that sweet sweet binary.... Commented Jun 25, 2020 at 18:56
  • I'm trying to do like this ,also get the same error "standard_init_linux.go:211: exec user process caused "no such file or directory".But the Blog I get about ,sayd:scratch image just could only by used by go project.I tried, go projects success,and python projects just could run by compiled file in the system level,such as compiled on python.36.debian,run on debian.This way is OK,but not good enough.Hope to help you. Commented Jul 17, 2020 at 9:03
  • @Dviad Frick not help me, because I just want to do with a binary,to make a smaller image(python application image build always 500-1000MB,the base Linux system image debian buster slim with python always 150MB?compare with go applcation ,too big?how big your image about python project always be? Commented Jul 18, 2020 at 2:21
  • @David Frick Use python.it is big package , very much.When I do pip install -r requirements.txt ,it be very large, what’s more, always need to do some apt install for python package install, large more . Commented Jul 18, 2020 at 2:36

3 Answers 3

9

So the answer is to use Google's distroless image. They have an example on their github that I have slightly edited as follows.:

# Build a virtualenv using the appropriate Debian release
# * Install python3-venv for the built-in Python3 venv module (not installed by default)
# * Install gcc libpython3-dev to compile C Python modules
# * Update pip to support bdist_wheel
FROM debian:buster-slim AS build
RUN apt-get update && \
    apt-get install --no-install-suggests --no-install-recommends --yes python3-venv gcc libpython3-dev && \
    python3 -m venv /venv && \
    /venv/bin/pip install --upgrade pip

# Build the virtualenv as a separate step: Only re-execute this step when requirements.txt changes
FROM build AS build-venv
COPY requirements.txt /requirements.txt
RUN /venv/bin/pip install --disable-pip-version-check -r /requirements.txt

# Copy the virtualenv into a distroless image
FROM gcr.io/distroless/python3-debian10
COPY --from=build-venv /venv /venv
COPY . /app
WORKDIR /app
ENTRYPOINT ["/venv/bin/python3", "hello.py"]

Just posting this in case someone is wondering. Definitely a cool thing.

Link to google distroless image

The video that helped me a lot

Sign up to request clarification or add additional context in comments.

2 Comments

Any reason to use this over alpine?
@JamesSchinner Smaller attack surface.
1

It's possible to get pyinstaller to compile a binary python project (just one file), then use the base alpine image to run it.
The binary package itself contains the python so we don't need to install Python.
Here is the sample:
Dockerfile

FROM six8/pyinstaller-alpine as builder
RUN mkdir /build
COPY ./hello.py /build/
WORKDIR /build
RUN pyinstaller --noconfirm --onefile --clean hello.py

FROM alpine as release
COPY --from=builder /build/dist/hello /usr/bin/hello
ENTRYPOINT ["hello"]

hello.py

print("Hello, World!")

I am using multi stage building that use six8/pyinstaller-alpine to build the binary and then copy the binary to the base alpine image

build the image

docker build --no-cache -t "hello:latest" .

run image

docker run hello

Here is the result

$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
hello        latest    5bde0c9e1df7   23 seconds ago   9.79MB
alpine       latest    c059bfaa849c   3 months ago     5.59MB

As you can see the base alpine image is 5.59MB, and the hello image is 9.79MB, which means the hello binary's size is 4.2MB

If I change to scratch image, I get the error

docker run hello
standard_init_linux.go:228: exec user process caused: no such file or directory

That means the binary has issue when running in scratch because it looks for something of the OS that is missing

Comments

0

You can compile Python code using the compileall module. The output gets saved in the __pycache__ folder. If you copy the content of this folder into your docker image and add the entry point, you do not need to package the code along.

Refer: https://docs.python.org/3/tutorial/modules.html#compiled-python-files

Note: Use the same underlying OS and Python version, while compiling and target packaging.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.