Skip to content
This repository has been archived by the owner on Nov 2, 2022. It is now read-only.

make pyenv available in Docker #96

Closed
wyardley opened this issue Jan 5, 2021 · 50 comments
Closed

make pyenv available in Docker #96

wyardley opened this issue Jan 5, 2021 · 50 comments

Comments

@wyardley
Copy link

wyardley commented Jan 5, 2021

What would you like Renovate to be able to do?
Currently, Renovate can seemingly only operate on the version of Python that it has installed globally (currently 3.9 in the 1.2.0 image). While we like to keep Renovate up to date, we have certain use cases where we need to stick with a specific Python version for one reason or another.

Since pipenv (a supported provider) can use pyenv to get a Python version, I noticed this in the "artifact update" error:

File name: Pipfile.lock

Command failed: pipenv lock
Warning: Python 3.8 was not found on your system...
Neither 'pyenv' nor 'asdf' could be found to install Python.
You can specify specific versions of Python with:
$ pipenv --python path/to/python

Thus, I think that if pyenv were made available in the Docker image, it might be possible to have Renovate work for non-default Python versions. Happy to hear suggestions if you have an alternate way of solving this.

Did you already have any implementation ideas?

@rarkins
Copy link
Contributor

rarkins commented Jan 6, 2021

@viceice wdyt? Transfer this to the buildpack repo?

@viceice
Copy link
Member

viceice commented Jan 6, 2021

Sure, move it to buildpack, pyenv should be pretty small.

@viceice
Copy link
Member

viceice commented Jan 6, 2021

Ok, I've looked into pyenv. It's not clear to me if pyenv will autoinstall the required python version or do we need to install it before it is usable by pyenv?

@rarkins rarkins transferred this issue from renovatebot/renovate Jan 6, 2021
@rarkins
Copy link
Contributor

rarkins commented Jan 6, 2021

Questions:

  • Do we just need to pre-install pyenv or do we need to pre-install pyenv plus multiple versions?
  • Do we need to make any changes to our existing python installation approach? i.e. the one that installs the latest version

@viceice
Copy link
Member

viceice commented Jan 6, 2021

I'm running some tests now. pushing a branch in a few minutes

@viceice
Copy link
Member

viceice commented Jan 6, 2021

looks like even when pyenv is available, we need to preinstall python versions whith pyenv

image

@viceice viceice mentioned this issue Jan 6, 2021
@rarkins
Copy link
Contributor

rarkins commented Jan 6, 2021

@wyardley can you comment on the preinstallation requirement? I don't think it's feasible for us to bloat the full image any further by preinstalling all possible python releases people would want, so we need a way around that if one exists.

@viceice maybe we need to add a "precommand" even if binarySource=global? (assuming we can detect which version of python that pipenv will want)

@viceice
Copy link
Member

viceice commented Jan 6, 2021

Yes, preinstall command ca work. But we need to do a user install if we aren't root.

Our python installer already skips install, if the specific version is already exists.

I'll try to create a dynamic python install tool, which can be run as non root.

Maybe we can adapt it for other tools later. So we can really remove the full image and let all tools install dynamic on global mode.

@rarkins
Copy link
Contributor

rarkins commented Jan 6, 2021

It would be nice if we could let the tools use pyenv if they already support that

@viceice
Copy link
Member

viceice commented Jan 6, 2021

Pyenv doesn't install any python version automatically. You need to explicit call pyenv install

@rarkins
Copy link
Contributor

rarkins commented Jan 6, 2021

Looks like pipenv would try through? Neither 'pyenv' nor 'asdf' could be found to install Python.

@viceice
Copy link
Member

viceice commented Jan 6, 2021

Not sure. We can try it, but my knowledge is very basic for python universe. I need some help to create a real test case, see linked pr.

The pr fails with missing python. No message about pyenv. 🤔

@rarkins
Copy link
Contributor

rarkins commented Jan 6, 2021

I think the research/testing burden can fall on @wyardley for now :)

@wyardley
Copy link
Author

wyardley commented Jan 6, 2021

Yeah, I was thinking this as well last nightl -- that maybe it wouldn’t handle dynamically installing it. I don’t use pyenv locally. I agree that bloating the install image with every possible version of Python is not ideal. In our case, we do run it on premise so in theory, it wouldn’t be hard for us to build on top of the base renovate image and add additional Python versions ourselves (I guess we could add pyenv ourselves too, if needed).

I am less familiar with https://asdf-vm.com/, but I will play with it as well, to see if that is capable of actually installing versions of tools.

