新しい Appsody スタックを作成する

Appsody は、クラウド・ネイティブ・アプリケーションの開発を単純化するためのオープンソース・プロジェクトです。Appsody の主要なコンポーネントであるスタック は、一連の事前構成されたテクノロジーと構成が含まれる Docker イメージであり、クラウド環境内にそのままデプロイできます。

スタックを使用することで、アプリケーション開発者 は基礎となるテクノロジー・コンポーネントにも、コンポーネントをビルドして Kubernetes 環境にデプロイする方法にも気を掛けることなく、アプリケーションのコードの作成に集中できます。すでに一般公開されて利用可能なスタックはいくつもありますが、スタック・アーキテクト が自社で使用している一連のテクノロジーとバージョンならびにモニタリング、ロギング、ヘルス・チェックなどに選択したソリューションを反映した独自のスタックを作成することもできます。

このチュートリアルでは、新しい Appsody スタックを作成する手順を説明します。スタック・アーキテクトとして、アプリケーション開発者がアプリケーションを実行、ビルド、デプロイするための基盤として使用できるスタックを作成する方法を学んでください。

新しいスタックを作成する必要があるかどうかわからない場合は、記事「Appsody スタックのカスタマイズ」に目を通してください。新しいスタックを作成すべき場合、既存のスタックを変更すべき場合、あるいはテンプレートを使用すればよい場合を判断する方法がわかります。

前提条件

このチュートリアルの手順を開始する前に、Appsody の概要と仕組みについて理解しておく必要があります。Appsody のドキュメントとブログ記事「Appsody の紹介」を参照して、Appsody の基礎を学んでください。

ローカル・ワークステーション上でスタックをビルドしてテストするには、以下の手順を完了してください。

アプリケーションを Kubernetes サービスにデプロイする場合は、クラスターにアクセスできることも要件となります。

開発プロセスにおけるスタックの役割

特定のテクノロジーまたは開発パターンのセットが必要となるアプリケーションを構築するときに、開発者はスタックを使用してその作業を単純化します。数多くのスタックが一般公開されて利用できるようになっていますが、多くの企業では、自社の開発者がクラウド・ネイティブ・アプリケーションを構築する際の要件と標準に準拠できるようにする企業固有のスタックを築くことを希望します。

新しい Appsody スタックを作成する方法を学ぶ前に、スタックの設計要件を簡単に確認しましょう。スタックは、「Rapid Local Development」モードまたは「Build-and-Deploy」モードのいずれかで開発者をサポートするように設計されています。

Rapid Local Development モード

Rapid Local Development モードでは、開発者がローカル・マシン上で新しいアプリケーションを作成するために必要な要素に加え、ローカルのコンテナー化された Docker 環境内で常時アプリケーションを実行するために必要な要素のすべてがスタックに組み込まれます。(ローカル・マシンのユーザー・スペース内でのみ開発を行うのではなく) アプリケーション開発プロセスを開始する時点からコンテナー化を導入すると、コンテナー化のプロセスで取り込まれる微妙で捉えにくいエラーが減るだけでなく、開発者がアプリケーションのコア・テクノロジー・コンポーネントをインストールする必要もなくなります。

このモードでのスタックの要件は、Docker イメージに事前ビルドされる特定のテクノロジーのすべての依存関係が揃っていること、さらにこれらの依存関係を、開発者がコードに明示的に追加する依存関係で動的に補完することです。

Appsody の Rapid Local Development モードでは、Appsody CLI (必要に応じてローカル IDE に接続されます) が、開発中のアプリケーションを実行するローカル Docker コンテナーと通信します。このモードではアプリケーション・コードがローカル・ファイル・システム上に保持されると同時に、Docker コンテナー内にマウントされるため、ローカルの変更によって自動的にアプリケーションの再起動がトリガーされます。

Build-and-Deploy モード

このモードでは、スタックが Appsody CLI を使用して自己完結型の Docker イメ―ジをビルドできるようにします。ビルドされるイメージには、スタック内のコア・テクノロジーに加え、アプリケーション・コード、そしてコア・テクノロジーとアプリケーション・コード両方の依存関係が組み込まれます。このイメージは手作業でもプログラムによってでも、Docker イメージをサポートする任意のプラットフォーム (ローカルまたはパブリック Kubernetes クラスターなど) にデプロイできます。

以下の図は、アプリケーション開発者がスタックを使用する方法を示しています。

Appsody のフロー

上の開発フロー図で示されているのは手作業による Kubernetes クラスターへのデプロイですが、本番指向の環境では、GitOps でビルド・ステップとデプロイ・ステップをトリガーし、Tekton Pipelines でデプロイを駆動することになるでしょう。Cloud Pak for Applications に含まれる Kabanero の Collections が Appsody のスタック、GitOps、Tekton Pipelines を統合して、エンタープライズ対応のクラウド・ネイティブ・アプリケーションの開発およびデプロイメント・ソリューションを提供します。

スタックの構造

1 つの Appsody スタックで Rapid Local Development モードと Build-and-Deploy モードの両方に対応できることから、すべてのスタックは基準となる構造に従っています。以下に示す構造は、スタックのソース構造を表しています。

my-stack
├── README.md
├── stack.yaml
├── image/
|   ├── config/
|   |   └── app-deploy.yaml
|   ├── project/
|   |   ├── [files that provide the technology components of the stack]
|   |   └── Dockerfile
│   ├── Dockerfile-stack
|   └── LICENSE
└── templates/
    ├── my-template-1/
    |       └── [example files as a starter for the application, e.g. "hello world"]
    └── my-template-2/
            └── [example files as a starter for a more complex application]

スタック・アーキテクト は、上記の構造を作成し、その構造を実際にスタック・イメージに組み込んで、アプリケーション開発者 が新しいアプリケーションを開発するためのベースとして使用できるようにする必要があります。スタック・アーキテクトとしての役割には、アプリケーション開発者が出発点として利用できる 1 つ以上のサンプル・アプリケーション (テンプレート と呼ばれます) をスタックに組み込むことも含まれます。

したがって、スタックを作成する際は、上記の構造を処理し、テンプレートそれぞれの tar ファイルと併せてスタック用の Docker イメージを生成します。このようにすれば、すべてのテンプレートがローカルまたは Appsody リポジトリー内に保管されて参照できるようになります。Appsody CLI でリポジトリーにアクセスし、スタックを使用してローカル開発を開始することができます。

新しいスタックを作成する

