Sunday, January 28, 2024

[SOLVED] How do you install two versions of python on a docker image and switch them on build?

Issue

I need to create a docker image that features two versions of Python, lets say, 3.9 & 3.10.

The idea is to install both versions of Python and then install the pip/wheel/lib directories from Python 3.9 as it is the default version we want to use. I then created sys links to the pip/wheel/lib directories.

Then using a .sh script, we will pass the Python version via a build argument, and using that ARG, we will select the alternative version of Python, this case being 10, which will make the 3.10 version the version used by the build.

But i'm not sure what the best way to do this, the dockerfile.

My Dockerfile looks like this:

COPY --from=python1 --chown=developer:developer /usr/local/bin/py* /usr/local/bin/
COPY --from=python1 --chown=developer:developer /usr/local/bin/pip* /usr/local/bin/
COPY --from=python1 --chown=developer:developer /usr/local/bin/wheel /usr/local/bin/
COPY --from=python1 --chown=developer:developer /usr/local/lib/lib* /usr/local/lib/

RUN for link in /usr/local/bin/py* /usr/local/bin/pip* /usr/local/bin/wheel /usr/local/lib/lib*; do \
        [ -e "$link" ] || ln -s "$link" /usr/local/bin/; \
    done

# Copy Base Python Version
COPY --from=python1 --chown=developer:developer /usr/local/lib/python3.9/ /usr/local/lib/python3.9/

# Copy Alternative Python Version
COPY --from=python2 --chown=developer:developer /usr/local/lib/python3.10/ /usr/local/lib/python3.10/

# Copy the version-switching script
COPY sagacity-cd/swap.sh /usr/local/bin/

# Run the script to set the default version based on the build argument
USER root
RUN chmod +x /usr/local/bin/swap.sh && \
    /usr/local/bin/swap.sh ${DEFAULT_PYTHON_VERSION}
USER developer

# Copy the version-switching script
COPY sagacity-cd/swap.sh /usr/local/bin/

# Run the script to set the default version based on the build argument
USER root
RUN chmod +x /usr/local/bin/swap.sh && \
    /usr/local/bin/swap.sh ${DEFAULT_PYTHON_VERSION}
USER developer 

My swap.sh looks like this:

#!/bin/bash

if [ "$1" == "3.9" ]; then
    rm /usr/local/bin/python
    ln -s /usr/local/bin/python3.9 /usr/local/bin/python
elif [ "$1" == "3.10" ]; then
    rm /usr/local/bin/python
    ln -s /usr/local/bin/python3.10 /usr/local/bin/python
else
    echo "Invalid version specified. Usage: $0 [3.9|3.10]"
    exit 1
fi

Solution

generic image that has both and we want to just swap the version on our CI/CD build when we build the Lambda, via Terraform passing in build args

If you're already going to build the Lambda via Terraform, why don't you just build the Lambda with the correct version of Python?

Say the Dockerfile for the Lambda is like this:

ARG PY_VERSION
FROM python:${PY_VERSION}-bookworm

# then all your lambda stuff

COPY . /app

ENTRYPOINT /app/run.sh

Now you can build your lambda for different versions:

docker build --build-arg="PY_VERSION=3.10" .
docker build --build-arg="PY_VERSION=3.9" .
docker build --build-arg="PY_VERSION=3.8" .

This is mentioned here in the docs.

If you really want a base image for the different versions, you can use the same thing, and pre-build the different versions into your own container repo, and then use the same mechanism to build the next layer (but that seems like overkill to me).



Answered By - blueteeth
Answer Checked By - Katrina (WPSolving Volunteer)