はじめに
以下は、VSCode Dev Containers用のDocker filesです。Ubuntu 22.04をベースイメージにしています。
FROM ubuntu:22.04
# Install prerequisites
RUN set -x \
    && export DEBIAN_FRONTEND=noninteractive \
    && apt-get update \
    && apt-get install -y --no-install-recommends \
        gnupg2 \
        software-properties-common \
        language-pack-ja \
        tzdata \
        curl \
        lsb-release \
    && apt-get -y clean \
    && rm -rf /var/lib/apt/lists/*
# Set locale & timezone
RUN update-locale LANG=ja_JP.UTF-8 LANGUAGE=ja_JP:ja \
    && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
    && echo "Asia/Tokyo" > /etc/timezone
ENV LANG=ja_JP.UTF-8
ENV LC_ALL=ja_JP.UTF-8
ENV LC_CTYPE=ja_JP.UTF-8
# Install packages
RUN set -x \
    # 最新のPythonバージョンをインストールするために、deadsnakes PPAを追加
    && add-apt-repository ppa:deadsnakes/ppa \
    && apt-get update \
    && apt-get install -y --no-install-recommends \
        python3.12-dev \
    && apt-get -y clean \
    && rm -rf /var/lib/apt/lists/*
# Python / pip
RUN ln -s $(which python3.12) /usr/bin/python
RUN curl -sSL https://bootstrap.pypa.io/get-pip.py | python -
    
以下のコマンドは、ビルドしたイメージ上で実行しました。
root@43e0c835ea78:/# python --version
Python 3.12.4
root@43e0c835ea78:/# pip --version
pip 24.1.2 from /usr/local/lib/python3.12/dist-packages/pip (python 3.12)
何が起きたのか
最新のUbuntuバージョンを利用するために、ベースイメージをUbuntu 22.04からUbuntu 24.04に変更しました。しかし、docker buildx buildに失敗しました。
pipのインストールで失敗していました。
$ docker buildx build --file Dockerfile.noble .
[+] Building 13.9s (9/9) FINISHED                                                                                                                                                                 docker:default
 => [internal] load build definition from Dockerfile.noble                                                                                                                                                  0.0s
 => => transferring dockerfile: 1.14kB                                                                                                                                                                      0.0s
 => [internal] load metadata for docker.io/library/ubuntu:24.04                                                                                                                                             0.0s
 => [internal] load .dockerignore                                                                                                                                                                           0.0s
 => => transferring context: 2B                                                                                                                                                                             0.0s
 => [1/6] FROM docker.io/library/ubuntu:24.04                                                                                                                                                               0.0s
 => CACHED [2/6] RUN set -x     && export DEBIAN_FRONTEND=noninteractive     && apt-get update     && apt-get install -y --no-install-recommends         gnupg2         software-properties-common          0.0s
 => CACHED [3/6] RUN update-locale LANG=ja_JP.UTF-8 LANGUAGE=ja_JP:ja     && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime     && echo "Asia/Tokyo" > /etc/timezone                                  0.0s
 => CACHED [4/6] RUN set -x     && add-apt-repository ppa:deadsnakes/ppa     && apt-get update     && apt-get install -y --no-install-recommends         python3.12-dev     && apt-get -y clean     && rm   0.0s
 => CACHED [5/6] RUN ln -s $(which python3.12) /usr/bin/python                                                                                                                                              0.0s
 => ERROR [6/6] RUN curl -sSL https://bootstrap.pypa.io/get-pip.py | python -                                                                                                                              13.9s
------
 > [6/6] RUN curl -sSL https://bootstrap.pypa.io/get-pip.py | python -:
13.75 error: externally-managed-environment
13.75
13.75 × This environment is externally managed
13.75 ╰─> To install Python packages system-wide, try apt install
13.75     python3-xyz, where xyz is the package you are trying to
13.75     install.
13.75
13.75     If you wish to install a non-Debian-packaged Python package,
13.75     create a virtual environment using python3 -m venv path/to/venv.
13.75     Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
13.75     sure you have python3-full installed.
13.75
13.75     If you wish to install a non-Debian packaged Python application,
13.75     it may be easiest to use pipx install xyz, which will manage a
13.75     virtual environment for you. Make sure you have pipx installed.
13.75
13.75     See /usr/share/doc/python3.12/README.venv for more information.
13.75
13.75 note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
13.75 hint: See PEP 668 for the detailed specification.
------
Dockerfile.noble:38
--------------------
  36 |     # Python / pip
  37 |     RUN ln -s $(which python3.12) /usr/bin/python
  38 | >>> RUN curl -sSL https://bootstrap.pypa.io/get-pip.py | python -
  39 |
  40 |
--------------------
ERROR: failed to solve: process "/bin/sh -c curl -sSL https://bootstrap.pypa.io/get-pip.py | python -" did not complete successfully: exit code: 1
以下のコマンドは、エラーが起きたRUN curl -sSL https://bootstrap.pypa.io/get-pip.py | python -をコメントアウトして作成したイメージ上で実行しました。
root@c89918743e60:/# python --version
Python 3.12.3
pipのインストールに失敗した原因
Ubuntu 24.04のpythonパッケージでは、PEP668に対応しているためです。
PEP668については、以下のサイトが参考になりました。
提案されているのは、OS側のpython3のディレクトリにEXTERNALLY-MANAGEDファイルをおいたら、そこはpython用のモジュール管理コマンドの影響から保護してね!という内容です。
Ubunutu 24.04では、/usr/lib/python3.12にEXTERNALLY-MANAGEDというファイルが存在していることを確認しました。
root@c89918743e60:/# python -c 'import sysconfig; print(sysconfig.get_path("stdlib"))'
/usr/lib/python3.12
root@c89918743e60:/# ls /usr/lib/python3.12/EXTERNALLY-MANAGED -l
-rw-r--r-- 1 root root 645  4月 10 14:33 /usr/lib/python3.12/EXTERNALLY-MANAGED
root@c89918743e60:/# ls /usr/lib/python3.12/EXTERNALLY-MANAGED -l
-rw-r--r-- 1 root root 645  4月 10 14:33 /usr/lib/python3.12/EXTERNALLY-MANAGED
root@c89918743e60:/# cat /usr/lib/python3.12/EXTERNALLY-MANAGED
[externally-managed]
Error=To install Python packages system-wide, try apt install
 python3-xyz, where xyz is the package you are trying to
 install.
 If you wish to install a non-Debian-packaged Python package,
 create a virtual environment using python3 -m venv path/to/venv.
 Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
 sure you have python3-full installed.
 If you wish to install a non-Debian packaged Python application,
 it may be easiest to use pipx install xyz, which will manage a
 virtual environment for you. Make sure you have pipx installed.
 See /usr/share/doc/python3.12/README.venv for more information.
また、Ubunutu 22.04では、/usr/lib/python3.12にEXTERNALLY-MANAGEDというファイルは存在しないことを確認できました。
解決方法
メッセージにある通り、pipxパッケージをインストールして、pipでなくpipxを利用するようにしました。
FROM ubuntu:24.04
# Install prerequisites
RUN set -x \
    && export DEBIAN_FRONTEND=noninteractive \
    && apt-get update \
    && apt-get install -y --no-install-recommends \
        gnupg2 \
        software-properties-common \
        language-pack-ja \
        tzdata \
        curl \
        lsb-release \
    && apt-get -y clean \
    && rm -rf /var/lib/apt/lists/*
# Set locale & timezone
RUN update-locale LANG=ja_JP.UTF-8 LANGUAGE=ja_JP:ja \
    && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
    && echo "Asia/Tokyo" > /etc/timezone
ENV LANG=ja_JP.UTF-8
ENV LC_ALL=ja_JP.UTF-8
ENV LC_CTYPE=ja_JP.UTF-8
# Install packages
RUN set -x \
    # 最新のPythonバージョンをインストールするために、deadsnakes PPAを追加
    && add-apt-repository ppa:deadsnakes/ppa \
    && apt-get update \
    && apt-get install -y --no-install-recommends \
        python3.12-dev \
        pipx \
    && apt-get -y clean \
    && rm -rf /var/lib/apt/lists/*
# Python / pipx
RUN ln -s $(which python3.12) /usr/bin/python
RUN pipx ensurepath
    
参考サイト