新しいスタックを作成するには、まず、上記の構造の scaffold を作成する必要があります。スタックは stableincubating、または experimental として分類されます。これらの分類の詳細については、Appsody のドキュメントを参照してください。Appsody には 2 つのサンプル・スタックが用意されています。一方のサンプル (samples/sample-stack) はスタック構造とファイルからなり、そこに入力できるようになっています。もう一方 (incubator/starter) にはこれらに加え、実際に使用できる最小限のスタックが含まれていて、それをコピーして実行し、新しいスタックの基盤として変更を加えることができます。

このチュートリアルでは、後者のスターター・スタックを使用します。作業をさらに簡単にするために、Appsody CLI では既存のスタックのコピーとして新しいスタックを作成する appsody stack create コマンドがサポートされています。

注: 概して、Appsody は常に既存のリポジトリーを調べてから、ローカル・キャッシュを調べます。スタックの通常の使用法では、まさしくこれが必要な動作ですが、新しいスタックを作成する過程では、当然なことながら、既存のリポジトリーにはその新しいスタックが既知となっていません。したがって、この場合は、Appsody に最初にローカル・キャッシュを調べるよう指示すると時間の短縮になります。このように指示するには、環境変数 export APPSODY_PULL_POLICY=IFNOTPRESENT を使用します。

  1. appsody stack create コマンドを実行して、スターター・スタックをコピーし、名前を変更します。このコマンドにより、スターター・スタックを格納するサブディレクトリーが作成されます。

     $ cd ~
     $ appsody stack create mystack --copy incubator/starter
     $ cd mystack
     $ ls - al
     total 16
     drwxr-xr-x  6 henrynash  staff  192 21 Oct 00:14 .
     drwxr-xr-x  3 henrynash  staff   96 21 Oct 00:14 ..
     -rw-r--r--  1 henrynash  staff  621 21 Oct 00:14 README.md
     drwxr-xr-x  7 henrynash  staff  224 21 Oct 00:14 image
     -rw-r--r--  1 henrynash  staff  297 21 Oct 00:14 stack.yaml
     drwxr-xr-x  3 henrynash  staff   96 21 Oct 00:14 templates
    

    コピーされるスターター・サンプル・スタックは単なる scaffold ではありません。実際にビルドして実行できるスタックです。意図的に多くの処理を行うものにはなっていませんが、Appsody スタックのビルド環境を確実に機能させてから変更を行えるようになっています。

  2. 新しいスタックをビルドします。

    スタックをビルド (つまり パッケージ化) すると、スタック・イメージ (Docker イメージ) が作成されます。Appsody CLI でこのイメージを使用することで、ビルドされたスタックを使用してプロジェクトを開始できます。開始する前に、Docker 環境がセットアップされていることを確認してください。ローカル Docker 環境を使用することをお勧めします。

    コピーしたサンプル・スタック構造内に Docker ファイル (Dockerfile-stack) があります。appsody stack package コマンドはこれを使用してイメージをビルドします。

    このようにして新しいスタックをビルドするには、stacks/mystack ディレクトリーから以下のコマンドを実行します。

     $ appsody stack package
    

    このコマンドにより、Docker ビルドが実行されて、mystack がローカル Appsody リポジトリー (dev.local) にインストールされ、ファイルが適格であることを確認する基本的なテストが実行されます。

    ビルドが完了したら、以下のコマンドを実行して、ローカル・リポジトリー内で使用可能になっていることを確認します。

     $ appsody list dev.local
     REPO             ID       VERSION         TEMPLATES       DESCRIPTION
     dev.local        mystack  0.1.0           *simple         sample stack to help...
    
  3. サンプル・スタックを機能させます。

    サンプル・スタックのコピーをビルドしてインストールした時点で、スタック・アーキテクトとしての役割を遂行していることになります。次は、アプリケーション開発者としてスタックを使ってみます。

    新しいディレクトリーを作成し、この新しい Appsody スタックを使用して初期化します。

     $ mkdir ~/test
     $ cd ~/test
     $ appsody init dev.local/mystack
    

    上記のコードにより、mystack 内のデフォルト・テンプレートに基づくアプリケーション開発フォルダーがセットアップされます。このフォルダーの中身を調べましょう。

     $ ls -al
     drwxr-xr-x   6 henrynash  staff   192 14 Sep 19:52 .
     drwxr-xr-x  41 henrynash  staff  1312 14 Sep 19:52 ..
     -rw-r--r--   1 henrynash  staff    27 14 Sep 19:52 .appsody-config.yaml
     drwxr-xr-x   3 henrynash  staff    96 14 Sep 19:52 .vscode
     -rw-r--r--   1 henrynash  staff    26 14 Sep 19:52 hello.sh
     drwxr-xr-x   3 henrynash  staff    96 14 Sep 19:52 tests
    

    ファイル .appsody-config.yaml はスタックを指しています。hello.sh はスターター・アプリケーションです。スターター・アプリケーションは超シンプルなもので、「Hello from Appsody!」というテキストをエコー出力するだけです。

    appsody run を使用して、コンテナー環境内でスターター・アプリケーションを実行します。

    以下の出力を見るとわかるように、サンプル・スタックは Docker 環境内で稼動するコンテナー内部で単純な hello.sh を正常に実行しました。

     $ appsody run
     Running development environment...
     Running command: docker[pull appsody/mystack:0.1]
     Using local cache for image appsody/mystack:0.1
     Running docker command: docker[run --rm -p 8080:8080 --name test20-dev -v /Users/henrynash/codewind-workspace/test20/:/project/userapp -v test20-deps:/project/deps -v /Users/henrynash/.appsody/appsody-controller:/appsody/appsody-controller -t --entrypoint /appsody/appsody-controller appsody/mystack:0.1 --mode=run]
     [Container] Running: /bin/bash /project/userapp/hello.sh
     [Container] Hello from Appsody!
    

カスタム・スタックを作成する

環境をセットアップしてサンプル・スタックが機能することを確認できたので、次は、スタック・アーキテクト本来の役割として、mystack に変更を加えて実際に目的とするスタックを作成します。

新しいスタックを作成する際は、以下の点を考慮する必要があります。

  • スタックにインストールする必要がある一連のテクノロジーは何か?すべての依存関係がインストールされるようにするにはどうすればよいか?
  • 作成したスタックを使用するアプリケーション開発者にどのようなサンプル・スターター・アプリケーションを提供すればよいか?
  • アプリケーション開発者がアプリケーションを作成するために必要な追加の依存関係をインストールできるようにするにはどうすればよいか?

このチュートリアルでは、アプリケーション開発者が Python HTTP サーバー・ベースのアプリケーションを作成してデプロイするために使用できるスタックを作成する方法を説明します。

