Upgrade python3.8 to 3.10 in Ubuntu Docker image

Question:

I am using playwright base image

FROM mcr.microsoft.com/playwright

Unfortunately, this comes with python3.8. I could either use python3.10 image and install playright on it, but it came with other complexities, so i chose to upgrade python on playright image to 3.10.

So far, my Dockerfile looks like this

FROM mcr.microsoft.com/playwright

apt install -y software-properties-common && add-apt-repository -y ppa:deadsnakes/ppa && apt update && apt install -y python3.10

RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.8 2

This works fine, but the problem is "How can i make python3.10" default version after setting up the alternatives?

Thanks

Asked By: Em Ae

||

Answers:

This Dockerfile should do the trick I think, though I’m not using update-alternatives so maybe not what you’re looking for

FROM mcr.microsoft.com/playwright


RUN apt update && apt install software-properties-common -y && add-apt-repository ppa:deadsnakes/ppa
RUN apt install python3.10 -y
RUN rm /usr/bin/python3 && ln -s /usr/bin/python3.10 /usr/bin/python3

Basically we just delete the old symbolic link at /usr/bin/python3 (which pointed the /usr/bin/python3.8 binary) and create a new symbolic link at /usr/bin/python3 (which points to the /usr/bin/python3.10 binary that we just installed). Here’s the output

➜ docker build . --tag test
[+] Building 14.7s (8/8) FINISHED                                                                                      
 => [internal] load build definition from Dockerfile                                                              0.0s
 => => transferring dockerfile: 280B                                                                              0.0s
 => [internal] load .dockerignore                                                                                 0.0s
 => => transferring context: 2B                                                                                   0.0s
 => [internal] load metadata for mcr.microsoft.com/playwright:latest                                              0.2s
 => CACHED [1/4] FROM mcr.microsoft.com/playwright@sha256:adade3016b008d5a892fd228499eed34919b4d8128b9c04bd447eb  0.0s
 => [2/4] RUN apt update && apt install software-properties-common -y && add-apt-repository ppa:deadsnakes/ppa    9.5s
 => [3/4] RUN apt install python3.10 -y                                                                           4.6s
 => [4/4] RUN rm /usr/bin/python3 && ln -s /usr/bin/python3.10 /usr/bin/python3                                   0.2s 
 => exporting to image                                                                                            0.2s 
 => => exporting layers                                                                                           0.2s 
 => => writing image sha256:fba6bb8a4cbd26ec4be70fd9d9d7638bcd2139fed83fd6ca52ef52992d47d1dc                      0.0s 
 => => naming to docker.io/library/os                                                                             0.0s 
➜ docker run -it test      
root@0bbc072f22ce:/# which python3 
/usr/bin/python3
root@0bbc072f22ce:/# python3 --version 
Python 3.10.9
Answered By: Campbell

python3 is simply a symbolic link to /usr/bin/python3.8. You can create a new link using the following command:

RUN ln -sf /usr/bin/python3.10 /usr/bin/python3

The -f (force) option overwrites the existing symlink with the new one.

Answered By: Selcuk

There are two things to notice:

  1. Python executable
  2. Alternatives priority

Executable

Running in the base image:

# which python
# which python3
/usr/bin/python3
# ls -l /usr/bin/python*
lrwxrwxrwx 1 root root       9 Mar 13  2020 /usr/bin/python3 -> python3.8
-rwxr-xr-x 1 root root 5230592 Jun 22 20:18 /usr/bin/python3.8

With the following Dockerfile (from the question);

FROM mcr.microsoft.com/playwright
RUN apt update
RUN apt install -y software-properties-common
RUN add-apt-repository -y ppa:deadsnakes/ppa
RUN apt update
RUN apt install -y python3.10

RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.8 2

python is now added and controlled by alternatives, but python3 is untouched:

# ls -l /usr/bin/python*
lrwxrwxrwx 1 root root      24 Dec 16 04:10 /usr/bin/python -> /etc/alternatives/python
lrwxrwxrwx 1 root root       9 Mar 13  2020 /usr/bin/python3 -> python3.8
-rwxr-xr-x 1 root root 5565184 Dec  7 01:12 /usr/bin/python3.10
-rwxr-xr-x 1 root root 5230592 Jun 22 20:18 /usr/bin/python3.8
# ls -l /etc/alternatives/python
lrwxrwxrwx 1 root root 18 Dec 16 04:10 /etc/alternatives/python -> /usr/bin/python3.8

Priority

From alternative’s manpage:

If the group is in automatic mode, and the newly added alternatives’
priority is higher than any other installed alternatives for this group, the
symlinks will be updated to point to the newly added alternatives.

This is numeric, so it’s not that 1 is the winner and 2 is second-best, but rather 2 is higher than 1.

Resolution

By changing both the executable form python to python3, and the priority so that 3.10 will be 2 and 3.8 will be 1 (as such):

FROM mcr.microsoft.com/playwright
RUN apt update
RUN apt install -y software-properties-common
RUN add-apt-repository -y ppa:deadsnakes/ppa
RUN apt update
RUN apt install -y python3.10

RUN update-alternatives --install /usr/bin/python3 python /usr/bin/python3.10 2
RUN update-alternatives --install /usr/bin/python3 python /usr/bin/python3.8 1

the default python version should be 3.10:

# which python
# which python3
# ls -l /usr/bin/python*
lrwxrwxrwx 1 root root      24 Dec 16 04:16 /usr/bin/python3 -> /etc/alternatives/python
-rwxr-xr-x 1 root root 5565184 Dec  7 01:12 /usr/bin/python3.10
-rwxr-xr-x 1 root root 5230592 Jun 22 20:18 /usr/bin/python3.8
# ls -l /etc/alternatives/python
lrwxrwxrwx 1 root root 19 Dec 16 04:16 /etc/alternatives/python -> /usr/bin/python3.10
# python3 --version
Python 3.10.9
Answered By: micromoses

The update-alternatives solution above worked for me, but I can’t seem to get a pip corresponding to version 3.10, has anyone run into this issue?

Answered By: ayan bandyopadhyay