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.