上記の質問に答えましょう。まず、Python スタックを構成して、スタックがよく使われている Python Web フレームワーク Flask を使用するようにします。必要なテクノロジーと依存関係をインストールするには、Python パッケージ化ツール pipenv を使用します。スターター・アプリケーションとして、URL /hello に応答するシンプルな「Hello World」を提供します。

必要となる手順の概要を確認してから、1 つずつステップを完了させていきましょう。

  1. 目的のスタック・イメージに合わせて Docker ファイルを変更する: スタックに含まれる Docker ファイルは、実際には 2 つあります。一方の Dockerfile-stack ファイルは、スタック・ソース構造内の mystack/image ディレクトリーに格納されています。Docker はこの Dockerfile-stack ファイルを使用して、Appsody CLI で使用するスタック自体のイメージをビルドします。このステップの一環として、べース・イメージを選択し、Flask をインストールするために pipenv コマンドを組み込みます。また、Appsody Docker 環境変数を適切な値に設定し、必要となるポートを設定します。
  2. スタックを構成するコンポーネントが開発者のアプリケーションとやり取りする形式のアーキテクチャーを決定する: 制御権を握るサーバー・プロセスがあるかどうか、あるいは開発者のアプリケーションが制御権を握るかどうかを考えます。基本的に、通常の Docker コンテナーを作成しているとしたら、何がエントリー・ポイントになるかを考えます。この場合、制御権を握るのは Flask アプリケーションです。開発者が作成しなければならないコードの量を最小限にするには、スタックを使用する開発者がアプリケーションに必要な URL エントリー・ポイントを指定するだけで済むようにスタックを設計します。開発者が指定するエントリー・ポイントをサーバー・コードにして、スタックの一部として提供します。
  3. テンプレート・ディレクトリー内にサンプル Hello World アプリケーションを作成する: 前述のように、Flask で Web 環境を管理して、スタックを使用する開発者が公開するエンドポイントのコードを提供するだけで済むようにします。このステップでは、/hello エンドポイントが含まれる 1 つの Python ファイルを作成します。スタックを使用するアプリケーション開発者はこのファイルを拡張して、実際のアプリケーション内で使用されるすべてのエンドポイントを含めることができます。
  4. 最終的なアプリケーション・イメージに合わせて Docker ファイルを変更する: Docker はスタック・ソース構造内の mystack/image/project ディレクトリーに格納されている 2 つ目の Docker ファイル (Dockerfile) を使用して、最終的なアプリケーション・イメージをビルドします。ビルドされたアプリケーション・イメージには、スタックに含まれるすべてのコンポーネントと開発者が作成したアプリケーションが含まれます。このビルドは Appsody CLI の build コマンドと deploy コマンドによって行われます。この Docker ファイルが、結合された依存関係がこの最終的なイメージにインストールされることを確実にします。

手順の概要を把握したところで、各ステップを詳しく見ていきましょう。

目的のスタック・イメージに合わせて Docker ファイルに変更を加える

スタック・ソース構造内に含まれる Docker ファイルをベースとして使用して、必要な変更を加えます。このファイルに含まれる多数の Appsody 環境変数は、サンプル・スタックの構造に合わせてすでに構成されています。したがって、ゼロから開始する必要はありません。

mystack 内にある mystack/image/Dockerfile-stack に、新しいスタックに応じて必要な変更を加えましょう。

  1. まず、ベース・イメージを選択する必要があります。

    有力候補となるベース・イメージは、標準的な Docker Python イメージです。現在選択されているイメージは RedHat イメージなので、ファイルの先頭に FROM ラベルで定義されている registry.access.redhat.com/ubi7/ubiFROM python:3.7 で置き換えてください。

  2. 該当する Appsody 環境変数を変更します。

    サンプル・スタック内には多数の変数の候補があります。新しいスタックをアプリケーションで実行するだけであれば、変更する必要があるのは appsody run の動作を制御する 3 つの変数だけです。

    サンプル・スタックは特定のテクノロジーに偏っていないため、アプリケーションのサンプルとしてはシェル・スクリプトを使用します。上述の 3 つの変数は、サンプル・スタック内では以下のようになっています。

     ENV APPSODY_RUN="/bin/bash /project/userapp/hello.sh"
     ENV APPSODY_RUN_ON_CHANGE=$APPSODY_RUN
     ENV APPSODY_RUN_KILL=false
    

    これらの変数を目的のスタックに合わせて更新するには、APPSODY_RUN 環境変数を更新する必要があります。Rapid Local Development モードで動作中に appsody run コマンドが実行されると、Appsody は制御をこの変数に渡すためです。通常、この変数に設定する値は、手作業で実行中にメインのテクノロジー・サービスを実行するために使用する任意のコマンドです。Flask の場合は以下のように更新します。

     ENV APPSODY_RUN="python -m flask run --host=0.0.0.0 --port=8080"
    

    Rapid Local Development モードでは、開発者のアプリケーション・ディレクトリー内でソース・ファイルの変更が検出された場合、アプリケーションが再起動されます。このモードでは、git commit を待機するのではなく、ファイルを直接観察してファイルの変更を検出します。再起動時に何か特別な処理を行う必要がある場合、アプリケーションを再起動するコマンドを独自の環境変数 (APPSODY_RUN_ON_CHANGE) に格納します。ただし、Flask の場合は特殊な処理は必要にならないため、この環境変数を変更する必要はありません。

    APPSODY_RUN_KILL は、Appsody が現在実行中のプロセスを強制終了する必要があるかどうかを決定するために使用できます。サンプル・スタックは 1 回限りのシェル・スクリプトを実行するだけなので、この環境変数は false に設定されています。新しいスタックで Appsody に既存の Flask プロセスをキルさせる必要がある場合は、値を true に設定します。

     ENV APPSODY_RUN_KILL=true
    

    以上の更新を行うと、appsody run 環境変数は以下のようになっているはずです。

     ENV APPSODY_RUN="python -m flask run --host=0.0.0.0 --port=8080"
     ENV APPSODY_RUN_ON_CHANGE=$APPSODY_RUN
     ENV APPSODY_RUN_KILL=true
    

    アプリケーションの再起動をトリガーする変更を、どのファイルで観察するかを Appsody に指示するには、APPSODY_WATCH_REGEX 変数を使用します。

    Python スタックの場合は、この変数の値を .py で終わるファイルに設定することになります。

     ENV APPSODY_WATCH_REGEX="^.*.py$"
    

    このチュートリアルの後のほうで、他の環境変数も更新します。参考までに、Appsody のドキュメントにすべての環境変数が記載されています。

  3. Flask モジュールとすべての依存関係がインストールされるようにします。

    環境変数を設定した後は、Flask モジュールとすべての依存関係がインストールされるようにする必要があります。チュートリアルの例では、pipenv を使用して依存関係のリストを作成してから、pip を使用してそれらの依存関係を依存関係ディレクトリーにインストールします。その後、インストールされた依存関係を取得するように Python パスを設定します。

    Python での依存関係を熟知していないとしても心配は要りません。重要な点として知っておくべきことは、必要なテクノロジー・コンポーネントとその依存関係をインストールするコードを Docker ファイル内に提供する必要があることです。

    最後のステップで、Flask にエントリー・ポイント (次のステップで作成するサーバー・コード) を指示します。

    このステップでの作業をすべて行うには、以下の Dockerfile-stack を追加します。追加する場所は、通常、ファイルの終わりのほうに設定されている WORKDIR の後ろです。

     RUN pip install pipenv
     RUN pipenv install flask
     RUN pipenv lock -r > requirements.txt
     RUN python -m pip install -r requirements.txt -t /project/deps
     ENV PYTHONPATH=/project/deps
     ENV FLASK_APP=/project/server/__init__.py
    

