# Source to image tool (S2I)
###### tags: `s2i`
S2I is a tool to build Docker image. It is one of major method to build image on OpenShift
S2I relies on special base image, which includes basic running environment such Python, PHP, Nginx, etc and some S2I scripts, such as
1. assemble - for installing source code into the image.
2. run - indicate how your code run.
3. usage - print usage.
RedHat has some official images ready use, such as Python, Ruby.
Test environment: CentOS 7.9
#### Install S2I
Install dependency packages
```
[root@lab-test-centos7 ~]# yum install epel-release -y
[root@lab-test-centos7 ~]# yum update -y
[root@lab-test-centos7 ~]# yum install golang git -y
[root@lab-test-centos7 ~]# sudo curl -fsSL https://get.docker.com/ | sh
[root@lab-test-centos7 ~]# systemctl enable docker
[root@lab-test-centos7 ~]# systemctl start docker
```
Install S2I
```
[root@lab-test-centos7 ~]# wget https://github.com/openshift/source-to-image/releases/download/v1.3.1/source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz
[root@lab-test-centos7 ~]# tar -xvzf ./source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz .
./
./sti
./s2i
[root@lab-test-centos7 ~]# mv ./s2i ./sti /usr/local/bin/
[root@lab-test-centos7 ~]# s2i version
s2i v1.3.1
```
#### Build a python continer image for S2I
```
[root@lab-test-centos7 ~]# git clone https://github.com/sclorg/s2i-python-container.git
```
```
[root@lab-test-centos7 ~]# cd s2i-python-container/
[root@lab-test-centos7 s2i-python-container]# ll
total 52
drwxr-xr-x. 5 root root 82 Oct 3 14:01 2.7
drwxr-xr-x. 5 root root 83 Oct 3 14:01 3.10
drwxr-xr-x. 5 root root 82 Oct 3 14:01 3.6
drwxr-xr-x. 5 root root 150 Oct 3 14:01 3.8
drwxr-xr-x. 5 root root 128 Oct 3 14:01 3.9
drwxr-xr-x. 5 root root 82 Oct 3 14:01 3.9-minimal
drwxr-xr-x. 2 root root 6 Oct 3 14:01 common
drwxr-xr-x. 22 root root 4096 Oct 3 14:01 examples
-rwxr-xr-x. 1 root root 6400 Oct 3 14:01 generator.py
drwxr-xr-x. 2 root root 88 Oct 3 14:01 imagestreams
-rw-r--r--. 1 root root 11357 Oct 3 14:01 LICENSE
-rw-r--r--. 1 root root 735 Oct 3 14:01 Makefile
-rw-r--r--. 1 root root 5234 Oct 3 14:01 manifest-minimal.yml
-rw-r--r--. 1 root root 5000 Oct 3 14:01 manifest.yml
-rw-r--r--. 1 root root 5695 Oct 3 14:01 README.md
drwxr-xr-x. 2 root root 27 Oct 3 14:01 specs
drwxr-xr-x. 8 root root 224 Oct 3 14:01 src
drwxr-xr-x. 2 root root 224 Oct 3 14:01 test
```
```
[root@lab-test-centos7 s2i-python-container]# yum install go-md2man -y
[root@lab-test-centos7 s2i-python-container]# git submodule update --init
[root@lab-test-centos7 s2i-python-container]# make build TARGET=centos7 VERSION=3.8
```
```
[root@lab-test-centos7 test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> f7e084d6363c 4 minutes ago 698MB
quay.io/centos7/s2i-base-centos7 latest 740bb8287e02 6 days ago 532MB
[root@lab-test-centos7 s2i-python-container]# docker tag f7e084d6363c local/s2i-centos7-python38
[root@lab-test-centos7 s2i-python-container]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
local/s2i-centos7-python38 latest f7e084d6363c 13 minutes ago 698MB
quay.io/centos7/s2i-base-centos7 latest 740bb8287e02 6 days ago 532MB
```
*__Note__*: you could launch tests to check functionality. It could take above half hour.
```
[root@lab-test-centos7 s2i-python-container]# make test TARGET=centos7 VERSIONS=3.8
output omit ...
Test cases results:
[PASSED] for 'gunicorn-config-different-port-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'gunicorn-config-different-port-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'gunicorn-config-different-port-test-app' test_application (00:00:12)
[PASSED] for 'gunicorn-config-different-port-test-app' test_application_with_user (00:00:12)
[PASSED] for 'gunicorn-config-different-port-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'gunicorn-different-port-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'gunicorn-different-port-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'gunicorn-different-port-test-app' test_application (00:00:12)
[PASSED] for 'gunicorn-different-port-test-app' test_application_with_user (00:00:12)
[PASSED] for 'gunicorn-different-port-test-app' test_application_enable_init_wrapper (00:00:11)
[PASSED] for 'django-different-port-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'django-different-port-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'django-different-port-test-app' test_application (00:00:25)
[PASSED] for 'django-different-port-test-app' test_application_with_user (00:00:25)
[PASSED] for 'django-different-port-test-app' test_application_enable_init_wrapper (00:00:15)
[PASSED] for 'standalone-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'standalone-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'standalone-test-app' test_application (00:00:12)
[PASSED] for 'standalone-test-app' test_application_with_user (00:00:11)
[PASSED] for 'standalone-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'setup-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'setup-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'setup-test-app' test_application (00:00:12)
[PASSED] for 'setup-test-app' test_application_with_user (00:00:11)
[PASSED] for 'setup-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'setup-requirements-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'setup-requirements-test-app' test_docker_run_usage (00:00:01)
[PASSED] for 'setup-requirements-test-app' test_application (00:00:12)
[PASSED] for 'setup-requirements-test-app' test_application_with_user (00:00:12)
[PASSED] for 'setup-requirements-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'django-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'django-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'django-test-app' test_application (00:00:25)
[PASSED] for 'django-test-app' test_application_with_user (00:00:25)
[PASSED] for 'django-test-app' test_application_enable_init_wrapper (00:00:14)
[PASSED] for 'numpy-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'numpy-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'numpy-test-app' test_application (00:00:11)
[PASSED] for 'numpy-test-app' test_application_with_user (00:00:12)
[PASSED] for 'numpy-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'app-home-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'app-home-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'app-home-test-app' test_application (00:00:11)
[PASSED] for 'app-home-test-app' test_application_with_user (00:00:12)
[PASSED] for 'app-home-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'locale-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'locale-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'locale-test-app' test_application (00:00:11)
[PASSED] for 'locale-test-app' test_application_with_user (00:00:12)
[PASSED] for 'locale-test-app' test_application_enable_init_wrapper (00:00:11)
[PASSED] for 'pipenv-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'pipenv-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'pipenv-test-app' test_application (00:00:12)
[PASSED] for 'pipenv-test-app' test_application_with_user (00:00:12)
[PASSED] for 'pipenv-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'app-module-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'app-module-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'app-module-test-app' test_application (00:00:11)
[PASSED] for 'app-module-test-app' test_application_with_user (00:00:12)
[PASSED] for 'app-module-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'pyuwsgi-pipenv-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'pyuwsgi-pipenv-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'pyuwsgi-pipenv-test-app' test_application (00:00:13)
[PASSED] for 'pyuwsgi-pipenv-test-app' test_application_with_user (00:00:13)
[PASSED] for 'pyuwsgi-pipenv-test-app' test_application_enable_init_wrapper (00:00:13)
[PASSED] for 'micropipenv-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'micropipenv-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'micropipenv-test-app' test_application (00:00:11)
[PASSED] for 'micropipenv-test-app' test_application_with_user (00:00:12)
[PASSED] for 'micropipenv-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'micropipenv-requirements-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'micropipenv-requirements-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'micropipenv-requirements-test-app' test_application (00:00:12)
[PASSED] for 'micropipenv-requirements-test-app' test_application_with_user (00:00:12)
[PASSED] for 'micropipenv-requirements-test-app' test_application_enable_init_wrapper (00:00:11)
[PASSED] for 'setup-cfg-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'setup-cfg-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'setup-cfg-test-app' test_application (00:00:11)
[PASSED] for 'setup-cfg-test-app' test_application_with_user (00:00:12)
[PASSED] for 'setup-cfg-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'npm-virtualenv-uwsgi-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'npm-virtualenv-uwsgi-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'npm-virtualenv-uwsgi-test-app' test_application (00:00:13)
[PASSED] for 'npm-virtualenv-uwsgi-test-app' test_application_with_user (00:00:12)
[PASSED] for 'npm-virtualenv-uwsgi-test-app' test_application_enable_init_wrapper (00:00:13)
[PASSED] for 'mod-wsgi-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'mod-wsgi-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'mod-wsgi-test-app' test_application (00:00:12)
[PASSED] for 'mod-wsgi-test-app' test_application_with_user (00:00:11)
[PASSED] for 'mod-wsgi-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'pin-pipenv-version-test-app' test_s2i_usage (00:00:02)
[PASSED] for 'pin-pipenv-version-test-app' test_docker_run_usage (00:00:02)
[PASSED] for 'pin-pipenv-version-test-app' test_application (00:00:12)
[PASSED] for 'pin-pipenv-version-test-app' test_application_with_user (00:00:13)
[PASSED] for 'pin-pipenv-version-test-app' test_application_enable_init_wrapper (00:00:12)
[PASSED] for 'var-docker' test_scl_variables_in_dockerfile (00:00:10)
[PASSED] for 'var-docker' test_from_dockerfile (00:01:32)
Tests for quay.io/centos7/python-38-centos7:1 succeeded.
```
#### Example of using S2I to build image
```
[root@lab-test-centos7 s2i-python-container]# s2i build ./examples/django-test-app local/s2i-centos7-python38 django-test-app:latest
---> Installing application source ...
---> Installing dependencies ...
Ignoring Django: markers 'python_version > "3.8"' don't match your environment
Collecting Django<2
Downloading Django-1.11.29-py2.py3-none-any.whl (6.9 MB)
Collecting pytz
Downloading pytz-2022.4-py2.py3-none-any.whl (500 kB)
Installing collected packages: pytz, Django
Successfully installed Django-1.11.29 pytz-2022.4
WARNING: You are using pip version 21.3.1; however, version 22.2.2 is available.
You should consider upgrading via the '/opt/app-root/bin/python3.8 -m pip install --upgrade pip' command.
---> Collecting Django static files ...
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/css/base.css'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/css/changelists.css'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/css/dashboard.css'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/css/fonts.css'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/css/forms.css'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/css/login.css'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/css/rtl.css'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/css/widgets.css'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/fonts/LICENSE.txt'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/fonts/README.txt'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/fonts/Roboto-Bold-webfont.woff'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/fonts/Roboto-Light-webfont.woff'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/fonts/Roboto-Regular-webfont.woff'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/LICENSE'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/README.txt'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/calendar-icons.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/icon-addlink.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/icon-alert.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/icon-calendar.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/icon-changelink.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/icon-clock.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/icon-deletelink.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/icon-no.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/icon-unknown-alt.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/icon-unknown.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/icon-yes.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/inline-delete.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/search.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/selector-icons.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/sorting-icons.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/tooltag-add.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/tooltag-arrowright.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/gis/move_vertex_off.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/img/gis/move_vertex_on.svg'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/SelectBox.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/SelectFilter2.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/actions.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/actions.min.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/calendar.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/cancel.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/change_form.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/collapse.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/collapse.min.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/core.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/inlines.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/inlines.min.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/jquery.init.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/popup_response.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/prepopulate.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/prepopulate.min.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/prepopulate_init.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/timeparse.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/urlify.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/vendor/jquery/LICENSE-JQUERY.txt'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/vendor/jquery/jquery.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/vendor/jquery/jquery.min.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/vendor/xregexp/LICENSE-XREGEXP.txt'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/vendor/xregexp/xregexp.js'
Copying '/opt/app-root/lib64/python3.8/site-packages/django/contrib/admin/static/admin/js/vendor/xregexp/xregexp.min.js'
61 static files copied to '/opt/app-root/src/staticfiles'.
Build completed successfully
```
Check image history, it only add one layer on top of "local/s2i-centos7-python38"
```
[root@lab-test-centos7 s2i-python-container]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
django-test-app latest 745862b3b085 About a minute ago 723MB
local/s2i-centos7-python38 latest f7e084d6363c 16 minutes ago 698MB
quay.io/centos7/s2i-base-centos7 latest 740bb8287e02 6 days ago 532MB
[root@lab-test-centos7 s2i-python-container]# docker history django-test-app
IMAGE CREATED CREATED BY SIZE COMMENT
745862b3b085 3 minutes ago /bin/sh -c tar -C /tmp -xf - && /usr/libexec… 24.5MB
f7e084d6363c 17 minutes ago /bin/sh -c #(nop) LABEL io.openshift.builde… 0B
e5e62a472336 17 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "$STI… 0B
2dff322f6385 17 minutes ago /bin/sh -c #(nop) USER 1001 0B
0d4fa3475bda 17 minutes ago /bin/sh -c source scl_source enable rh-pytho… 14.4MB
0c77815f7cfb 17 minutes ago /bin/sh -c #(nop) COPY dir:6beb140d3873a828a… 1.23MB
e01529703ea2 17 minutes ago /bin/sh -c #(nop) COPY dir:bde9e6936f4abec80… 18.1kB
81d71c1ea183 17 minutes ago /bin/sh -c #(nop) COPY dir:88fd71f67eeae799d… 10.3kB
55e684db3091 18 minutes ago /bin/sh -c INSTALL_PKGS="rh-python38 rh-pyth… 151MB
e32657c4dc55 21 minutes ago /bin/sh -c #(nop) LABEL summary=Platform fo… 0B
4a8b40304dcd 21 minutes ago /bin/sh -c #(nop) ENV SUMMARY=Platform for … 0B
1ec71b378b7a 21 minutes ago /bin/sh -c #(nop) ENV PYTHON_VERSION=3.8 PY… 0B
b65aa4a6efec 21 minutes ago /bin/sh -c #(nop) EXPOSE 8080 0B
740bb8287e02 6 days ago /bin/sh -c yum install -y centos-release-scl… 295MB FROM quay.io/centos7/s2i-core-centos7:latest
<missing> 6 days ago /bin/sh -c #(nop) LABEL summary="$SUMMARY" … 0B
<missing> 6 days ago /bin/sh -c #(nop) ENV SUMMARY="Base image wi… 0B
<missing> 6 days ago /bin/sh -c rpm-file-permissions && useradd… 33.7MB FROM registry.centos.org/centos/centos:7
<missing> 6 days ago /bin/sh -c #(nop) CMD ["base-usage"] 0B
<missing> 6 days ago /bin/sh -c #(nop) ENTRYPOINT ["container-ent… 0B
<missing> 6 days ago /bin/sh -c #(nop) WORKDIR ${HOME} 0B
<missing> 6 days ago /bin/sh -c #(nop) COPY dir:f01b7cf4c814e2dfe… 0B
<missing> 6 days ago /bin/sh -c rpmkeys --import file:///etc/pki/… 0B
<missing> 6 days ago /bin/sh -c #(nop) ENV BASH_ENV=${APP_ROOT}/e… 0B
<missing> 6 days ago /bin/sh -c #(nop) ENV STI_SCRIPTS_URL=im… 0B
<missing> 6 days ago /bin/sh -c #(nop) LABEL summary="$SUMMARY" … 0B
<missing> 6 days ago /bin/sh -c #(nop) ENV SUMMARY="Base image wh… 0B
<missing> 22 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 22 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 22 months ago /bin/sh -c #(nop) ADD file:c45f0145b324a6436… 203MB
```
Validation by running container from the image
```
[root@lab-test-centos7 s2i-python-container]# docker run -it --rm django-test-app
---> Migrating database ...
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying sessions.0001_initial... OK
---> Serving application with 'manage.py runserver 0.0.0.0:8080' ...
WARNING: this is NOT a recommended way to run you application in production!
Consider using gunicorn or some other production web server.
Performing system checks...
System check identified no issues (0 silenced).
October 03, 2022 - 04:26:26
Django version 1.11.29, using settings 'project.settings'
Starting development server at http://0.0.0.0:8080/
Quit the server with CONTROL-C.
```
#### Reference
https://www.cyberithub.com/install-go-on-centos/
https://github.com/openshift/source-to-image/
https://cloud.redhat.com/blog/create-s2i-builder-image
https://zhuanlan.zhihu.com/p/33046277