@viceice
Copy link
Member

viceice commented Jan 6, 2021

Had a short look at asdf. it can install multiple tools with multiple versions without root, Maybe it can be used to preinstall our tools and also to install tools dynamically.

It also uses plugins to add support for installing / handling tools. So we can easily add new tools, which are not yet supported.

@wyardley
Copy link
Author

wyardley commented Jan 6, 2021

Had a short look at asdf. it can install multiple tools with multiple versions without root, Maybe it can be used to preinstall our tools and also to install tools dynamically.

Was having the same thought. A lot of positives, though I guess potentially may be some security implications of using such a magical tool.

Side question: with the new approach, there's still no way for us to set a (single) Python version that's different from the one baked into the Renovate image without building our own container, right? Even if it's not called out as a breaking change, it would be nice if the version change were noted in the release notes and / or if there were some way to influence what that version was.

w/r/t the pyenv and bloating images thing - if the asdf approach doesn't work, maybe Renovate could support +- 1 to the current version without bloating image size too much (e.g., 3.8 / 3.10)?

@viceice
Copy link
Member

viceice commented Jan 7, 2021

This will bloat too, as other people suggesting to do this for node, java and other tools too. So that isn't an option.

So let me check my previous idea of allowing install python dynamically as non-root. So renovate can try to install missing tools at runtime when binarySource is global.

@wyardley
Copy link
Author

wyardley commented Feb 4, 2021

No hurry, but just curious if any of these ideas / approaches have panned out at all?

@rarkins
Copy link
Contributor

rarkins commented Feb 5, 2021

So have we exhausted the idea that pyenv can install at runtime rather than just switch version?

@wyardley
Copy link
Author

wyardley commented Feb 5, 2021

Sounds like asdf can.asdf has the added benefit of potentially supporting other use cases besides Python, tho I would say maybe it could be a bit too “magical” and / or that it might be good to double check how careful it is when downloading / installing things.

Edit: With pyenv, it looks like it would work if you first ran pyenv install n.n.n https://github.com/pyenv/pyenv#installation. However, it seems like it won’t magically grab the version requested by pipenv if it hasn’t been installed first.

https://pipenv.pypa.io/en/latest/advanced/#automatic-python-installation mentions that pipenv can prompt to install the missing version via pyenv. Let me test to see if it can do this without confirmation if a specific option is passed.

@viceice
Copy link
Member

viceice commented Feb 5, 2021

@wyardley I've added pyenv and a test to #97 . Looks like pipenv==2020.11.15 is able to use python 3.9 to update the lockfile

@wyardley
Copy link
Author

wyardley commented Feb 5, 2021

@viceice: nice! and thanks

Yean, was just about to post that it seems like it will auto-install after all, at least with pipenv sync or pipenv install on a clean environment, if a) pyenv is installed and b) if PIPENV_YES is set in the environment or when running in a non-interactive environment.

% which pyenv
/usr/local/bin/pyenv
% PIPENV_YES=true pipenv install
Warning: Python 3.9 was not found on your system...
Installing CPython 3.9.1 with /usr/local/bin/pyenv (this may take a few minutes)...
[...]
% PIPENV_YES=true pipenv sync --dev
Warning: Python 3.9 was not found on your system...
Installing CPython 3.9.1 with /usr/local/bin/pyenv (this may take a few minutes)...

@viceice
Copy link
Member

viceice commented Feb 5, 2021

with PIPENV_YES=true we need the full build chain too. and it will need a lot of time to compile python. 😕 I don't like to have this accidently in the app or any self-hosted renovate by default.

#12 3.728 Successfully installed pipenv-2020.11.15
#12 3.778 + cd test/b-pipenv
#12 3.778 + pipenv lock
#12 4.332 Warning: Python 3.6 was not found on your system...
#12 4.366 Installing CPython 3.6.12 with /usr/local/pyenv/bin/pyenv (this may take a few minutes)...
⠇ Installing python..✘ Failed...
#12 7.512 Something went wrong...
#12 7.512 Downloading Python-3.6.12.tar.xz...
#12 7.512 -> https://www.python.org/ftp/python/3.6.12/Python-3.6.12.tar.xz
#12 7.512 Installing Python-3.6.12...
#12 7.512
#12 7.512 BUILD FAILED (Ubuntu 20.04 using python-build 20180424)
#12 7.512
#12 7.512 Inspect or clean up the working tree at /tmp/python-build.20210205075243.95
#12 7.512 Results logged to /tmp/python-build.20210205075243.95.log
#12 7.512
#12 7.512 Last 10 log lines:
#12 7.512 checking for --with-universal-archs... no
#12 7.512 checking MACHDEP... linux
#12 7.512 checking for --without-gcc... no
#12 7.512 checking for --with-icc... no
#12 7.512 checking for gcc... no
#12 7.512 checking for cc... no
#12 7.512 checking for cl.exe... no
#12 7.512 configure: error: in `/tmp/python-build.20210205075243.95/Python-3.6.12':
#12 7.512 configure: error: no acceptable C compiler found in $PATH
#12 7.512 See `config.log' for more details
#12 7.512
#12 7.536 Warning: The Python you just installed is not available on your PATH, apparently.

