Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

python3Minimal: Add top-level for a minimal Python 3 build #66762

Merged
merged 8 commits into from Aug 21, 2019

Conversation

adisbladis
Copy link
Member

@adisbladis adisbladis commented Aug 17, 2019

Motivation for this change

The regular python3 closure is pretty big, especially for non-interactive scripts.

Before:

$  du -sch (nix-store -qR (nix-build '<nixpkgs>' --no-out-link -A python3)) | sort -h
56K	/nix/store/mppjwxsqh2jfzsy06zqwpwra1dcn66f2-libffi-3.2.1
80K	/nix/store/g8al6vdf21mgfi5774qx6r6cil1j7zr8-bzip2-1.0.6.0.1
132K	/nix/store/w3wqang215is14xqajycbxmd52b44qkw-zlib-1.2.11
260K	/nix/store/lflh9l7j6v456xvk4sq8ax51pycz5l21-expat-2.2.7
344K	/nix/store/ji9kpgmbddkv2l2szzjfqinhja2322k0-xz-5.2.4
392K	/nix/store/f00sh4p25dcg3ywcr2hzj0wyb01hgyrn-readline-6.3p08
696K	/nix/store/1g2vh6nqpx630fz7dbgwds11b6q70wxk-gdbm-1.18.1
1.2M	/nix/store/ph2lq28vn677rs9ibxcffwgyd8rb0w04-sqlite-3.28.0
1.3M	/nix/store/xfghy8ixrhz3kyy6p724iv3cxji088dx-bash-4.4-p23
3.6M	/nix/store/rngzs8bxnajzpwnkk4896gy9d5s525ic-openssl-1.0.2s
7.8M	/nix/store/2fxvx0vh4h6j6z09ihd2ifcpqsy7lw68-ncurses-6.1-20190112
29M	/nix/store/iykxb0bmfjmi7s53kfg6pjbfpd8jmza6-glibc-2.27
57M	/nix/store/w7gsq8v86hni4ynaqgwwlnlny115ylng-python3-3.7.4
101M	total

After:

$ du -sch (nix-store -qR (nix-build '<nixpkgs>' --no-out-link -A python3Minimal)) | sort -h
56K	/nix/store/mppjwxsqh2jfzsy06zqwpwra1dcn66f2-libffi-3.2.1
80K	/nix/store/g8al6vdf21mgfi5774qx6r6cil1j7zr8-bzip2-1.0.6.0.1
132K	/nix/store/w3wqang215is14xqajycbxmd52b44qkw-zlib-1.2.11
260K	/nix/store/lflh9l7j6v456xvk4sq8ax51pycz5l21-expat-2.2.7
344K	/nix/store/ji9kpgmbddkv2l2szzjfqinhja2322k0-xz-5.2.4
1.3M	/nix/store/xfghy8ixrhz3kyy6p724iv3cxji088dx-bash-4.4-p23
29M	/nix/store/iykxb0bmfjmi7s53kfg6pjbfpd8jmza6-glibc-2.27
56M	/nix/store/f3gzz8iqb4g07qxbcrg4sw14xpxindb4-python3-3.7.4
87M	total
Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nix-review --run "nix-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.
Notify maintainers

cc @

@adisbladis adisbladis changed the title Python minimal python3Minimal: Add top-level for a minimal Python 3 build Aug 17, 2019
Copy link
Member

@FRidh FRidh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a specific case in Nixpkgs in mind where you want to use this? In the past "crippled" versions were removed because of the confusion they could cause. Having tkinter in a separate package was a compromise for having a decent closure size. See
#19255

Consider also the name for when people do use nix-env -i.

Note there is also the boot.nix, though that is specifically for Darwin for bootstrapping.

pkgs/development/interpreters/python/cpython/default.nix Outdated Show resolved Hide resolved
pkgs/top-level/all-packages.nix Outdated Show resolved Hide resolved
@adisbladis
Copy link
Member Author

Do you have a specific case in Nixpkgs in mind where you want to use this?

Particularly in https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py and in similar cases like #48378.

@FRidh
Copy link
Member

FRidh commented Aug 17, 2019

Is that really worth it? Many people will have another python3 on their system anyway.

@adisbladis
Copy link
Member Author

adisbladis commented Aug 17, 2019

Is that really worth it? Many people will have another python3 on their system anyway.

Maybe not yet? I do however think it's worth it as a step in the right direction for smaller closures.

I also see the potential in other areas such as dockerTools which I personally use a lot in CI environments that are not always having a local cache, so any savings in dependency fetching is great.

In the past "crippled" versions were removed because of the confusion they could cause.

We explicitly call it python3Minimal so it should be obvious that it's not what you'd want to use by default.

