S2I (Source to Image)解説 - 1. S2Iとは何か？


一般的に、アプリケーションを実行するためのコンテナイメージを作成する手法として、Dockerfileを作成し、Dockerというサービスを利用し、コンテナイメージをビルドする方法をとることが多いと思います。しかし、コンテナイメージをビルドするツール・方法が多く提案されています。そこで、本記事はコンテナイメージビルドツールの一つである、**S2I (Source to Image)** について紹介します。



# Source To Imageとは?
S2I(Source to Image)とは、コンテナイメージをビルドするプロセスを、**アプリケーションの開発側**と**環境構築側**に分けて、段階的に実行するコンテナイメージビルダーである。

S2Iでのビルドは、`S2I buid`によって実行される。`S2I buid`を実行すると、開発側が作成したアプリケーションソースコード (例えば、pythonやGoのスクリプト)をinputにし、環境構築側が作成した実行環境のコンテナイメージ である`s2i builder image`を取得し、アプリケーションに関する新規のコンテナイメージを生成する。要するに、S2Iは**アプリケーションソースコードからDockerイメージをビルド**する仕組みである。

S2Iを利用するメリットの一つは、**アプリケーション開発側の負担が減り、開発側がアプリケーション開発に専念できること**である。なぜならば、アプリケーション開発と環境構築のプロセスが分けられており、開発側が環境構築を行うためのファイルを作成する必要がなくなるからである。

![S2I_build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781216/dbd755d3-8a74-42ff-e1e2-59e2ec40564e.png)


# S2Iに関する基本用語について
ここで、S2Iに関する用語、`S2I builder image`、`S2I script`について説明する。


### **S2I builder image**
ビルド処理を実行するS2Iスクリプトとベースイメージ (Ubuntu、CentOS7, Debianなどのイメージのこと)を組み合わせ生成されるイメージである。アプリケーションのビルドと、実行環境をアセンブルするDockerイメージである。

ここで出てきたS2I scriptで様々な処理を行っている。次はS2I scriptの中身について確認する。

### **s2i script**

S2I scriptはbuilder imageの実行コンテナ内で実行されるスクリプト群で、`run`,`assemble`,`save-artifacts`といったスクリプトがある。主にアプリケーションのビルドを行うスクリプト「`assemble`」と、アプリケーションをデプロイしたミドルウェアを起動するスクリプト「`run`」の2つは、builderイメージの実行時に必須のスクリプトである。

S2I scritは以下の主に以下の2つで構成されている。

#### `assemble` script (必須)

- ソースコードからアプリケーションのアーティファクト（成果物）をビルドし、それらをイメージ内の適切なディレクトリに配置する。
- 例えば、GitやGitHubなどのソースリポジトリからcloneしたソースの処理を行う。
- assembleスクリプトのワークフローの具体例については、具体的なソースコードで確認していく。以下に、実際にPythonのコンテナイメージを作成するためのスクリプト例 `assemble.sh`を示す：

```bash:assemble.sh
#!/bin/bash -e
if [[ "$1" == "-h" ]]; then
        exec /usr/libexec/s2i/usage
fi

# アプリケーション、例えば、sample.py, requirements.txtをアプリの実行を行うディレクトリへコピーし配置している
echo "---> Installing application source..."
cp -Rf /tmp/src/. ./

# requirements.txtを用いて、pip installでライブラリのインストールを行っている
echo "---> Building application from source..."
pip install --upgrade pip
if [ -f requirements.txt ]; then
    pip install -r requirements.txt
fi
```
Pythonはスクリプト言語のため、今回アーティファクトのビルドを行うプロセスはないことに注意。



#### `run` script (required)
- アプリケーションを実行するためのスクリプト
- 実際にpythonスクリプト `sample.py`を実行するrun スクリプト例 `run.sh`
run
```bash:run.sh
#!/bin/bash -e
python sample.py
```

他にもオプションとして以下のようなスクリプトを追加することも可能である：
- usage script (optional)
    - ユーザーにイメージの利用方法を通知するためのスクリプト
- save-artifacts (optional)
    - S2Iの機能の一つである`incremental build` (増分ビルド)を実行する際に必要となる。ここでは、説明しない。


# DockerfileのみによるビルドとS2Iビルドの比較
ここでは、DockerfileのみによるコンテナイメージのビルドとS2Iによるビルド、それぞれのビルドプロセスの比較を簡単に行う。結論から言うと、この2つのプロセスの違いは以下である：
| Dockerfileのみのビルド            | S2Iビルド                           | 
| --------------------------------- | ----------------------------------- | 
| ビルドプロセス中で開発側、環境構築側の分担がない    | 開発側、環境構築側の分担がある      | 
| Dockerfileのみ                    | Dockerfile + S2I script             | 
| コンテナイメージのビルドは1回のみ | コンテナイメージのビルドは2段階行う | 

次では、それぞれのビルドワークフローを図で解説していく。