@rarkins which pipenv version is used in 1.2.0 image ? Is it the pro image?

@rarkins
Copy link
Contributor

rarkins commented Feb 5, 2021

Currently WhiteSource Renovate On-Premises (can I say "WSROP"?) is built off the renovate/renovate image. I plan to give it its own buildpack one day so that it can be more easily customized. I can release a new version soon anyway, for improved npm 7 detection.

@viceice
Copy link
Member

viceice commented Feb 5, 2021

we should wait until the latest python and dotnet issues are fixed in buildpack

@viceice
Copy link
Member

viceice commented Feb 5, 2021

docker run --rm -it whitesource/renovate:1.2.0 bash
ubuntu@d1b0aa913826:/usr/src/app$ cd /tmp/
ubuntu@d1b0aa913826:/tmp$ curl -sSLO https://raw.githubusercontent.com/renovatebot/docker-buildpack/feat/pyenv/test/python/test/b-pipenv/Pipfile
ubuntu@d1b0aa913826:/tmp$ pipenv lock
Warning: Python 3.6 was not found on your system...
Neither 'pyenv' nor 'asdf' could be found to install Python.
You can specify specific versions of Python with:
$ pipenv --python path/to/python
ubuntu@d1b0aa913826:/tmp$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
Cloning into '/home/ubuntu/.pyenv'...
remote: Enumerating objects: 74, done.
remote: Counting objects: 100% (74/74), done.
remote: Compressing objects: 100% (65/65), done.
remote: Total 18684 (delta 32), reused 14 (delta 4), pack-reused 18610
Receiving objects: 100% (18684/18684), 3.78 MiB | 5.53 MiB/s, done.
Resolving deltas: 100% (12670/12670), done.
ubuntu@d1b0aa913826:/tmp$ export export PYENV_ROOT="$HOME/.pyenv"
ubuntu@d1b0aa913826:/tmp$ export PATH="$PYENV_ROOT/bin:$PATH"
ubuntu@d1b0aa913826:/tmp$ pipenv lock
Warning: Python 3.6 was not found on your system...
Would you like us to install CPython 3.6.12 with Pyenv? [Y/n]: n

You can specify specific versions of Python with:
$ pipenv --python path/to/python
ubuntu@d1b0aa913826:/tmp$ ./node_modules/.bin/renovate --version^C
ubuntu@d1b0aa913826:/tmp$ echo "" | pipenv lock
Warning: Python 3.6 was not found on your system...
Would you like us to install CPython 3.6.12 with Pyenv? [Y/n]: Installing CPython 3.6.12 with /home/ubuntu/.pyenv/bin/pyenv (this may take a few minutes)...
✘ Failed...
Something went wrong...
Downloading Python-3.6.12.tar.xz...
-> https://www.python.org/ftp/python/3.6.12/Python-3.6.12.tar.xz
Installing Python-3.6.12...

BUILD FAILED (Ubuntu 18.04 using python-build 1.2.22-47-g4c302a02)

Inspect or clean up the working tree at /tmp/python-build.20210205090452.183
Results logged to /tmp/python-build.20210205090452.183.log

Last 10 log lines:
    sys.exit(ensurepip._main())
  File "/tmp/python-build.20210205090452.183/Python-3.6.12/Lib/ensurepip/__init__.py", line 204, in _main
    default_pip=args.default_pip,
  File "/tmp/python-build.20210205090452.183/Python-3.6.12/Lib/ensurepip/__init__.py", line 117, in _bootstrap
    return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
  File "/tmp/python-build.20210205090452.183/Python-3.6.12/Lib/ensurepip/__init__.py", line 27, in _run_pip
    import pip._internal
