S2Iに再入門

こんにちは!!
最近は雨が多いですね！早く青空が広がるといいなぁっと思っている今日このごろです。

さて、今日はS2Iについて改めて勉強していきたいと思います。

Opneshiftのビルド方式の一つであるS2IことSource to Imageですが、簡単そうに見えて以外に奥が深いかったので、再度整理して行きます。

# Source To Imageとは

> Source-to-Image (S2I) は再現可能な Docker 形式のコンテナーイメージをビルドするためのツールです。これはアプリケーションソースをコンテナーイメージに挿入し、新規イメージをアセンブルして実行可能なイメージを生成します。

要するに、**ソースコードからDockerイメージをビルド**する仕組みとなります。

![S2I.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675393/7c3ab7be-a3b6-4803-378a-cdd19d0f23ba.png)


ソースコードとイメージが別れているので管理がしやすことがメリットとしてあげられます。よくある、Dockerfileは開発者と運用者どちらで管理するかという問題を回避することが出来ます。

上記の図だとソースコードは開発者、s2i builder imageは運用者が管理する構造を作ることが可能です。

# s2i builder imageの中身

では具体的に中身を見ていこうと思います。

## s2i builder imageで行われいること

"s2i builder image"で以下のことが行われています。

1. s2iスクリプトを準備(ダウンロードまたは内部のスクリプトを使用)
2. アプリケーションのソースコードをダウンロード
3. アプリケーションのソースコードをs2i builder imageへ挿入
4. s2i builder imageで定義されているスクリプトを実行
5. Docker Imageを作成

 

図にすると以下ようになります。

![S2I-S2I.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675393/6f4bce0c-51ae-df19-20f0-1518948816c1.png)


s2iスクリプトで色々な処理を行っていそうですね。もう少しスクリプトの中身を見て行こうと思います。

## s2iスクリプト

s2iスクリプトは以下の主に以下の2つで構成されています。

- assemble
    - アプリケーションをビルドするためのスクリプト
- run
    - アプリケーションを起動するためのスクリプト

s2i builder imageの中には上記のスクリプトが組み込まれています。ソースコードをs2i builder imageに合わせると、assembleスクリプトが実行され成果物が特定のフォルダに格納されせます。

格納された成果物をrunスクリプトで実行する感じです。

以下では実際のスクリプトの中身を見て行きます。参考に以下のサイトを利用します。

[https://github.com/sclorg/s2i-python-container/blob/master/3.6/s2i](https://github.com/sclorg/s2i-python-container/blob/master/3.6/s2i/bin/assemble)/

### assembleについて

assembleスクリプトの実際の中身をみて見たいと思います。今回はpythonのs2iのベースイメージのassembleを抜粋しています。

```bash
elif [[ -f requirements.txt ]]; then
  echo "---> Installing dependencies ..."
  pip install -r requirements.txt
fi

if [[ -f setup.py && -z "$DISABLE_SETUP_PY_PROCESSING" ]]; then
  echo "---> Installing application ..."
  pip install .
fi
```

上記にようにassembleではPythonのモジュールをインストールを実施しています。Javaなのであればコンパイルなどを行うことが可能です。

### runについて

実際にアプリケーションを起動するためのスクリプトが記載されています。

```bash
app_file_check="${APP_FILE-}"
APP_FILE="${APP_FILE-app.py}"
if [[ -f "$APP_FILE" ]]; then
  echo "---> Running application from Python script ($APP_FILE) ..."
  maybe_run_in_init_wrapper python "$APP_FILE"
else
  test -n "$app_file_check" && (>&2 echo "ERROR: file '$app_file_check' not found.") && exit 1
fi
```

ここではapp.pyまたは環境変数APP_FILEで指定されたファイルを実行するようになっていますね。余談ですがDocker Imageを設定する場合は環境変数を使う場合が多いみたいです。

# スクリプトの実行

スクリプトを見てきましたが、どこで実行が定義されているのでしょうか。

まず上記のDockerfileを見て見ましょう。[こちら](https://github.com/sclorg/s2i-python-container/blob/master/3.6/Dockerfile)にあります。

どこにも記載がりません。では、今回ベースとなるイメージ(centos/s2i-base-centos7)を調べて見ましょう。

s2i-base-centos7のDockerfileは[こちら](https://github.com/sclorg/s2i-base-container/blob/master/base/Dockerfile)です。こちらにも記載はなさそうですね。

では、さらに調べてみましょう。ベースイメージのcentos/s2i-core-centos7を調べてみます。

s2i-core-centos7のDockerfileは[こちら](https://github.com/sclorg/s2i-base-container/blob/master/core/Dockerfile)です。こちらをみると以下の文があります。

```
LABEL io.openshift.s2i.scripts-url=image:///usr/libexec/s2i
```

Kubernetesはベンダーごとの拡張機能を利用するためにLabelを利用しています。Openshiftの拡張機能を利用するために上記のLabelが定義されています。上記のLabelを利用してs2iスクリプトの実行を定義しています。

# 補足 Docker イメージのレイヤ構造

Dockerイメージは複数のレイヤーが重なった形になっています。そのため、今回はs2i-core-centos7イメージで定義された情報をs2i-python-containerで利用することが可能となっています。以下のようなイメージです。

![S2I-Docker_layer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675393/2887b643-f433-4e99-bd18-522580d0368e.png)


# まとめ

Source To Imageの動作について見てきましたがいかがでしたでしょうか。

Opneshiftに搭載されている機能ですが、もちろんローカルでも試すことができますしBuilder Imageも自分で作成することができます。

シンプルなCI/CDを実装するならassembleにステップを記述する方法もありかもしれません。

ぜひ活用して行きたいと思いますー