Dockerfile-stack に加えた変更を保存します。

開発者のアプリケーションをサポートする、アーキテクチャーのサーバー・サイドを提供する

Docker ファイルを修正した後は、前のステップで参照したサーバー・エントリー・ポイントを提供する必要があります。明確にするために、mystack/project ディレクトリーのサブディレクトリーを使用してサーバー・コードを保持することをお勧めします。そのサブディレクトリー内にファイルを作成して、そこにサーバーを含めます。例えば、カレント・ディレクトリーが mystack に設定されている場合は、以下のコマンドを実行します。

$ mkdir project/server
$ cat <<EOF > project/server/__init__.py
from flask import Flask

app = Flask(__name__)

from userapp import *
EOF

このコードは Flask アプリケーション (app) を起動してから、ユーザーが作成した Python ファイルのすべてをインポートしてサーバーに含めます。サーバー・サイドに必要となる作業はこれだけです!

テンプレート・ディレクトリー内にサンプル Hello World アプリケーションを作成する

次は、単一の URL エンドポイントに応答するだけのサンプル・アプリケーションを作成します。スタックにはいくつでもテンプレートを含めることができます (各テンプレートが templates 内の 1 つのディレクトリーとして表されます)。これらのテンプレートで、開発者が特定のスタックで作成できるアプリケーションの異なるクラスを表すことができます。

コピーしたサンプル・スタックには、simple という名前のテンプレートが 1 つだけ含まれています。初めてサンプル・スタックを実行したときにわかったように、テンプレート内には平凡なアプリケーションとして hello.sh スクリプトが用意されています。

現在カスタマイズしているスタックの mystack/templates/simple ディレクトリー内には、このスクリプトではなく、以下のシンプルな Python アプリケーションを作成します。

$ cat <<EOF > templates/simple/__init__.py
from server import app

@app.route('/hello')
def HelloWorld():
    return 'Hello from Appsody!'
EOF

新しいスタックをビルドして実行する

新しい Python/Flask スタックに最小限必要なサポートを確保しました。このスタックを実行しましょう!

  1. スタック・アーキテクトとしての役割で、stacks/mystack ディレクトリーから前と同じスタック・パッケージ化コマンドを使用して、サンプル・スタック・イメージをビルドします。

     $ appsody stack package
    

    このビルドが成功したら、スタックを実行できます。

  2. 今度はスタックを使用するアプリケーション開発者としての役割で、新しいディレクトリーを作成し、Appsody を使用して再初期化します。以下に例を示します。

     $ mkdir ~/myapp
     $ cd ~/myapp
     $ appsody init dev.local/mystack
    

    新しい Hello World! Python アプリがインストールされたことを確認します。

     $ ls -al
     drwxr-xr-x   9 henrynash  staff   288 16 Sep 00:22 .
     drwxr-xr-x  43 henrynash  staff  1376 16 Sep 00:00 ..
     -rw-r--r--   1 henrynash  staff    27 16 Sep 00:00 .appsody-config.yaml
     drwxr-xr-x   3 henrynash  staff    96 16 Sep 00:00 .vscode
     -rw-r--r--   1 henrynash  staff    96 16 Sep 00:00 __init__.py
     -rw-r--r--   1 henrynash  staff    26 16 Sep 00:00 hello.sh
     drwxr-xr-x   3 henrynash  staff    96 16 Sep 00:00 tests
    

    注: 元の hello.sh はまだスタックから削除していないため、ディレクトリー内に残っています。まだ削除していない理由は、Flask サーバーの TESTDEBUG の手段をまだ追加していないことから、このシェルが引き続き参照されているためです。これらの手段を追加した後は、hello.sh を削除できます。

  3. appsody run を使用してアプリとスタックを実行します。

     $ appsody run
     Running development environment...
     Using local cache for image appsody/mystack:0.1
     Running docker command: docker[run --rm -p 8080:8080 --name myapp-dev -v /Users/henrynash/codewind-workspace/myapp.   /:/project/userapp -v myapp-deps:/project/deps -v /Users/henrynash/.appsody/appsody-controller:/appsody/appsody-controller -t     --entrypoint /appsody/appsody-controller appsody/mystack:0.1 --mode=run]
     [Container] Running: python -m flask run --host=0.0.0.0 --port=8080
     [Container]  * Serving Flask app "/project/server/__init__.py"
     [Container]  * Environment: production
     [Container]    WARNING: This is a development server. Do not use it in a production deployment.
     [Container]    Use a production WSGI server instead.
     [Container]  * Debug mode: off
     [Container]  * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
    

    これで、Flask がアプリケーションを実行するようになりました。公開されたエンドポイントにアクセスすると、以下のレスポンスが返されます。

     $ curl http://0.0.0.0:8080/hello
     Hello from Appsody!
    
  4. Hello World アプリケーションに変更を加えると Appsody によってサーバーが再起動されることも確認できます。例えば、myapp ディレクトリー内にある __init__.py を編集して、/hello URL に対するメッセージ・レスポンスを「Hello again from Appsody!」に変更し、ファイルを保存します。これにより、Flask サーバーが自動的に再起動するはずです。エンドポイントに再度アクセスすると、更新されたメッセージが表示されます。

     $ curl http://0.0.0.0:8080/hello
     Hello again from Appsody!
    

新しいスタックは現在、Rapid Local Development モードで稼動しています。開発者がこのスタックをベースにアプリケーションを作成すると、行った変更が直ちにコンテナー内で反映されるので、変更をテストしながら作業を行うことができます。

基礎となるコンポーネントが実行中になったので、完全なソリューションに仕上げるための変更を加えましょう。具体的には、スタックを以下のもので増補します。

  • Rapid Local Development モードの TEST フェーズと DEBUG フェーズのサポート
  • 開発者のアプリケーションに含まれる依存関係をインクルードするためのサポート
  • appsody build と appsody deploy のサポート
  • このチュートリアルの続きとして提案されている改善

Rapid Local Development モードの TEST フェーズと DEBUG フェーズのサポートを追加する

appsody run を制御する環境変数はすでに構成しました。appsody debugappsody test を制御する同等の変数にも値を入力する必要があります。

DEBUG フェーズのサポート

run モードでの 3 つの変数と同様に、debug モードにも同等の変数があります。サンプル・スタック内では、これらの変数は以下のようになっています。

ENV APPSODY_DEBUG="echo -n \"Debugging \"; /bin/bash /project/userapp/hello.sh"
ENV APPSODY_DEBUG_ON_CHANGE=$APPSODY_DEBUG
ENV APPSODY_DEBUG_KILL=false

Flask スタックでは、Flask をデバッグ・モードで起動しましょう。これにより、エラーが発生した場合に診断情報を入手できます。このように変更するには、以下の手順に従います。

  1. FLASK_ENV 環境変数の値を development に設定します。
  2. APPSODY_DEBUG_ON_CHANGE に必要な変更はありません (run モードでの場合と同じです)。
  3. APPSODY_DEBUG_KILL の値を true に設定します。

以上の変更を加えた後は、デバッグ関連の 3 つの変数は以下のようになっているはずです。

ENV APPSODY_DEBUG="FLASK_ENV=development python -m flask run --host=0.0.0.0 --port=8080"
ENV APPSODY_DEBUG_ON_CHANGE=$APPSODY_DEBUG
ENV APPSODY_DEBUG_KILL=true

stacks/mystack ディレクトリーからスタックを再ビルドします。

$ appsody stack package

appsody debug を実行すると、Flask がデバッガー・モードで起動します。

$ cd ~myapp
$ appsody debug
Running debug environment
Using local cache for image appsody/mystack:0.1
Running docker command: docker[run --rm -p 8080:8080 --name myapp-dev -v /Users/henrynash/codewind-workspace/myapp/:/project/userapp -v myapp-deps:/project/deps -v /Users/henrynash/.appsody/appsody-controller:/appsody/appsody-controller -t --entrypoint /appsody/appsody-controller appsody/mystack:0.1 --mode=debug]
[Container] Running: FLASK_ENV=development python -m flask run --host=0.0.0.0 --port=8080
[Container]  * Serving Flask app "/project/server/__init__.py" (lazy loading)
[Container]  * Environment: development
[Container]  * Debug mode: on
[Container]  * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
[Container]  * Restarting with stat
[Container]  * Debugger is active!
[Container]  * Debugger PIN: 131-015-677

Flask デバッグ・モードの動作を確認するには、myapp 内にある __init__.py にエラーを取り込んで、ブラウザーからエンドポイント http://0.0.0.0:8080/hello にアクセスします。デバッガー情報が表示されるはずです。

TEST フェーズのサポート

Appsody の test モードでは、開発者がアプリケーション用に作成した単体テストを実行できます。実際のテストはスタックに固有であり、通常は単体テスト・フレームワークが起動されます。Python でのフレームワークの一例は、unittest です。これを使用して、/hello エンドポイントにアクセスして戻りデータを確認する、単純な機能テストを作成します。

mystack/templates/simple/tests ディレクトリー内にファイルを作成します。例えば、mystack ディレクトリーから以下のコマンドを実行します。

$ cat <<EOF > templates/simple/tests/test.py
from server import app
import unittest

class ServerTestCase(unittest.TestCase):

    def setUp(self):
        # create a test client
        self.app = app.test_client()
        self.app.testing = True

    def test_hello_endpoint(self):
        result = self.app.get('/hello')
        assert b'Hello' in result.data

if __name__ == '__main__':
    unittest.main()
EOF

この単体テストを実行するように、Dockerfile-stack 内の APPSODY_TEST 変数を更新します。

ENV APPSODY_TEST="python -m unittest discover -s /project/userapp/tests -p *.py"
ENV APPSODY_TEST_ON_CHANGE=$APPSODY_TEST
ENV APPSODY_TEST_KILL=true

スタックを再ビルドして、(古いアプリケーション・ディレクトリーを削除して) 新しいアプリケーション・ディレクトリーを作成し、appsody test を再初期化して実行すると、Flask サーバーが実行中になった後、テストが実行されることを確認できます。

$ cd ~
$ rm -r myapp
$ mkdir myapp
$ cd myapp
$ appsody init dev.local/mystack
$ appsody test
Running test environment
Using local cache for image appsody/mystack:0.1
Running docker command: docker[run --rm -p 8080:8080 --name myapp-dev -v /Users/henrynash/codewind-workspace/myapp/:/project/userapp -v myapp-deps:/project/deps -v /Users/henrynash/.appsody/appsody-controller:/appsody/appsody-controller -t --entrypoint /appsody/appsody-controller appsody/mystack:0.1 --mode=test]
[Container] Running command:  python -m unittest discover -s /project/userapp/tests -p *.py
[Container] .
[Container] ----------------------------------------------------------------------
[Container] Ran 1 test in 0.006s
[Container]
[Container] OK

APPSODY_TEST_ON_CHANGE も設定してあるので、いずれかのファイルを変更するたびにテストが再実行されます。このように、このお膳立てによってテスト駆動開発手法を実践することができます。

開発者のアプリケーションに含まれる依存関係をインクルードするためのサポートを追加する

アプリケーション開発者がコードの依存関係を追加すると、Appsody の実行中にその依存関係が自動的にインクルードされるようにして、開発者がスタック自体を変更しなくても済むようにしなければなりません。

Docker の APPSODY_PREP 変数は、スタック開発者がアプリケーション開発者に依存関係を追加する手段を提供するように意図されています。Appsody は各コマンド (例えば、APPSODY_RUNAPPSODY_DEBUGAPPSODY_TEST など) を実行する前に、この変数を実行します。スタック・アーキテクトに必要とされる作業は、開発者のアプリケーションに追加された新しい依存関係を APPSODY_PREP に取り込むためのコマンド・シーケンスを作成することです。

注: 以前、APPSODY_PREPAPPSODY_INSTALL と呼ばれていましたがこの名称は廃止されました (古いスタックでは、この名前を見かけるかもしれません)。

前に Dockerfile-stack に追加した依存関係のインクルード・コードと同様に、実際に使用する依存関係管理システムはスタックに固有です (例えば、Java の場合は maven を使用します)。

Python の場合、前と同じく pipenv を使用します。pipenv を使用すると、コマンド・ライン上でパッケージを指定することも、カレント・ディレクトリー内で Pipfile を見つけさせることもできます。Pipfile はインストールする必要があるパッケージとそれぞれの依存関係を一覧表示します。

ENV APPSODY_PREP="cd /project/userapp; pipenv lock -r > requirements.txt; python -m pip install --upgrade -r requirements.txt -t /project/deps"

上記の行により、アプリケーション開発者がアプリケーション・ディレクトリー内に Pipfile を用意すると、pipenv がそこに指定された依存関係を /project/deps (ここにはスタック自体のすべてのコンポーネントがすでに格納されています。チュートリアルの前半を参照) 内のパッケージのセットに追加します。Appsody を実行するたびに、Appsody は上記のチェックを行って、新しい依存関係が追加されているかどうかを調べます。

APPSODY_PREP コマンドを更新した後は、スタックを再ビルドする必要があります。これにより、スタックが開発者のアプリケーション内で定義されたすべての依存関係をプルできる状態になります。

この機能をテストしましょう。一例として、アプリケーション・コード内で手の込んだ日付操作を行います。この操作では、スペシャリスト向けライブラリーである Python パッケージ dateutil を使用します (このパッケージはデフォルトでは Python に同梱されていません)。まず、このパッケージを使用するように、myapp ディレクトリー内の Hello World サンプル・コードを更新します。以下に例を示します。

from server import app
from datetime import *
from dateutil.relativedelta import *

@app.route('/hello')
def HelloWorld():
    lastFriday = date.today() + relativedelta(day=31, weekday=FR(-1))
    return 'Hello from Appsody, last Friday of this month is: ' + str(lastFriday)

上記のように更新して (スタックを再ビルドする必要はありません) appsody run を実行すると、このコマンドが失敗します (dateutil がインストールされていないためです)。

そこで、この依存関係を取り込むための Pipfilemyapp 内に追加します。

$ cat <<EOF > Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[packages]
python-dateutil = "*"
EOF

appsody run を実行すると、サーバーが問題なく起動するはずです。/hello エンドポイントにアクセスすると、以下の出力が表示されます。

$ curl http://0.0.0.0:8080/hello
Hello from Appsody, last Friday of this month is: 2019-09-27

これで、スタックを変更しなくても、開発者が独自のパッケージと任意の依存関係をアプリケーションに追加できるようになりました。

このチュートリアルでは Python と pipenv を使用しましたが、スタックのテクノロジー基盤に適切なものであれば、どのパッケージ管理ツールでも使用することができます。どのパッケージ管理ツールを使用するのでも、原則は同じです。 つまり、開発者が依存関係を追加すると、スタックを再ビルドしなくてもスタックが動的にその依存関係を取り込みます。

インストールされた依存関係をキャッシュに入れる

まだ明らかになっていないかもしれませんが、Appsody では、実行後に新しくインストールされた依存関係を、次の実行時までキャッシュに入れておくことができます (実行後から次の実行までのサイクル時間を加速するため)。Appsody は依存関係をキャッシュに入れるために、Docker ボリュームを作成し、appsody run/debug/test によって作成されたランタイム環境内にそのボリュームをマウントします。Docker ボリュームは、どのコンテナー・インスタンスからも独立しています。

サンプル・スタックでは、Dockerfile-stack 内の既存の行によってこのキャッシュがすでに構成されています。

ENV APPSODY_DEPS=/project/deps

Dockerfile-stack に追加した Docker コマンドは、インストールするすべてのパッケージを /project/deps 内に配置します。実際のイベント・シーケンスは以下のとおりです。

  1. スタックのビルド時に、Dockerfile-stack に追加したコマンドによって一連のパッケージ (およびその依存関係) が /project/deps に書き込まれます。
  2. appsody run/debug/test を実行すると、Appsody は Docker に対し、APPSODY_DEPS に設定された場所にマッピングされた、{project_name}-dev (このサンプル・プロジェクトでは myapp-dev) という名前のボリュームを作成するよう指示します。Docker ボリュームのセマンティクスでは、/project/deps はすでにスタック・イメージ内に含まれているため、その内容を使用してボリュームが初期化されることになります。
  3. 後続の /project/deps への書き込み (つまり、APPSODY_PREP で定義された、開発者のアプリケーション内で作成された依存関係が追加されること) により、ボリューム は更新されます (したがって、そのコンテンツがその後の実行で可視になります)。ただし、/project/deps の基礎となるスタック・ディレクトリーは影響されません。したがって、以降の appsody build/deploy コマンドでは、スタック・イメージから /project/deps にアクセスすることによって、スタック単独の依存関係を参照できます (このことは以降のセクションで確認できます)。

appsody build と appsody deploy のサポートを追加する

ある時点で、アプリケーション開発者は Rapid Local Development モードを卒業し、完成したアプリケーションを実際にビルドして (作成したコードとスタックのコードの両方が結合された単一のイメージとして) Docker/Kubernetes 環境にデプロイしようと決意します。ビルドとデプロイを可能にするには、スタックに以下のものも含まれている必要があります。

  • 2 つ目の Dockerfile。Appsody がこの結合されたイメージをビルドするために使用します。
  • デプロイメント・マニフェスト・テンプレート。Appsody がイメージをデプロイするために使用します。

appsody build のサポート

スタンドアロンの最終イメージのビルドをサポートするには、Dockerfile をスタックに追加する必要があります。この Dockerfile ファイルの内容を調べる前に、Appsody ビルド・プロセスの仕組みを確認しましょう。

appsody build コマンドを実行すると、以下の処理が行われます。

  • スタック・イメージからローカルの場所 (通常は ~/.appsody/extract/{project_name}-dev) にファイル・システムのコンテンツを抽出します。
  • この抽出したコンテンツに開発者のアプリケーションを追加して APPSODY_MOUNTS に一致するディレクトリー (この例では /project/userapp) に抽出します。
  • この抽出されたディレクトリー構造に対し、/project 内の Dockerfile を使用して Docker ビルドを実行します。

参考のために、最初の 2 つのステップが行われて Appsody が Docker を使用しようとする時点で、抽出された構造は以下のようになっています。

$ ls -al ~/.appsody/extract/myapp
total 48
drwxr-xr-x  10 henrynash  staff   320 20 Sep 22:55 .
drwxr-xr-x  19 henrynash  staff   608 20 Sep 22:55 ..
-rw-r--r--   1 henrynash  staff    32 13 Sep 17:38 .dockerignore
-rw-r--r--   1 henrynash  staff   578 20 Sep 10:49 Dockerfile
-rw-r--r--   1 henrynash  staff   150 20 Sep 10:50 Pipfile
-rw-r--r--   1 henrynash  staff  4566 20 Sep 10:50 Pipfile.lock
drwxr-xr-x  15 henrynash  staff   480 20 Sep 10:50 deps
-rw-r--r--   1 henrynash  staff   121 20 Sep 10:50 requirements.txt
drwxr-xr-x   3 henrynash  staff    96 16 Sep 14:54 server
drwxr-xr-x   8 henrynash  staff   256 20 Sep 22:55 userapp

deps ディレクトリーにはスタック自体の依存関係 (開発者のアプリケーションによって追加された依存関係を除く) が格納され、アプリケーション・ディレクトリー (この例では myapp) のコンテンツは userapp 内にあることに注意してください。

上記の構造を踏まえると、最終的なアプリケーション・イメージのための Dockerfile 内に何を書き込む必要があるのかわかります。

サンプル・スタックにあらかじめ組み込まれている必要最小限の Dockerfile (スタック・ソース構造内の mystack/image/project に格納されています) は以下のような内容になっています。

FROM registry.access.redhat.com/ubi7/ubi

WORKDIR /project

COPY . ./

EXPOSE 8080

CMD ["/bin/bash",  "/project/userapp/hello.sh"]

この Dockerfile を以下のように変更します。

  • 開発者のアプリケーションに必要な依存関係 (基本的に、Dockerfile-stack 内の APPSODY_PREP に含まれていたコマンド) を追加します
  • Python パスと FLASK_APP 変数 (同じく Dockerfile-stack に含まれていたもの) を追加します。
  • サーバー・アプリケーションに直接制御を渡します。最終的なアプリケーション・イメージには Appsody コントローラーは組み込まれません。

以上のように Dockerfile を変更すると、以下のような内容になります。

FROM python:3.7

RUN pip install pipenv

WORKDIR /project
COPY . ./

WORKDIR /project/userapp
RUN pipenv lock -r > requirements.txt
RUN python -m pip install --upgrade -r requirements.txt -t /project/deps
WORKDIR /project

ENV PYTHONPATH=/project/deps
ENV FLASK_APP=server/__init__.py

EXPOSE 8080
CMD ["python", "-m", "flask", "run", "--host=0.0.0.0", "--port=8080"]

これらの変更を加えた上でスタックを再ビルドした後、アプリケーション開発者としてアプリケーション・ディレクトリー (myapp) 内から appsody build を実行すると、myapp という名前の Docker イメージがビルドされます。この Docker イメージは、アプリケーションとスタックの両方を含むスタンドアロンのイメージです!早速、試してみましょう。通常のイメージなので、ローカル Docker 環境内で実行できます (公開されているポートをマッピングしてください)。つまり、以下のコマンドを実行します。

$ docker run -p 8080:8080 myapp
Serving Flask app "server/__init__.py"
Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
Debug mode: off
Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)

前と同じく、選択されているエンドポイント http://0.0.0.0:8080/hello にアクセスすると、通常のレスポンスが返されます。完全なイメージがビルドされたので、これを任意の Docker または Kubernetes プラットフォームにデプロイできます。

appsody deploy のサポート

最後のデプロイ段階に役立つように、Appsody ではスタック・アーキテクトがデプロイメント・マニフェストを提供できるようになっています。Appsody はこのマニフェストをテンプレートとして使用して、最終的なアプリケーション・イメージをデプロイします。

デフォルトのデプロイメントでは Appsody Operator が使用されます。既存の Operator がない場合は、Appsody CLI によって Kubernetes クラスターにインストールされます。Appsody Operator についての詳しい説明はこのチュートリアルの範囲外ですが、このユーザー・ガイドで詳細を確認できます。

Operator を使用することから、デプロイメント・マニフェストは実際のところ、kind が AppsodyApplication の Kubernetes カスタム・リソース (CR)です。同じスタックのテンプレート (mystack/image/config/app-deploy.yaml 内にあります) は、以下のような内容になっています。

apiVersion: appsody.dev/v1beta1
kind: AppsodyApplication
metadata:
  name: APPSODY_PROJECT_NAME
spec:
  version: 1.0.0
  applicationImage: APPSODY_DOCKER_IMAGE
  stack: APPSODY_STACK
  service:
    type: NodePort
    port: APPSODY_PORT
  expose: true

appsody deploy を実行すると、Appsody CLI が CR 内の各種の変数に、スタックに関連する実際の値を代入します。スタック・アーキテクトとして嬉しいことに、上記のサンプルは有効であり、新しいスタックでも機能します。

デプロイする前にいったん手を休めて、Appsody Operator がどこからアプリケーション・イメージをプルするのか、そしてさらに重要なことに、Appsody Operator にプルするために必要な資格情報があるのかどうかを考えてください。Kubernetes スタックと Docker 環境の両方をローカルで (例えば、Docker Desktop for Mac を使用して) 実行していれば、問題はありません (Docker Desktop Kubernetes クラスターはローカル Docker レジストリーにアクセスできるため)。

一方、クラウド・ベースのクラスターにデプロイするとなると、クラスターはローカル Docker レジストリーにアクセスできないため、2 つのことを行う必要があります。

  • 適切でアクセス可能な Docker レジストリーを判断します (docker.io のアカウントを持っているとしたら、当然それを使用することになります)。デプロイ・プロセスに対し、最初にそのレジストリーにイメージをプッシュして、生成後のデプロイ CR バージョンでそのレジストリー内のイメージを参照するように指示します。
  • 選択したレジストリーからイメージをプルするために資格情報が必要な場合は、デプロイ CR に資格情報っを追加する必要もあります。

ローカル Docker インスタンスを実行する場合

ローカルで実行している場合、アプリケーション・ディレクトリー内から appsody deploy を実行するだけで、アプリケーション・イメージがビルドされてデフォルトの Docker レジストリーにプッシュされ、最終的なデプロイメント CR が作成されて Kubernetes クラスターに適用されます。これにより、マッピングしたポートを使用してアプリケーションにアクセスできるようになります。以下に一例を示します。

$ appsody deploy
...
...
Deployed project running at http://localhost:32351

リモート Docker レジストリーを使用する場合

一方、リモート Docker レジストリー (ただし、イメージのプルに資格情報を必要としないレジストリー) を使用する場合は、いくつかのオプションをデプロイに渡し、レジストリーとイメージの名前を指定して、最初にそのレジストリーにイメージをプッシュするように指示します。以下に例を示します。

$ appsody deploy -t docker.io/henrynash/myapp --push

資格情報を必要とするリモート Docker レジストリーを使用する場合

Appsody Operator がイメージをプッシュする際に資格情報を提供しなければならないレジストリーを使用する場合、デプロイ CR に変更を加えることによって資格情報を提供できます。通常、資格情報が含まれるクラスター内にはシークレットがすでに格納されているはずです。そのシークレットを参照するには、 pullSecret 属性を CR に追加します。Appsody Operator は CR を処理するときに、この属性を取得して使用します。

実際には Appsody はデプロイ・フェーズの間、変更後の (つまり、値が代入された) CR をアプリケーション・ディレクトリー内に格納します。CR がクラスターに適用される前にこれを修正するには、Appsody に対し、CR を生成した後にデプロイしないよう指示します。

$ appsody deploy --generate-only
$ cat app-deploy.yaml
apiVersion: appsody.dev/v1beta1
kind: AppsodyApplication
metadata:
  name: myapp
spec:
  version: 1.0.0
  applicationImage: myapp
  stack: mystack
  service:
    type: NodePort
    port: 8080

これで、pullSecrets 属性が spec に追加されます。

apiVersion: appsody.dev/v1beta1
kind: AppsodyApplication
metadata:
  name: myapp
spec:
  version: 1.0.0
  applicationImage: myapp
  stack: mystack
  service:
    type: NodePort
    port: 8080
  pullSecret: mysecret

上記の属性が追加された後は、デプロイ・ステップを通常どおりに実行できます。

$ appsody deploy -t docker.io/henrynash/myapp --push

どの類のデプロイを実施するかに関わらず、アプリケーション・イメージが実行中になります。これを確認するには、前と同じくエンドポイントにアクセスします。

$ curl http://localhost:32351/hello
Hello from Appsody, last Friday of this month is: 2019-09-27

新しいスタックの開発とテストが完了しました!

このチュートリアルの続きとして提案されている改善

実際に機能するスタックを作成した後は、本番環境での使用に向けて、さまざまな方法でスタックを強化できます。

すべてのアプリケーションに使用させる基準のエンドポイントを追加する

スタックの利点の 1 つは、スタックでビルドされたすべてのアプリケーションに継承させる機能を実装できることです。HTTP エンドポイントを提供するスタックでは、一般的にこの利点を生かして、業界標準の /live/health などの URL を実装します。スタック自体にこのようなエンドポイントを実装することで、そのスタックでビルドされたすべてのアプリケーションでこれらのエンドポイントが自動的に有効にされます。例えば /live liveness エンドポイントを追加するには、以下のように project/server/__init__.py ファイルを更新してこのエンドポイントに対するレスポンスを含めます。

from flask import Flask, jsonify

app = Flask(__name__)

from userapp import *

@app.route('/live')
def Liveness():
    state = {"status": "UP"}
    return jsonify(state)

上記のように変更して、前と同じく appsody stack package を使用してスタックを再パッケージ化した後、myapp ディレクトリー内で例えば appsody run を実行すると、新しいエンドポイントが有効になっていることを確認できます。

$ curl http://0.0.0.0:8080/live
{"status":"UP"}

スタック・アーキテクトは、開発者がスタックを使用して作成したすべてのアプリケーションに基準として定義したエンドポイントが含まれていることを確認する方法を知っていなければなりません。

README とその他のスタック識別ファイルを揃える

スタックの公開に向けて重要となるファイルには、以下があります。

  1. README。このファイルで、アプリケーション開発者にスタックの使用方法に関する情報を提供します。例えば、モニタリングまたはヘルス・チェック用に含めたエンドポイントの詳細や、特殊なデバッグの詳細などの情報です。

  2. stack.yaml。スタックのメタデータ (使用されている言語、バージョン、保守担当者の連絡先詳細など) を提供するために、このファイルを含めます。

  3. image/LICENSE。スタックを使用する際に適用されるライセンスを指定するために、このファイルを含めます。

最小権限の原則に従ってアプリケーションが実行されるようにする

このチュートリアルで作成したスタックは、すべての処理を root として実行します。有効な原則として、可能な限り、最小限必要な権限でアプリケーションを実行してください。選択したベース・イメージにテクノロジーのユーザーがすでに作成されていることもありますが、ユーザーは Docker コマンドを使用して追加できます。その場合、Docker の USER コマンドを利用して、選択したユーザーとしてアプリケーションを実行できます。

コンポーネントのバージョンを固定する

このチュートリアルで Dockerfiles 内に flask パッケージを指定したときに、バージョンを指定しませんでした。つまり、単純に最新バージョンを受け入れることになります。この使い方は間違っていませんが、本来スタック・アーキテクトとしては、このような制限のないインストールが問題の原因になる可能性があるかどうかを考えなければなりません。

具体的に言うと、スタックを作成した時点 (および /image/Dockerfile-stack のコンテンツが処理された時点) とスタックを使用してアプリケーションがビルドされる時点 (/image/project/Dockerfile が処理される時点) の間には時間差があります。この時間差が数か月ともなると、アプリケーションのビルド時にプルするパッケージと依存関係が、スタックを作成したときにテストしたものより新しくなっている可能性は大いにあります。

したがって、通常はパッケージ・バージョンを既知の有効なバージョンに固定することをお勧めします。例えば、このチュートリアルで作成したスタックでは、RUN pipenv install flask=="1.1.1" と指定するべきでしょう。

まとめと次のステップ

このチュートリアルから明らかなように、Appsody は以下の点で役立ちます。

  • スタック・アーキテクト は、特定のクラスのアプリケーションを対象に、一連のテクノロジー/バージョンに加えて、モニタリング/ロギング/ヘルス・チェック用に選択したソリューションを定義して、スタックを作成することができます。
  • アプリケーション開発者 がこれらのスタックを使用すれば、関連するテクノロジーをインストールまたは構成する方法についても、それらのテクノロジーの具体的なデプロイメント要件についても知る必要なく、アプリケーションの作成を開始できます。

スタック・アーキテクトとして新しいスタックの作成方法を理解した今、任意の言語でスタックの作成に取り掛かってください。Appsody オープンソース・プロジェクトに新しく作成する特定の言語/テクノロジーのスタックがなければ、完成したスタックをこのプロジェクトに提出するのも一考です。