As a side note: python3Minimal clocks in at 90483408 bytes according to nix path-info, perl clocks in at 84557752.
This makes Python a contender where it previously wasn't because of closure size concerns.

@flokli
Copy link
Contributor

flokli commented Aug 17, 2019

I really like having a minimal python for these and other noninteractive, script-style tasks.

Having it explicitly named python3Minimal avoids people accidentially using the "wrong python version", as it was the case before #19309.

We probably want to document the existence of it once some scripts start using it, but I'd be fine with merging this as it is.

Copy link
Member

@FRidh FRidh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the pname has to be different, especially when python3Minimal is in the top-level.

@Mic92
Copy link
Member

Mic92 commented Aug 19, 2019

Another great use case for this would distributing minimal docker images as well. I would love to use nix to package docker images as it's much more composable than docker files.

Would you use a python without tls support in a docker container? I would quickly run into problems when communicating with external services.

@FRidh
Copy link
Member

FRidh commented Aug 19, 2019

I suggest disabling pkgs/withPackages/buildEnv.

@flokli
Copy link
Contributor

flokli commented Aug 19, 2019

Another great use case for this would distributing minimal docker images as well. I would love to use nix to package docker images as it's much more composable than docker files.

Would you use a python without tls support in a docker container? I would quickly run into problems when communicating with external services.

It really depends on your usecase, whether that version of python is doing the actual ssl communication, or if it's just a helper script.

@flokli
Copy link
Contributor

flokli commented Aug 19, 2019

I suggest disabling pkgs/withPackages/buildEnv.

I don't see much benefit / closure size reduction from that. Let's say, you want to use all the "minimizing aspects" of the main python, but there's some language bindings only pulling in a library already part of your closure, and you want to make use of that.

@danbst
Copy link
Contributor

danbst commented Aug 19, 2019

I agree with @Mic92 that removing OpenSSL is too restrictive.

@danbst
Copy link
Contributor

danbst commented Aug 19, 2019

Building with musl might be another way to shave off some bits, but it's not really used anywhere yet.

According to https://github.com/NixOS/rfcs/blob/0d1cc2015543039a6ffc73d821457dd9210f56d1/rfcs/0046-platform-support-tiers.md#tier-2-3, Musl-based package are on Tier 2 support, so they are infinitely-small close to be built by Hydra (Tier 2-ε is on Hydra).

cc @7c6f434c : can we suppose that Tier 2 support packages are allowed to be built by Hydra?

@7c6f434c
Copy link
Member

I don't have opinions on Hydra resource mangement, I am just trying to codify the current state (and prepare the language for evolving the description)!

What is the likely use case where Nixpkgs is used, Python3 is used but glibc is not used at all? Does Python3 path itself get smaller just because of switching to musl (not because of a finer tuning of configuration)?

@danbst
Copy link
Contributor

danbst commented Aug 19, 2019

@7c6f434c well yeah, you are right - we can't strip glibc that easy. But current implementation will cause package rebuilds in python3Minimal.withPackages (p: with p; [ cryptography ]) - we can rebuild Musl packages as well here.

What is the likely use case where Nixpkgs is used, Python3 is used but glibc is not used at all?

Some docker/container stuff. Personally, I don't have a glibc-free usecase.

@flokli does it makes sense to patch .withPackages in such way, that ${python3} dep is replaced with ${python3Minimal} one? In that case we can use binary cache for py packages (instead of rebuilding for python3Minimal)

@FRidh
Copy link
Member

FRidh commented Aug 19, 2019

@danbst extension modules will then point to python3 instead of minimal, so you don't gain anything, in fact, it takes more size

@danbst
Copy link
Contributor

danbst commented Aug 19, 2019

@FRidh I was talking about something like pkgs.replaceDependency or "Shipping Security Updates"-style rewrites. It is complicated, but doable.

@FRidh
Copy link
Member

FRidh commented Aug 19, 2019

I don't see much benefit / closure size reduction from that. Let's say, you want to use all the "minimizing aspects" of the main python, but there's some language bindings only pulling in a library already part of your closure, and you want to make use of that.

There is no size benefit. It is to prevent having to deal with tickets where users start building packages using that Python.

@jonringer
Copy link
Contributor

Would you use a python without tls support in a docker container? I would quickly run into problems when communicating with external services.

No, I wouldn't. But these changes would make it a lot easier to override and add back tls/openssl, than it would to do all the closure minification myself.

@7c6f434c
Copy link
Member

7c6f434c commented Aug 19, 2019 via email

@danbst
Copy link
Contributor

danbst commented Aug 19, 2019