zipimport.ZipImportError: can't decompress data; zlib not available
Makefile:1102: recipe for target 'install' failed
make: *** [install] Error 1

Warning: The Python you just installed is not available on your PATH, apparently.

@viceice
Copy link
Member

viceice commented Feb 5, 2021

compiling on the fly should not hte way we want to go, as we already have all python versions precompiled, see https://github.com/renovatebot/python/tree/releases

i think we need to be able to install those tools as non-root to home dir and allow renovate to install them on the fly in global mode

@rarkins
Copy link
Contributor

rarkins commented Feb 5, 2021

Let's invent a new mode for now, e.g. "install" in addition to "global"

@rarkins
Copy link
Contributor

rarkins commented Feb 5, 2021

It would only be valid within our buildpack-based images anyway, e.g. not when npm i -g renovate?

@viceice
Copy link
Member

viceice commented Feb 5, 2021

It would only be valid within our buildpack-based images anyway, e.g. not when npm i -g renovate?

yes, as it will need our buildpack tools, but anyone can add the tools to a custom image and use that as base.

@rarkins
Copy link
Contributor

rarkins commented Feb 5, 2021

OK, but let's still retain the meaning of global as only trying pre-installed tools, and failing if not.

@viceice
Copy link
Member

viceice commented Feb 5, 2021

ok, so new binarySource mode install 🙃 will not work for tools which depends on system packages

@viceice
Copy link
Member

viceice commented Feb 5, 2021

we can use process.env.BUILDPACK==="1" as check for our buildpack tools :)

@wyardley
Copy link
Author

wyardley commented Feb 5, 2021

compiling on the fly should not hte way we want to go, as we already have all python versions precompiled, see https://github.com/renovatebot/python/tree/releases

Hrm, maybe I misunderstood? I thought the goal was for Renovate not to ship with all of these?
If they're already there, maybe pyenv just needs to be installed and have the right shims / base path to these for this to work? And / or maybe pipenv just needs the right hint? For sure pipenv can be given an explicit path to Python, but not sure if it can be given a base path to look in... if it helps, here's the find_a_system_python() method:
https://github.com/pypa/pipenv/blob/47d8b96e10e462169cb9d3e719318565514408ad/pipenv/core.py#L334-L355

It would be a bit more work, but renovate could (theoretically) parse the expected version in the Pipfile and then call pipenv with --python=/path/to/latest/3.8 as an argument?

@viceice
Copy link
Member

viceice commented Feb 5, 2021

We have precompiled in separate repo. So we can build a solution to download on the fly.

We already extract the required python constraint. If you use binarySource=docker they already be used.

@wyardley
Copy link
Author

wyardley commented Feb 5, 2021

Ok, I think I'm understanding a little better now.

