Skip to content

About

Cloud NativeなImage事情

従来、container runtimeはDockerがデファクトスタンダードでした。

最近のCloud Nativeなcontainer runtime事情としては、 Container Runtime のページで記載した通り、container runtimeはHigh Level Container RuntimeLow Level Container Runtime で役割を分離しています。 Low Level Container Runtime はdaemon serviceではなくバイナリで提供され、High Level Container Runtime から実行されます。Low Level Container RuntimeOCI(Open Container Initiative)に準拠した config.json に生成すべきコンテナのメタ情報が書かれているのでそれを基にコンテナを生成します。

この辺りの話は以下ページなどがわかりやすかったです。

このcontainer runtimeの話はconfig.jsonに書かれている情報を基にコンテナを生成するための仕組みです。コンテナ情報をポータブルに持ち出せる状態(OCI imageと言われますが実態はtar archive)として保存する仕組みはCRI(のHigh Level Container Runtime)として標準実装ではないため別途考慮する必要があります。(例えば、cri-oではimage buildを非サポートだったりします)

OCI imageのLayoutについての公式リファレンスは以下です。

Cloud Native Buildpacksとは

Cloud Native Buildpacks はアプリケーションのソースコードをDockerfileなしでOCI準拠のimageとしてbuildするためのツールです。

元々は Buildpacks という名前でHerokuが内製ツールとして作ったものですが、2018年に CNCF Project として公開されました。 Herokuのツール名と見分けるため、 Cloud Native Buildpacks(CNB) と表現されることが多いようです。

アプリケーションのソースコードが配置されているディレクトリで Builderと呼ばれるbuildpackやbuild image, run imageを組み合わせたcomponentを指定して pack build コマンドを実行することでOCI準拠のimageをbuildできます。build時の処理は Detect phaseBuild phase があります。

(余談) pack build コマンドで --buildpack オプションを指定することでbuilderに含まれないbuildpackを指定することも可能

  1. Detect phase
  2. Build phase

Builder は独自に作成することも可能ですが、Paketo Buildpacks のようなコミュニティが提供するBuilderやBuildpackを利用することも可能です。

pack builder suggest コマンドを実行したところ、Google, Heroku, Paketo Buildpacks がsuggestされました。

$ pack builder suggest
Suggested builders:
        Google:                gcr.io/buildpacks/builder:v1      Ubuntu 18 base image with buildpacks for .NET, Go, Java, Node.js, and Python
        Heroku:                heroku/builder:22                 Base builder for Heroku-22 stack, based on ubuntu:22.04 base image
        Heroku:                heroku/buildpacks:20              Base builder for Heroku-20 stack, based on ubuntu:20.04 base image
        Paketo Buildpacks:     paketobuildpacks/builder:base     Ubuntu bionic base image with buildpacks for Java, .NET Core, NodeJS, Go, Python, Ruby, Apache HTTPD, NGINX and Procfile
        Paketo Buildpacks:     paketobuildpacks/builder:full     Ubuntu bionic base image with buildpacks for Java, .NET Core, NodeJS, Go, Python, PHP, Ruby, Apache HTTPD, NGINX and Procfile
        Paketo Buildpacks:     paketobuildpacks/builder:tiny     Tiny base image (bionic build image, distroless-like run image) with buildpacks for Java, Java Native Image and Go

Tip: Learn more about a specific builder with:
        pack builder inspect <builder-image>

Components

Builder

Buildpack