@7c6f434c in that sense, python package isn't much different in glibc and musl variants. It's size is same, and image size for python+bash would be reduced only if both are musl-based.

OTOH, glibc is 30Mb, and musl is 6Mb. So we tradeoff +6Mb excess size for composite images and -30Mb size reduction for standalone python images.

But I agree now this idea is bad. I've tried to use pkgsMusl.python3.withPackages and it turns out, that something somewhere still brings regular pkgs.python3 into closure, which is another case for investigation, not related to this PR.

@7c6f434c
Copy link
Member

7c6f434c commented Aug 19, 2019 via email

@flokli
Copy link
Contributor

flokli commented Aug 20, 2019

So we do agree exposing the arguments in a composable way as in that PR is something useful to have in nixpkgs?

In that case, any feedback to the code itself?

@FRidh
Copy link
Member

FRidh commented Aug 21, 2019 via email

This builds Python without optional dependencies.

We can't just use python3.override, as things like
python3Minimal.withPackages would pass the wrong python derivation into
these modules.
@flokli
Copy link
Contributor

flokli commented Aug 21, 2019

alright - this PR doesn't use python3Minimal so far, so let's merge it.

@domenkozar
Copy link
Member

Not including ssl is too restrictive as a lot of applications need internet access nowadays, has there been any talk about adding it back?

@flokli
Copy link
Contributor

flokli commented Jul 21, 2023

Not including ssl is too restrictive as a lot of applications need internet access nowadays, has there been any talk about adding it back?

IIRC this is used to build glibc, which needs some python in its build system and other small usecases, where we want it to be as minimal as possible. Pulling in openssl into that wouldn't work.

If you want another python, you might want to use just plain python3, or compose your own, playing with these parameters:

image

@adisbladis
Copy link
Member Author

adisbladis commented Jul 21, 2023

Not including ssl is too restrictive as a lot of applications need internet access nowadays, has there been any talk about adding it back?

The original intent was to keep the derivation as small as possible, mainly for in sandboxing use cases.
How much does it increase the closure size?
If the impact isn't too big I think it's OK.

Scratch that, see #66762 (comment).

@domenkozar
Copy link
Member

It's additional 7MB and openssl will be in pretty much any closure anyway.

@domenkozar
Copy link
Member

We could disable openssl when building glibc but have python3Minimal with the ssl module. WDYT?

@domenkozar
Copy link
Member

Overriding openssl isn't trivial:

mkPoetryApplication {
  projectDir = ./.;
  python = pkgs.python3Minimal.override { openssl = pkgs.openssl; };
}

Results into

error: builder for '/nix/store/3jlwh4li4kndxs1kq99c6v1h4khyn531-python3.10-cryptography-40.0.2.drv' failed with exit code 1;
       last 10 log lines:
       > Finished executing pythonRemoveTestsDir
       > pythonCatchConflictsPhase
       > Found duplicated packages in closure for dependency 'cffi':
       >   cffi 1.15.1 (/nix/store/8r1y609lqxmqxb1f7cfy14wmqgzi5ia5-python3.10-cffi-1.15.1/lib/python3.10/site-packages)
       >   cffi 1.15.1 (/nix/store/58kx9mp3nh47zy5567si148prx35cdqr-python3.10-cffi-1.15.1/lib/python3.10/site-packages)
       > Found duplicated packages in closure for dependency 'pycparser':
       >   pycparser 2.21 (/nix/store/6d6ljx4qsgr41fvk2ajiglci5678mrc8-python3.10-pycparser-2.21/lib/python3.10/site-packages)
       >   pycparser 2.21 (/nix/store/60hgn1k5bnsnrpzbjfcax81hb3iap7hq-python3.10-pycparser-2.21/lib/python3.10/site-packages)
       >
       > Package duplicates found in closure, see above. Usually this happens if two packages depend on different version of the same dependency.
       For full logs, run 'nix log /nix/store/3jlwh4li4kndxs1kq99c6v1h4khyn531-python3.10-cryptography-40.0.2.drv'.
error: 1 dependencies of derivation '/nix/store/9qcq1md9s0k3lz5nyig1b8mvyrahfkh9-python3.10-secretstorage-3.3.3.drv' failed to build
error: 1 dependencies of derivation '/nix/store/0ll1pj4fzkr1brql8gs477p02br5cz7y-python3.10-keyring-23.13.1.drv' failed to build
error: 1 dependencies of derivation '/nix/store/lcl6478qwihklzq60irhpkqynn3xwry4-python3.10-poetry-1.3.2.drv' failed to build

@domenkozar
Copy link
Member

See also #169475

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

Successfully merging this pull request may close these issues.

None yet

9 participants