openfaas / python-flask-template

HTTP and Flask-based OpenFaaS templates for Python 3
MIT License
85 stars 86 forks source link

extra chown command pads image size and build time #55

Closed rgschmitz1 closed 1 year ago

rgschmitz1 commented 2 years ago

My actions before raising this issue

Expected Behaviour

The --chown flag was introduced in v17.09.0-ce allows for copying files and changing ownership in one step, this would allow for copying files with non-root permissions without any additional container layer.

Current Behaviour

There's an additional RUN chown -R app:app ../ layer in several Dockerfiles that pads the overall image size and build time, this is especially noticeable as user specified requirements.txt grows.

Possible Solution

Add the --chown=app flag to any COPY command intended for non-root user (app) files, this will reduce overall build time and container image size.

or alternative...

Create an additional build stage (e.g. FROM python:* AS production) and copy over necessary build artifacts after testing finishes. This may require significant tweaking to the Dockerfiles to make this solution possible (e.g. using a virtualenv), however it may result in a much smaller container image?

Steps to Reproduce (for bugs)

  1. faas-cli template pull https://github.com/openfaas-incubator/python-flask-template
  2. faas-cli new --lang python3-http-debian hello-python
  3. Add several requirements to the hello-python/requirements.txt, example below
    boto3
    botocore
    click
    gensim
    jmespath
    joblib
    nltk
    numpy
    pandas
    python-dateutil
    pytz
    regex
    s3transfer
    scipy
    simplejson
    six
    smart-open
    tqdm
    urllib3
  4. time faas-cli build --no-cache -f hello-python.yml
  5. Modify any file COPY command intended for non-root user files to include --chown=app

    
    diff --git a/template/python3-http-debian/Dockerfile b/template/python3-http-debian/Dockerfile
    index 624fb03..6396fd3 100644
    --- a/template/python3-http-debian/Dockerfile
    +++ b/template/python3-http-debian/Dockerfile
    @@ -19,8 +19,8 @@ ENV PATH=$PATH:/home/app/.local/bin
    
    WORKDIR /home/app/

-COPY index.py . -COPY requirements.txt . +COPY --chown=app index.py . +COPY --chown=app requirements.txt . USER root RUN pip install -r requirements.txt USER app @@ -32,8 +32,7 @@ COPY function/requirements.txt . RUN pip install --user -r requirements.txt

USER root -COPY function/ . -RUN chown -R app:app ../ +COPY --chown=app function/ .

ARG TEST_COMMAND=tox ARG TEST_ENABLED=true

6. `time faas-cli build --no-cache -f hello-python.yml`
7. Compare image size and build time

## Context
<!--- How has this issue affected you? What are you trying to accomplish? -->
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
I'm a college student working on a capstone project involving deploying open-source cloud native applications in Kubernetes and doing a comparison against vendor specific solutions.

I'm using python-flask-templates as a basis for my own custom functions and would love to contribute in any way I can.

## Your Environment
* FaaS-CLI version ( Full output from: `faas-cli version` ):

/ \ __ | | _ / | | | | | ' \ / \ ' | | / ` |/ ` _ \ | || | |) | / | | | | (| | (| |) | _/| ./ _|| ||| _,|_,_|__/ |_|

CLI: commit: b1c09c0243f69990b6c81a17d7337f0fd23e7542 version: 0.14.2


* Docker version `docker version` (e.g. Docker 17.0.05 ):

Docker version 20.10.14, build a224086


* Are you using Docker Swarm or Kubernetes (FaaS-netes)?
`Kubernetes`

* Operating System and version (e.g. Linux, Windows, MacOS):

NAME="Ubuntu" VERSION="20.04.4 LTS (Focal Fossa)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.04.4 LTS" VERSION_ID="20.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=focal UBUNTU_CODENAME=focal



* Code example or link to GitHub repo or gist to reproduce problem:
`I can create a full gist if desired, but the requirements.txt provided in the "steps to reproduce" above matches my specific use case. To summarize my results, after implementing the first proposed solution produces a ~30 second decrease in build time and ~500mb decrease in image size.`

* Other diagnostic information / logs from [troubleshooting guide](https://docs.openfaas.com/deployment/troubleshooting)
LucasRoesler commented 2 years ago

I saw the same thing in an (unrelated) Node image recently, my solution for that image was to run the node install as the non-root user.

I think the --chown was relatively new when we first started these templates, but it has been 5 years, it is probably safe to use now? What do you think @alexellis ?

alexellis commented 2 years ago

Hi @rgschmitz1 thanks for the detailed feedback and suggestions.

We don't use COPY --chown due to potential support problems with other container builders like Kaniko.

If you can show the build still works with kaniko, then I think we could take a PR for this change.

Separately, would you be open to a short chat to hear more about what you're doing with OpenFaaS?

Alex

rgschmitz1 commented 2 years ago

Hi @alexellis ,

It was in the back of my mind that other container builders might not support the same flags, but I just did a quick search and it does look like chown support was added fairly recently to Kaniko (https://github.com/GoogleContainerTools/kaniko/pull/962). I haven't used Kaniko, but I'm willing to verify.

It might be worth while to test out a different the approach that @LucasRoesler mentioned if the --chown flag isn't standard for all the different build tools.

I saw the same thing in an (unrelated) Node image recently, my solution for that image was to run the node install as the non-root user.

Also, I'd be happy to send a message to fill you in on how I'm using OpenFaaS!

rgschmitz1 commented 2 years ago

Sorry for the delay in getting back to you all, I've been busy with taking care of my 7 month old and classes.

I just tested out Kaniko with COPY --chown=app and it appears to be working correctly. See the build log here, https://gist.github.com/rgschmitz1/5b42f8d796b715287589e7470d2f6c44

--- additional note --- I manually checked that the permissions in the /home/app directory were set correctly... There was a lot of files (not all 100% necessary), I can create an additional log if desired.

I also noticed that the tox test generated a completely new virtualenv with root permissions, I'm not sure if it is necessary or desired to keep these test files in the final image. I'll likely create a new issue ticket with some additional recommendations to trim down the container image size. šŸ‘šŸ»

alexellis commented 1 year ago

That sounds good.

@LucasRoesler do you want to go ahead and send a PR for this?

LucasRoesler commented 1 year ago

@alexellis patched here https://github.com/openfaas/python-flask-template/pull/58

LucasRoesler commented 1 year ago

@alexellis also related is https://github.com/openfaas/python-flask-template/pull/59 which resolves #57

rgschmitz1 commented 1 year ago

@alexellis and @LucasRoesler , thanks for the support!