Stack

  • https://buildpacks.io/docs/concepts/components/stack/

    • build imagerun image で構成されます
      • build image とはlifecycle(及びそれによるbuildpack) が実行されるコンテナ環境のbase image
      • run image とはapplication imageをbuildするためのbase image
  • https://buildpacks.io/docs/operator-guide/create-a-stack/

    • custom stackを作成するにはbuild imagerun imageをcustom imageとして用意します
      1. common base imageの作成
      2. run imageの作成
      3. build imageの作成
    • Buildpack の stackで使用するimageは以下設定が必要です

      1. io.buildpacks.stack.id Label
      2. 環境変数

        • CNB_USER_ID
        • CNB_GROUP_ID
        • CNB_STACK_ID

        e.g. Dockerfile
        # 1. Set a common base
        FROM ubuntu:bionic as base
        
        # 2. Set required CNB information
        ENV CNB_USER_ID=1000
        ENV CNB_GROUP_ID=1000
        ENV CNB_STACK_ID="io.buildpacks.samples.stacks.bionic"
        LABEL io.buildpacks.stack.id="io.buildpacks.samples.stacks.bionic"
        
        # 3. Create the user
        RUN groupadd cnb --gid ${CNB_GROUP_ID} && \
          useradd --uid ${CNB_USER_ID} --gid ${CNB_GROUP_ID} -m -s /bin/bash cnb
        
        # 4. Install common packages
        RUN apt-get update && \
          apt-get install -y xz-utils ca-certificates && \
          rm -rf /var/lib/apt/lists/*
        
        # 5. Start a new run stage
        FROM base as run
        
        # 6. Set user and group (as declared in base image)
        USER ${CNB_USER_ID}:${CNB_GROUP_ID}
        
        # 7. Start a new build stage
        FROM base as build
        
        # 8. Install packages that we want to make available at build time
        RUN apt-get update && \
          apt-get install -y git wget jq && \
          rm -rf /var/lib/apt/lists/* && \
          wget https://github.com/sclevine/yj/releases/download/v5.0.0/yj-linux -O /usr/local/bin/yj && \
          chmod +x /usr/local/bin/yj
        
        # ========== ADDED ===========
        # 9. Set user and group (as declared in base image)
        USER ${CNB_USER_ID}:${CNB_GROUP_ID}
        

        docker build . -t cnbs/sample-stack-build:bionic --target build
        
    • io.buildpacks.stack.id ラベルを設定したimageをbuilderで指定します

      e.g. builder.toml
      [[buildpacks]]
        # ...
      
      [[order]]
        # ...
      
      [stack]
        id = "com.example.stack"
        build-image = "example/build"
        run-image = "example/run"
        run-image-mirrors = ["gcr.io/example/run", "registry.example.com/example/run"]
      

Buildpack Group

  • https://buildpacks.io/docs/concepts/components/buildpack-group/
    • 実行する順番に定義されたBuildpackのリストです。 Buildpack はモジュール化されているため再利用が可能でBuildpack Group で複数のBuildpackを接続することが可能です。
    • buildpack.toml で他Buildpackを指定している例

      • samples/hello-worldsamples/hello-moon Buildpackを持つ samples/hello-universe Buildpack Group

        • https://github.com/buildpacks/samples/blob/main/buildpacks/hello-universe/buildpack.toml
          buildpack.toml
          # Buildpack API version
          api = "0.2"
          
          # Buildpack ID and metadata
          [buildpack]
          id = "samples/hello-universe"
          version = "0.0.1"
          name = "Hello Universe Buildpack"
          homepage = "https://github.com/buildpacks/samples/tree/main/buildpacks/hello-universe"
          
          # Order used for detection
          [[order]]
          [[order.group]]
          id = "samples/hello-world"
          version = "0.0.1"
          
          [[order.group]]
          id = "samples/hello-moon"
          version = "0.0.1"
          
      • Builder から [[buildpacks]]samples/hello-universe Buildpack Groupを指定することでsamples/hello-worldsamples/hello-moon Buildpackを利用できる

        • https://buildpacks.io/docs/operator-guide/create-a-builder/#1-builder-configuration
        • [[order]] > [[order.group]] に並んでいる順番にdetect/buildが実行される
          builder.toml
          # Buildpacks to include in builder
          [[buildpacks]]
          uri = "samples/buildpacks/hello-processes"
          
          [[buildpacks]]
          # Packaged buildpacks to include in builder;
          # the "hello-universe" package contains the "hello-world" and "hello-moon" buildpacks
          uri = "docker://cnbs/sample-package:hello-universe"
          
          # Order used for detection
          [[order]]
              # This buildpack will display build-time information (as a dependency)
              [[order.group]]
              id = "samples/hello-world"
              version = "0.0.1"
          
              # This buildpack will display build-time information (as a dependant)
              [[order.group]]
              id = "samples/hello-moon"
              version = "0.0.1"
          
              # This buildpack will create a process type "sys-info" to display runtime information
              [[order.group]]
              id = "samples/hello-processes"
              version = "0.0.1"
          
          # Stack that will be used by the builder
          [stack]
          id = "io.buildpacks.samples.stacks.bionic"
          # This image is used at runtime
          run-image = "cnbs/sample-stack-run:bionic"
          # This image is used at build-time
          build-image = "cnbs/sample-stack-build:bionic"
          

Lifecycle

1. Analyze
2. Detect
3. Restore
4. Build
5. Export
6. Create
7. Launch
8. Rebase

Platform