フラミナル

考え方や調べたことを書き殴ります。IT技術系記事多め

Cloud Native Buildpacksをちょっとだけ触ってみる

f:id:lirlia:20210617000007p:plain

はじめに

世の中にはすごいエンジニアや、よりよい物を作ろうと工夫しているエンジニアがたくさんいます。しかもその工夫や苦労をネットに公開してくれていることさえあります。

本になっているわけではないので体系的に学ぶことはできないのですが、そこで考えた工夫やエッセンス、調査内容は必ず誰かの糧になると思います。この記事では私が「読む価値がある!」と思った記事を引用しながら、自分の考えを追加して理解を深めていこうというものです。

今回紹介する記事

logmi.jp

素晴らしい記事をありがとうございます!

Dockerfileの問題点

  • ネットで検索したDockerfileをベースにするので不要な設定はいりがち
  • 作ったDockerfileにライブラリやパッケージの脆弱性入り込みがち
  • 人によって全然違うDockerfileができる
    • 誤解を恐れずに言えば空っぽのサーバに設定ファイルを自由に追加している

-> まとめるとDockerfileをきちんとメンテしないといけないのに、メンテされずらい+量が多い+人が自力で書かないといけないという現状になっている

解決方針

  • 自動ビルドする仕組みとその定義を用意してあげる
    • Dockerfileなんて作るのをやめてしまえ
      • ※いわゆるアプリケーションでしか使えない
      • 例:MySQLコンテナ作る時には使えない
  • この解決を図る1つの手法として挙げられるものが、Cloud Native Buildpacks(CNB)
  • CNBはDockerfileで実現していたビルドを、どうビルドを定義するのかを定義されているスクリプトファイル

それを使うことによって、自動でコードから、例えば「これはJava」「これはPython」と判定して、その判定に沿ってJava用のベストプラクティスに沿ったビルドをする、Python用のベストプラクティスに沿ったビルドをする、といったかたちでイメージを作成するためのツールになります。

これを採用すると、Dockerfileを書く手間がまずかからなくなる。当然Buildpacksのバージョンやビルド定義が古ければ脆弱性が入ってしまう可能性がありますが、きちんと更新して、ちゃんと管理されているものを使う限りは、そのリスクが大幅に減ります。

f:id:lirlia:20210616230510p:plain

代替技術としてのCloud Native Buildpacksとkpack

記事でたら書く

Cloud Native Buildpacksとは?

元々Buildpackというアプリケーションのソースコードをコンテナイメージに変換する仕組みがHerokuによって開発された。

しかしDocker/Kubernetesによりコンテナへの人気が高まったことから、より汎用的なコンテナイメージ作成ツールとして独立する形で、Cloud Native Buildpacks(CNB)が誕生した。

  • Pack
    • Buildpacksを動かす本体
  • Paketo Buildpacks
    • 上記CNBの一実装として、CFFによりホストされているのが「Paketo Buildpacks」だ。Node.jsやJava、Goなど定番の言語に対応している。
    • モジュールの提供、Pythonアプリビルドしたいならこれを使う
  • kpack
    • 「kpack」は、Pivotal(現VMware)によって開発されている、CNBをKubernetesのカスタムリソースとして動かせるプロジェクトだ。これにより、Kubernetes上でソースコードからコンテナイメージへの変換処理を行えるようになる

「Kubernetes-native」へと舵を切るCloud Foundry、その理由と展望は?:草間一人氏が解説(2/2 ページ) - @IT

packの動き

その中でbuildpackは、アプリのソースコードを検査し、アプリケーションをビルドして実行するための計画を策定する作業単位。一般的なbuildpackは以下の3つのファイルが最低必要になる

  • buildpack.toml – buildpackのメタデータ
  • bin/detect – buildpackが実行できるかどうかを検証
    • buildpackの内容と実際のソースコードが合致しているかどうかを逐次的にみていく、例えばnpm buildpackならpackage.jsonを見る
  • bin/build – buildpack ロジックの実行
    • 実際にイメージを作成する
    • pythonならpip install -r requirements.txtをしたり

詳細なpackの動きはこちらを参照 * spec/buildpack.md at main · buildpacks/spec · GitHub

CNB(pack)を試してみる

事前準備