Will binarySource=docker work when renovate itself is running in Docker in Kubernetes? (I have a feeling the container won't be able to create its own sidecars, but could be wrong).

@viceice
Copy link
Member

viceice commented Feb 5, 2021

It would need a sidecar dind container. Wich can be hopefully the new rootless one. You need to share the /tmp folder as Volume.

Checkout our helm chart repo, there is an issue for this to integrate it to the chart.

Maybe you can help to get that running.

@viceice
Copy link
Member

viceice commented Feb 5, 2021

We also planning a new install binarySource mode, which is like the docker slim one, but downloads the required tools on the fly and running them locally

@wyardley
Copy link
Author

So with 1.3.0, where 3.8 and 3.9 are both installed, I get a different error:

Command failed: pipenv lock
Creating a virtualenv for this project...
Pipfile: /tmp/renovate/github/myorg/foo/Pipfile
Using /usr/bin/python3.8 (3.8.5) to create virtualenv...

⠋ Creating virtual environment...�
⠙ Creating virtual environment...�
⠹ Creating virtual environment...�
⠸ Creating virtual environment...�
⠼ Creating virtual environment...�
⠴ Creating virtual environment...�
⠦ Creating virtual environment...RuntimeError: failed to query /usr/bin/python3.8 with code 1 err: 'Traceback (most recent call last):\n  File "/usr/local/python/3.9.2/lib/python3.9/site-packages/virtualenv/discovery/py_info.py", line 16, in <module>\n    from distutils import dist\nImportError: cannot import name \'dist\' from \'distutils\' (/usr/lib/python3.8/distutils/__init__.py)\n'

�✘ Failed creating virtual environment 

[pipenv.exceptions.VirtualenvCreationException]: 
Failed to create virtual environment.

https://stackoverflow.com/questions/64234182/error-when-creating-a-pipenv-virtual-environment-with-python-3-7

We can play around with that since we're already messing around with a custom docker image, but would it be possible to get distutils installed in there?

@rarkins
Copy link
Contributor

rarkins commented Mar 17, 2021

We can play around with that since we're already messing around with a custom docker image, but would it be possible to get distutils installed in there?

I'm fine with that but not experienced with it. Are you familiar enough to PR it to this repo?

@wyardley
Copy link
Author

I'm fine with that but not experienced with it. Are you familiar enough to PR it to this repo?

In a general sense, I understand what's needed, but not w/r/t the buildpack stuff.

Maybe just adding python3-distutils here would work?

build-essential \
libbz2-dev \
libffi-dev \
liblzma-dev \
libreadline-dev \
libsqlite3-dev \
libssl-dev \
zlib1g-dev \

@wyardley
Copy link
Author

FROM whitesource/renovate:1.3.0
  
USER root
RUN install-tool golang 1.15.10
RUN install-tool golang 1.16.2
RUN apt-get update && apt-get -y install python3-distutils && apt-get clean all
USER 1000

While I don't think this is the right fix in terms of this buildpack setup, the above does allow both Python 3.8 and 3.9 to work for me with latest pro image.

@viceice
Copy link
Member

viceice commented Mar 18, 2021

The problem is, that other tools bring in the system python, which is not expected.

eg this:

# go suggests: git svn bzr mercurial
apt_install bzr mercurial

So we do not explicit install any system python. so if we would install python3-distutils we will get a system python on every docker image. We don't want that.

I'm currently not sure about the best way to solve this issue. 🤔

@wyardley
Copy link
Author

wyardley commented Mar 18, 2021

Is the 3.8.5 that ends up on the standard image not from the system one?

I looked to see if there were a way to install distutils via another method and didn’t come up with one.

@viceice
Copy link
Member

viceice commented Mar 18, 2021

3.8.5 semms to be from ubuntu 20.04 system default, which is installed as a transitive dep, not explicit.

@wyardley
Copy link
Author

wyardley commented Mar 18, 2021

3.8.5 semms to be from ubuntu 20.04 system default, which is installed as a transitive dep, not explicit.

Right - and that's the issue - pipenv finds it, but it doesn't have a working distutils. In practical terms, this only seems to add two dependencies currently:

Setting up python3-lib2to3 (3.8.5-1~20.04.1) ...
Setting up python3-distutils (3.8.5-1~20.04.1) ..

of course, I can see the what you're saying, as if python3 at some point weren't builtin or a transitive dependency, explicitly installing python3-distutils. If bzr isn't needed, it looks like you could potentially remove the system python3

The following packages were automatically installed and are no longer required:
  libmpdec2 libpython3-stdlib libpython3.8-minimal libpython3.8-stdlib
  python3-minimal python3.8 python3.8-minimal
Use 'apt autoremove' to remove them.
The following packages will be REMOVED:
  brz bzr python3 python3-breezy python3-certifi python3-configobj
  python3-dulwich python3-fastimport python3-six python3-urllib3
0 upgraded, 0 newly installed, 10 to remove and 19 not upgraded.
After this operation, 12.6 MB disk space will be freed.
(Reading database ... 37630 files and directories currently installed.)
Removing bzr (2.7.0+bzr6622+brz) ...
Removing brz (3.0.2-4ubuntu2) ...
Removing python3-breezy (3.0.2-4ubuntu2) ...
Removing python3-dulwich (0.19.15-1build1) ...
Removing python3-urllib3 (1.25.8-2ubuntu0.1) ...
Removing python3-fastimport (0.9.8-5build1) ...
Removing python3-certifi (2019.11.28-1) ...
Removing python3-configobj (5.0.6-4) ...
Removing python3-six (1.14.0-2) ...
Removing python3 (3.8.2-0ubuntu2) ...

@viceice
Copy link
Member

viceice commented Mar 18, 2021

bzr is installed because of go 😕

@viceice
Copy link
Member

viceice commented Apr 8, 2021

@wyardley If you're still interested in this, please open a new issue at containerbase/buildpack repo, as this repo is now deprecated and will be archived soon

@viceice viceice closed this as completed Apr 8, 2021
@benlangfeld
Copy link

Is containerbase/base#101 the duplicate/continuation of this @viceice @rarkins ?

@viceice
Copy link
Member

viceice commented Jul 27, 2021

Yes, i think so

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants