4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

docker applicationを動かしてみた

Posted at

株式会社日立製作所 研究開発グループ サービスコンピューティング研究部の長沼です。
今回はCloud Native Application Bundles(CNAB)という観点で、実装の1つであるdocker applicationを動かしてみましたので、その内容について紹介します。
CNABの概要については、こちらの記事を参照ください。

docker applicationとは

公式のREADME.mdによれば、
docker CLI Pluginとして動作する、アプリケーションをインストール・共有する仕組みです。
CNAB仕様と互換があり、Composeファイル(docker-compose.yml)から
CNABのinvocation image(アプリケーションをインストールするためのコンテナイメージ、すなわちインストーラ)を作成し、このinvocation imageをコンテナレジストリを用いて共有(配布・再利用)するための機能群を提供するものです。

以降では、この一連の流れを具体的な手順と合わせて説明していきます。

docker applicationの準備

動作環境

今回使用するマシンのOSとdocker、およびdocker-app(docker applicationを実現するコマンド)のversionは以下の通りとなります。

  • ubuntu 18.04 LTS
  • docker
    • client: Docker Engine - Community 19.03.2
    • Server: Docker Engine - Community 19.03.2
  • docker-app: v0.8.0

またアプリケーションを展開するためのプライベートレジストリ(Harbor)と、インストール先として上記マシン上で動作するdocker swarmクラスタ、も準備しておきます。

インストール

まずdocker application(docker-appコマンド)のインストールを以下手順に従い実施していきます。
https://github.com/docker/app#installation

上記で紹介されているようにdocker-appは、スタンドアローンとして利用する方法と、
docker CLI Pluginによりdockerのサブコマンドとして利用する方法があります。
今回は、dockerのサブコマンドとして利用する方法を使う方法で紹介していきます。
具体的には、以下コマンドを実行します。

# docker-appのdownload
$ export OSTYPE="$(uname | tr A-Z a-z)"
$ curl -fsSL --output "/tmp/docker-app-${OSTYPE}.tar.gz" "https://github.com/docker/app/releases/download/v0.8.0/docker-app-${OSTYPE}.tar.gz"
$ tar xf "/tmp/docker-app-${OSTYPE}.tar.gz" -C /tmp/

# docker CLI plugin利用の設定
$ mkdir -p ~/.docker/cli-plugins && cp "/tmp/docker-app-plugin-${OSTYPE}" ~/.docker/cli-plugins/docker-app

appがサブコマンドとして認識されない('app' is not a docker command.などとなる)場合、dockerのexperimentalを有効にすることで解決する場合があります。
例えば、以下を実行します。

$ export DOCKER_CLI_EXPERIMENTAL=enabled

docker applicationの利用

docker applicationを利用する上で必要となる一連の流れとして、

  • invocation imageの元となるコンテンツ開発
  • CNAB invocation imageへのビルド、
  • レジストリへのpush/pull、
  • アプリケーションのインストール
    を以下で紹介していきます。

コンテンツの開発

docker applicationは主に以下の3つのファイルからなります。

  • metadata file (metadata.yml): アプリケーションのバージョンや説明などのメタ情報を記述
  • compose file (docker-compose.yml): アプリケーションで使うイメージやポートなどの構成を記述
  • parameter file (parameters.yml): compose fileに与える変数の定義を記述

以降では、docker applicationの例でも用いられている、指定メッセージを表示する簡単なWebサーバを動作させるアプリケーションの作成を例に挙げ、説明を行っていきます。

まず上記ファイルの雛形をinitコマンドを使って生成します。

$ docker app init hello-message

するとhello-message.dockerappというディレクトリが作成され、3つのファイルの雛形が作成されているのが確認できます。
なおinitコマンドに--single-fileオプションを付けると、この3つのファイルを一つにまとめた1ファイル(今回の場合はhello-message.dockerappというYAMLファイル)
として雛形を出力することもできます。

$ tree hello-message.dockerap
hello-message.dockerapp/
├── metadata.yml
├── parameters.yml
└── docker-compose.yml

この雛形を編集して、実際に動かすアプリケーションに必要な情報へ書き換えを行います。
ここでアプリケーション動作時に変更したい(変数化しておきたい)項目は、parameters.ymlにkey:valueの形式で記述し、docker-compose.yml側で変数${key}として埋め込むことができます。
今回の例では、表示するメッセージ(docker-compose.ymlの${message})と公開ポート(同じく${ports.port1})を変数としています。

metadata.yml
# アプリケーションのバージョン
version: 0.1.2
# アプリケーションの名前
name: hello-message
# アプリケーションの簡単な説明
description: This application returns a hello message for HTTP request.
# アプリケーションやパッケージのメンテナの名前・E-Mail
maintainers:
  - name: maintainer.name
    email: maintainer@email.address
parameters.yml
# docker-compose.ymlの${message}に対応するkeyとvalue(デフォルト値)
message: world 
# keyを階層構造にもできる
ports:
  port1: 5678 
docker-compose.yml
version: "3.3"
services: 
  hello-server:
    image: hashicorp/http-echo
    # ${message}は変数として扱われる
    command: ["-text", "hello ${message}"]
    ports:
      - ${ports.port1}:5678

これら用いて、docker app renderにより変数化部分に値が入ったdocker-composeファイルを生成することもできます。
以下ではメッセージ部分はデフォルト値(parameters.yamlで指定した値)、公開ポート部分は--setオプションで変更した値、で生成したdocker-composeファイルを生成する例を示しています。

$ docker app render --set ports.port1=8080
version: "3.3"
services:
  hello-server:
    command:
    - -text
    - hello world
    image: hashicorp/http-echo
    ports:
    - mode: ingress
      target: 5678
      published: 8080
      protocol: tcp

invocation imageのビルド・レジストリへのpush/pull

invocation imageのビルド

docker app bundleコマンドにより、hello-message.dockerappに対する

# invocation imageのbuild
$ docker app bundle
Invocation image "hello-message:0.1.2-invoc" successfully built

# invocation imageの確認
$ docker images | grep hello-message
hello-message          0.1.2-invoc         fbce87b60497        23 seconds ago      49.1MB

# bundle.jsonの確認
$ls .
bundle.json  docker-compose.yml  metadata.yml  parameters.yml

ちなみに現在のdocker-appの実装では、実はdocker app renderでもCNAB invocation imageのビルドが行われるようです。
変数に値を入れたdocker-composeファイルを生成するにしては処理時間がかかると感じたら、実はイメージのビルドも行っていたんですね。。

作成したinvocation imageの中身

作成したinvocation image(hello-message:0.1.2-invoc)とは、いったいどんなものか気になり、中身をのぞいてみました。

$ docker inspect hello-message:0.1.2-invoc
[
  {
    ...
    "Config": {
     "Hostname": "",
      "Domainname": "",
      "User": "cnab",
      "Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
      "Cmd": [
        "/bin/sh",
        "-c",
        "/cnab/app/run"
      ], ...,
    }, ...
  }
]

から分かるように、invocation image実行時は、イメージ内の/cnab/app/runが起動されるようです。
invocation image内の/cnab内にどのようなものが格納されているかを見てみると、以下のように今回作成したhello-message.dockerappとrunコマンド(バイナリ)が格納されたものであることが確認できました。

# tree /cnab の結果
cnab
└── app
    ├── hello-message.dockerapp
    │   ├── bundle.json
    │   ├── docker-compose.yml
    │   ├── metadata.yml
    │   └── parameters.yml
    └── run

レジストリへのpush・pull

さらに作成したinvocation imageは、レジストリに格納することができます。
これにより、dockerイメージと同じようにレジストリを介し、invocation image(すなわちアプリのインストーラ)を配布・再利用することができるようになります。

以降ではローカルに立てたレジストリ(registry:5000)を介してinvocation imageをpush/pullする例を示しています。
今回はinsecure registryを使ったため、--insecure-registriesオプションを付ける必要がありました。

# レジストリへpush
$ docker app push --insecure-registries registry:5000 --tag registry:5000/hello-message:0.1.2

# レジストリからのpull
$ docker app pull --insecure-registries registry:5000 registry:5000/hello-message:0.1.2

さらにdocker app inspectをpush前後で比較してみると単純なpushではなく、以下のようにアプリケーションのイメージ(hello-serverに対応するimage)
も参照場所が書き換えられていました。
すなわちinvocation imageだけでなく、invocation imageに含まれるアプリのイメージも、今回invocation imageを格納したレジストリへ集約しているようです。

# hello-message.dockerappディレクトリ直下で実行した結果
$ docker app inspect .
hello-message 0.1.2

Maintained by: maintainer.name <maintainer@email.address>

This application returns a hello message for HTTP request.

Service (1)  Replicas Ports Image
-----------  -------- ----- -----
hello-server 1        5678  hashicorp/http-echo

Parameters (2) Value
-------------- -----
message        world
ports.port1    5678

Attachments (7)                                     Size
---------------                                     ----
bundle.json                                         2.345kB
...(略)


# pushしたregistry:5000/hello-message:0.1.2に対して実行するとhello-serverのImage部分が変更されている
$ docker app inspect --insecure-registries registry:5000 registry:5000/hello-message:0.1.2
hello-message 0.1.2

Maintained by: maintainer.name <maintainer@email.address>

This application returns a hello message for HTTP request.

Service (1)  Replicas Ports Image
-----------  -------- ----- -----
hello-server 1        5678  registry:5000/hello-message@sha256:ba27d460cd1f22a1a4331bdf74f4fccbc025552357e8a3249c40ae216275de96

Parameters (2) Value
-------------- -----
message        world
ports.port1    5678

Attachments (7)                                     Size
---------------                                     ----
bundle.json                                         2.345kB
...

アプリの起動

このようにビルドしたinvocation imageは、現状ではdocker swarmとkubernetesへインストール(デプロイ)することができます。
swarmの場合は、以下のようにしてアプリをインストール・確認できます。

# hello-messageのswarmへのインストール
$ docker app install --insecure-registries registry:5000 registry:5000/hello-message:0.1.2

# インストール結果の確認
$ docker app list
INSTALLATION  APPLICATION           LAST ACTION RESULT  CREATED    MODIFIED   REFERENCE
hello-message hello-message (0.1.2) install     success 12 seconds 11 seconds registry:5000/hello-message:0.1.2

# アンインストール
$ docker app uninstall hello-message

kubernetesも、compose-on-kubernetesでAPIを拡張したkubernetesクラスタに対して、--orchestrator kubernetesオプションを付けることでアプリケーションをインストールできるとのことです。
ただ今回準備した環境ではうまく動かすことができず、こちらは引き続き調査などを行っていきたいと思います。

まとめ

今回はdocker-appを使って、コンテンツの準備、CNABのinvocation imageのビルド/push/pull、およびアプリのインストールまでの流れを紹介しました。
これまでの資産として既にdocker-composeファイルで動作するアプリケーションがあり、これをCNAB仕様に従って共有したいようなユースケースには、うまくフィットする気がしました。
特にdocker app pull/pushという、慣れ親しんだdokcerコマンドの使い勝手でinvocation imageを配布/再利用(push/pull)できる仕組みはステキに感じました。
またCNAB向けのレジストリという点ではcnab-to-ociというプロジェクトでも議論されており、こういった周辺動向含め引き続き見ていきたいと思います。

参考資料

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?