### Dockerfileのみを用いたビルド
Dockerfileのみのビルドでは、ビルドプロセスに開発側、環境構築側の分担がなく、コンテナイメージの作成が以下図のように行われる。
![mehcanism_Dockerfile_build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781216/fb25321b-9ace-1768-2cf8-b88856e08b47.png)


### S2Iビルドのワークフロー
まず、S2Iビルドのワークフローについて解説する。今回の説明では、GitHub、DockerHubの外部レジストリを利用することを仮定しているが、S2Iのワークフローを内部レジストリのみを使用したローカル環境内で実行することも可能である。

#### 1. S2I builder imageの生成
環境構築側が`Dockerfile`、`S2I script`を作成し、Dockerを使い、Dockerビルドを行い、`S2I builder image`を生成する。その後、コンテナイメージレジストリ(例えば、GitHub, DockerHub)へ保存する。
![mehcanism_S2I_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781216/6e8016c5-f6bd-cccb-754d-7643d1e3aed8.png)


#### 2. アプリケーションソースコードの開発
アプリケーションの開発側がアプリケーション用のソースコードを作成し、 ソースコードリポジトリ (例えば、Git,GitHub)へ保存する。

#### 3. S2Iビルドの実行
ソースコードリポジトリから開発者が作成したアプリケーションソースコードとS2I builder imageを、それぞれ取得し、S2I buildを実行する。すると新規のコンテナイメージが作成されるので、これをコンテナイメージレジストリへ保存する。

![mehcanism_S2I.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781216/c257ad1f-d17b-db59-ab84-5dd0e82ba4fe.png)


より細かい比較については、ローカル環境による具体的なビルドにより、次回確認していきたいと思います。以下に参考にした文献やS2Iについて書かれた記事をあげておきます。

# 参考文献
- [OpenShift徹底活用ガイド](https://www.amazon.co.jp/OpenShift%E5%BE%B9%E5%BA%95%E6%B4%BB%E7%94%A8%E3%82%AC%E3%82%A4%E3%83%89-%E6%BE%A4%E6%A9%8B%E6%9D%BE%E7%8E%8B%E3%80%81%E9%9D%92%E5%B1%B1%E7%9C%9F%E5%B7%B3%E3%80%81%E5%A4%A7%E6%B4%A5%E6%B5%A9%E5%8F%B8%E3%80%81%E9%96%A2%E5%85%8B%E9%9A%86%E3%80%81%E9%88%B4%E6%9C%A8%E6%B4%8B%E4%B8%80%E6%9C%97%E3%80%81%E6%B2%B3%E8%A7%92%E4%BF%AE/dp/4863543182/ref=pd_lpo_sccl_1/358-6750756-8978840?pd_rd_w=tDOnU&content-id=amzn1.sym.d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_p=d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_r=DQCHQ5NQBKHEBDMRHVSJ&pd_rd_wg=AJ8Bg&pd_rd_r=0802ab4e-8cbf-4f6e-acd7-f4f4a1b19930&pd_rd_i=4863543182&psc=1)
- [Source-To-Image (S2I)公式ドキュメント](https://github.com/openshift/source-to-image)
- [[OpenShift]自作のS2Iスクリプトを使ってローカルにあるPerlスクリプトをS2Iビルドしてデプロイする](https://zaki-hmkc.hatenablog.com/entry/2020/02/20/213638)
- [Minishiftで遊んでみよう！手軽にkubernetesを体験するの巻](https://qiita.com/yoshii0110/items/ef8502d46a49dd0cc3ee)
- [MACOSにS2IコマンドをインストールしてS2Iビルドする](https://korattablog.com/2020/07/06/macos%E3%81%ABs2i%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%A6s2i%E3%83%93%E3%83%AB%E3%83%89%E3%81%99%E3%82%8B/)
- [OpenShift v3 と source-to-image (s2i)](https://qiita.com/nak3/items/6407c01cc2d1f153c0f1)
- [S2I work flow](https://www.kubesphere.io/docs/v3.3/project-user-guide/image-builder/s2i-introduction/)
- [第5章 S2I イメージのテスト](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/3.9/html/creating_images/creating-images-s2i-testing)
- [S2Iに再入門](https://qiita.com/Yusuke-Y/items/a636263398cfce100c35)
- [OpenShift Origin構築手順メモ](https://enakai00.hatenablog.com/entry/2015/12/27/221936)
- [OpenShift OriginによるDockerイメージ管理（1）〜イメージストリームを理解する](https://enakai00.hatenablog.com/entry/2015/12/28/203731)
- [OpenShift OriginによるDockerイメージ管理（2）〜Dockerfileによるイメージビルドを自動化](https://enakai00.hatenablog.com/entry/2015/12/28/215957)
- [OpenShift OriginによるDockerイメージ管理（3）〜Dockerfileからイメージを作成する際のお作法](https://enakai00.hatenablog.com/entry/2015/12/30/092724)
- [OpenShift OriginによるDockerイメージ管理（4）〜S2Iによるイメージビルド](https://enakai00.hatenablog.com/entry/2016/01/03/174854)