Skip to content

Commit 05aa01e

Browse files
authored
Stop including pip in the final app image (#264)
After #254, pip is now installed into its own layer rather than into the system site-packages directory inside the Python layer. This means its now possible to exclude pip from the final app image, by making the pip layer be a build-only layer. Excluding pip from the final app image: - Prevents several classes of user error/confusion/bad app design patterns seen in support tickets (see #255 for more details). - Reduces app image supply chain surface area. - Reduces app image size by 13 MB and layer count by 1, meaning less to have to push to the remote registry. - Matches the approach used for Poetry, where we don't make Poetry available at run-time either. Users that need pip at run-time for a temporary debugging task can run `python -m ensurepip --default-pip` in the container at run-time to make it available again (this command doesn't even have to download anything - it uses the pip bundled with Python). Or if pip is an actual run-time dependency of the app, then the app can add `pip` to its `requirements.txt` (which much more clearly conveys the requirements of the app, and also allows the app to pick what pip version it needs at run-time). Should we find that pip's absence causes confusion in the future, we could always add a wrapper/shim `pip` script in the app image which does something like: ``` echo "pip isn't installed at run-time, if you need it temporarily run 'python -m ensurepip --default-pip' to install it" exit 1 ``` ...to improve discoverability. We'll also document pip (and Poetry) being available at build-time only in the docs that will be added by #11. Closes #255. GUS-W-16697386.
1 parent d8fa779 commit 05aa01e

File tree

3 files changed

+12
-16
lines changed

3 files changed

+12
-16
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- pip is now only available during the build, and is longer included in the final app image. ([#264](https://github.com/heroku/buildpacks-python/pull/264))
13+
1014
## [0.17.1] - 2024-09-07
1115

1216
### Changed

src/layers/pip.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub(crate) fn install_pip(
3131
layer_name!("pip"),
3232
CachedLayerDefinition {
3333
build: true,
34-
launch: true,
34+
launch: false,
3535
invalid_metadata_action: &|_| InvalidMetadataAction::DeleteLayer,
3636
restored_layer_action: &|cached_metadata: &PipLayerMetadata, _| {
3737
let cached_pip_version = cached_metadata.pip_version.clone();
@@ -49,15 +49,15 @@ pub(crate) fn install_pip(
4949
// reduce build log spam and prevent users from thinking they need to manually upgrade.
5050
// https://pip.pypa.io/en/stable/cli/pip/#cmdoption-disable-pip-version-check
5151
.chainable_insert(
52-
Scope::All,
52+
Scope::Build,
5353
ModificationBehavior::Override,
5454
"PIP_DISABLE_PIP_VERSION_CHECK",
5555
"1",
5656
)
5757
// Move the Python user base directory to this layer instead of under HOME:
5858
// https://docs.python.org/3/using/cmdline.html#envvar-PYTHONUSERBASE
5959
.chainable_insert(
60-
Scope::All,
60+
Scope::Build,
6161
ModificationBehavior::Override,
6262
"PYTHONUSERBASE",
6363
layer.path(),

tests/pip_test.rs

+5-13
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use libcnb_test::{assert_contains, assert_empty, BuildpackReference, PackResult,
55

66
#[test]
77
#[ignore = "integration test"]
8-
#[allow(clippy::too_many_lines)]
98
fn pip_basic_install_and_cache_reuse() {
109
let mut config = default_build_config("tests/fixtures/pip_basic");
1110
config.buildpacks(vec![
@@ -69,14 +68,13 @@ fn pip_basic_install_and_cache_reuse() {
6968

7069
// Check that at run-time:
7170
// - The correct env vars are set.
72-
// - pip is available (rather than just during the build).
73-
// - Both pip and Python can find the typing-extensions package.
71+
// - pip isn't available.
72+
// - Python can find the typing-extensions package.
7473
let command_output = context.run_shell_command(
7574
indoc! {"
7675
set -euo pipefail
7776
printenv | sort | grep -vE '^(_|HOME|HOSTNAME|OLDPWD|PWD|SHLVL)='
78-
echo
79-
pip list
77+
! command -v pip > /dev/null || { echo 'pip unexpectedly found!' && exit 1; }
8078
python -c 'import typing_extensions'
8179
"}
8280
);
@@ -85,18 +83,12 @@ fn pip_basic_install_and_cache_reuse() {
8583
command_output.stdout,
8684
formatdoc! {"
8785
LANG=C.UTF-8
88-
LD_LIBRARY_PATH=/layers/heroku_python/venv/lib:/layers/heroku_python/python/lib:/layers/heroku_python/pip/lib
89-
PATH=/layers/heroku_python/venv/bin:/layers/heroku_python/python/bin:/layers/heroku_python/pip/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
90-
PIP_DISABLE_PIP_VERSION_CHECK=1
86+
LD_LIBRARY_PATH=/layers/heroku_python/venv/lib:/layers/heroku_python/python/lib
87+
PATH=/layers/heroku_python/venv/bin:/layers/heroku_python/python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
9188
PIP_PYTHON=/layers/heroku_python/venv
9289
PYTHONHOME=/layers/heroku_python/python
9390
PYTHONUNBUFFERED=1
94-
PYTHONUSERBASE=/layers/heroku_python/pip
9591
VIRTUAL_ENV=/layers/heroku_python/venv
96-
97-
Package Version
98-
----------------- -------
99-
typing_extensions 4.12.2
10092
"}
10193
);
10294

0 commit comments

Comments
 (0)