# packインストール
$ (curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.19.0/pack-v0.19.0-linux.tgz" | sudo tar -C /usr/local/bin/ --no-same-owner -xzv pack)

# デフォルトのbuilderを設定
$ pack config default-builder  gcr.io/buildpacks/builder:v1
Builder gcr.io/buildpacks/builder:v1 is now the default builder

サンプルJavaアプリでpack buildしてみる

$ git clone https://github.com/buildpacks/samples

$ pack build sample-app --path samples/apps/java-maven --builder cnbs/sample-builder:bionic
bionic: Pulling from cnbs/sample-builder
4bbfd2c87b75: Pull complete
d2e110be24e1: Pull complete
889a7173dcfe: Pull complete
58904b69a6b9: Pull complete
ece01c3b31c4: Pull complete
5c4cf4bf4c45: Pull complete
9892987675a2: Pull complete
75dd0332c4e5: Pull complete
357fefdf9bc9: Pull complete
a697cc8a1d5c: Pull complete
5c2e4179bee1: Pull complete
c4e3bdcbb8c3: Pull complete
04f9e5a54d38: Pull complete
c238db6a02a5: Pull complete
53a52c7f9926: Pull complete
0cceee8a8cb0: Pull complete
a302059dbdba: Pull complete
db1bbcc47135: Pull complete
4f4fb700ef54: Pull complete
Digest: sha256:1021257ca330d07fab87a9abb10f5f118d6ec1a13c579f64fddf81d473554261
Status: Downloaded newer image for cnbs/sample-builder:bionic
bionic: Pulling from cnbs/sample-stack-run
4bbfd2c87b75: Already exists
d2e110be24e1: Already exists
889a7173dcfe: Already exists
58904b69a6b9: Already exists
ece01c3b31c4: Already exists
Digest: sha256:f3c067d8b11dfc0b0a2f14e9c8297f4ebfcca2b6d10e5fad1a7efd4f24fd61f9
Status: Downloaded newer image for cnbs/sample-stack-run:bionic
0.11.3: Pulling from buildpacksio/lifecycle
5dea5ec2316d: Pull complete
6d75e71a489d: Pull complete
Digest: sha256:d6c578fbdf88f2e2594d9907307b17775e648656f62e1ae810d31c804f928cf9
Status: Downloaded newer image for buildpacksio/lifecycle:0.11.3
===> DETECTING
[detector] samples/java-maven 0.0.1
===> ANALYZING
[analyzer] Previous image with name "sample-app" not found
===> RESTORING
===> BUILDING
[builder] ---> Java buildpack
[builder] ---> Installing JDK
[builder] ---> Running Maven Wrapper
[builder] [INFO] Scanning for projects...
[builder] [INFO] Downloading from central: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter-parent/maven-metadata.xml
〜必要ファイルのダウンロード〜
[builder] [INFO] Installing /workspace/pom.xml to /home/cnb/.m2/repository/io/buildpacks/example/sample/0.0.1-SNAPSHOT/sample-0.0.1-SNAPSHOT.pom
[builder] [INFO] ------------------------------------------------------------------------
[builder] [INFO] BUILD SUCCESS
[builder] [INFO] ------------------------------------------------------------------------
[builder] [INFO] Total time:  01:43 min
[builder] [INFO] Finished at: 2021-06-16T14:28:29Z
[builder] [INFO] ------------------------------------------------------------------------
===> EXPORTING
[exporter] Adding layer 'samples/java-maven:jdk'
[exporter] Adding 1/1 app layer(s)
[exporter] Adding layer 'launcher'
[exporter] Adding layer 'config'
[exporter] Adding layer 'process-types'
[exporter] Adding label 'io.buildpacks.lifecycle.metadata'
[exporter] Adding label 'io.buildpacks.build.metadata'
[exporter] Adding label 'io.buildpacks.project.metadata'
[exporter] Setting default process type 'web'
[exporter] Saving sample-app...
[exporter] *** Images (5a6cbb926327):
[exporter]       sample-app
[exporter] Adding cache layer 'samples/java-maven:jdk'
[exporter] Adding cache layer 'samples/java-maven:maven_m2'
Successfully built image sample-app

確認

$ docker images |grep sample-app
sample-app                                                 latest    5a6cbb926327   41 years ago    300MB

$ docker run -d --rm -p 8080:8080 sample-app
51a985b201a34dedca9d9ce18360ec71c4d12cbbc60f88bca3b463ded992e1e4

$ curl -vsS localhost:8080
* Rebuilt URL to: localhost:8080/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: text/html;charset=UTF-8
< Content-Language: en-US
< Transfer-Encoding: chunked
< Date: Wed, 16 Jun 2021 14:33:37 GMT