Enabling Software Collections Binaries on a Docker Image

If you’ve ever had to install a Software Collections (SCL) binary on a Docker image, you probably felt really confused when a simple “yum install” in your Dockerfile failed to work. “I’ve installed plenty of binaries using yum”, you said. What’s the deal with these SCL binaries?

The truth is, the yum command did install the binary correctly, but not in the way that you’d expect without knowing more about SCL. Software Collections allow you to have multiple versions of the same tool available on a system. Because of this, it is up to the administrator to enable the correct version of the tool using commands provided by SCL.

In this post, we will learn how to persistently enable SCL binaries on a Docker image, such that the correct version of the binary is enabled on startup. We’ll look at two different methods of doing this – first by creating an entrypoint and second by utilizing environment variables.

Method #1 – Entrypoint

An entrypoint can be written in the Dockerfile to enable the SCL binary on container startup. Here’s an example Dockerfile:

FROM docker.io/centos:7

# Install SCL release package and python SCL
RUN yum -y install centos-release-scl && \
    yum -y install --setopt=tsflags=nodocs rh-python35

# Enable rh-python scl binary
COPY entrypoint.sh /usr/bin/entrypoint.sh
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT [ "/usr/bin/entrypoint.sh" ]

And the entrypoint.sh script:

#!/bin/bash
source scl_source enable rh-python35
exec "$@"

Let’s test this out with:

docker build -t scl-test:latest .
docker run --name scl-test -it scl-test python --version

The result should be (at the time of writing):

Python 3.5.1

Method #2 – Environment Variables

Another way to persistently enable scl binaries in a docker image is to set environment variables.

FROM docker.io/centos:7
 
# Install SCL release package and python SCL
RUN yum -y install centos-release-scl && \
    yum -y install --setopt=tsflags=nodocs rh-python35
 
# Enable rh-python scl binary
COPY scl_enable /usr/bin/scl_enable
ENV BASH_ENV="/usr/bin/scl_enable" \
    ENV="/usr/bin/scl_enable" \
    PROMPT_COMMAND=". /usr/bin/scl_enable"

And here’s the scl_enable script:

unset BASH_ENV PROMPT_COMMAND ENV
source scl_source enable rh-python35

Let’s test is out with:

docker build -t scl-test:latest .
docker run --name scl-test -it scl-test /bin/bash -c "python --version"

Again, the result should be:

Python 3.5.1

Each environment variable set plays a role in making sure scl is enabled:

  • BASH_ENV: Specifies a command or script to run when bash is started non-interactively
  • ENV: Specifies a command or script to run when sh is started interactively
  • PROMPT_COMMAND: Specifies a command or script to run before bash displays a prompt (for interactive sessions)

Note that in the “docker run” command above, we needed to pass /bin/bash in as a command. This is because we are starting a non-interactive session (leveraging the BASH_ENV variable). Without passing /bin/bash, the scl binary wouldn’t have been enabled.

With the given Dockerfile, you could, however, run docker run –name scl-test -it scl-test to start an interactive /bin/sh session (leveraging ENV), and your scl binaries would be enabled there.

Thanks for Reading!

Hopefully this helps resolve some confusion around Software Collections and persistently enabling scl binaries in a Dockerfile.

Austin Dewey

Austin Dewey is a DevOps engineer focused on delivering a streamlined developer experience on cloud and container technologies. Austin started his career with Red Hat’s consulting organization, where he helped drive success at many different Fortune 500 companies by automating deployments on Red Hat’s Kubernetes-based PaaS, OpenShift Container Platform. Currently, Austin works at fintech startup Prime Trust, building automation to scale financial infrastructure and support developers on Kubernetes and AWS. Austin is the author of "Learn Helm", a book focused on packaging and delivering applications to Kubernetes, and he enjoys writing about open source technologies at his blog in his free time, austindewey.com.

4 Comments

  1. I just set environment variables in my Dockerfile to match /opt/rh/rh-python35/enable

    1. I prefer to use “source scl_source enable” in order to abstract away the file path, but setting the env vars in that way should work as well.

  2. Isn’t it simpler to just set ENTRYPOINT [“/usr/bin/scl”, “enable”, “rh-python35” ] and avoid all the scripts?

    1. Using the entrypoint script provided in the post allows for general use cases. The script will allow you to start an interactive bash session or run a specific command, and python 3.5 will be enabled in both cases.

      However, you’re on the right track if you have a more specific use case you want to cover. You could build an image using your entrypoint and execute a script inline by running docker run --name scl-test -it scl-test "python -c 'print(\"Hello world\")'". You could also say something like ENTRYPOINT ["/usr/bin/scl","enable","rh-python35","script.py"] to execute a specific python script using python 3.5.

Leave a Reply