@@ -126,9 +126,10 @@ def additional_preamble(image: str, tag: str = "") -> str:
126126 if is_alma9 :
127127 commands += (
128128 "# AlmaLinux 9 ships Python 3.9; pygemc and other tools require >=3.10.\n "
129- "# Install 3.11 from AppStream and make it the system python3.\n "
130- "RUN dnf install -y python3.11 python3.11-devel \\ \n "
131- " && ln -sf /usr/bin/python3.11 /usr/bin/python3 \n \n "
129+ "# Install 3.11 from AppStream. The python3 symlink is set in\n "
130+ "# post_package_setup(), after the main package install, to prevent\n "
131+ "# dnf from resetting it to 3.9 via the alternatives system.\n "
132+ "RUN dnf install -y python3.11 python3.11-devel \n \n "
132133 )
133134
134135 elif family == "debian" :
@@ -141,6 +142,19 @@ def additional_preamble(image: str, tag: str = "") -> str:
141142 return commands
142143
143144
145+ def post_package_setup (image : str , tag : str = "" ) -> str :
146+ """Steps that must run after package installation.
147+ Symlinks set here cannot be clobbered by dnf alternatives."""
148+ is_alma9 = "almalinux" in image .lower () and tag .startswith ("9" )
149+ if is_alma9 :
150+ return (
151+ "# Pin python3 → 3.11 after all packages are installed so dnf\n "
152+ "# alternatives cannot reset the symlink to 3.9.\n "
153+ "RUN ln -sf /usr/bin/python3.11 /usr/bin/python3\n \n "
154+ )
155+ return ""
156+
157+
144158def create_dockerfile (image : str , tag : str , geant4_version : str , root_version : str ,
145159 meson_version : str ,
146160 novnc_version : str ) -> str :
@@ -150,6 +164,7 @@ def create_dockerfile(image: str, tag: str, geant4_version: str, root_version: s
150164 commands += install_jlab_ca (image )
151165 commands += additional_preamble (image , tag )
152166 commands += packages_install_command (image , tag )
167+ commands += post_package_setup (image , tag )
153168 commands += cleanup_string_by_family [map_family (image )]
154169 commands += install_additional_libraries (image ,
155170 geant4_version ,
0 commit comments