DockerとGKEでWebアプリをデプロイ🐳

はじめに

本記事ではDockerとGKE(Google Kubernetes Engine)の入門としてWebアプリケーションのデプロイをおこないます。はじめにDockerとGKEについて簡単に説明したあとに、Googleの公式チュートリアルに沿って実装をします。

Docker

Dockerは仮想化技術のひとつで、VM(Virtual Machine)と比較されることが多いです。VMはホストPC上に仮想化ソフトウェアをインストールし、ソフトウェア上でホストPCのOSと完全に分離したOS(ゲストOS)を管理するものです。VMに対してDockerは、ホストPCのOS上で「コンテナ」という仮想的な区画を作成・管理します。コンテナはホストPCのOSのカーネルを利用します。そのため、

  • ゲストOSを立ち上げる必要がなく、消費するリソースが少ない
  • 複数コンテナ間で同じカーネルを共有することができる
  • 起動が早い

等の利点があります。
また、Dockerを使えばアプリケーションを「コンテナ」にパッケージングして、デプロイ・実行がすることができます。具体的にはコンテナを作る際に「Dockerfile」というファイルにアプリケーションを動かすために必要なOS、ライブラリや環境変数などを記述し、そのファイルを使ってコンテナを作成します。さらに、Dockerfileから作成したコンテナはDockerイメージとして簡単に共有することができます。そのため、

  • インフラをコード化できる
  • コンテナごとデプロイすれば、「ローカルで動いたのにデプロイしたら動かなかった・・・」というような悲しいことが起きない
  • 環境の共有が容易

といった利点もあります。

GKEとKubernetes

KubernetesはDockerなどのコンテナ仮想化ソフトウェアを管理やデプロイをするためのOSS(オープンソースソフトウェア)です。細かい説明は割愛しますが、複数のコンテナを連携させることでアプリケーションのスケーリングや管理を最適に自動化してくれます。
Kubernetesで複数のコンテナを管理している最上位階層を「クラスタ」といいます。
また、Kubernetesの活用として、「Kubeflow」があります。Kubeflowはモデルの作成・学習・検証、ワークフロー構築、モデルサービングといった機械学習サービス運用におけるタスクをKubernetes上で実行するためのOSSです。そしてGKEはGoogle のインフラストラクチャを使用してKubernetesを使用できるGCP(Google Cloud Platform)のサービスのひとつです。GKEやKubernetesを活用することで、MLOpsの効率化を図ることができます。

作業環境

  • Python 3.7.3
  • Mac OS X 10.14.6
  • Docker 20.10.5
    • インストール方法はOSによって異なるためこちらの記事などを参考になるかと思います

実装

Webアプリケーションのコンテナ化

Dockerfile→Dockerイメージを作成する

デプロイしたいアプリケーションをコンテナ化するためにDockerfileを作成します。以下のは文章のポジネガ判定をするようなモデルをAPI化したい場合のDockerfileの例です。

# ubuntuの最新のイメージを使う
FROM ubuntu:latest
# mecabやその他必要なものの導入
RUN apt-get update \
    && apt-get install -y mecab \
    && apt-get install -y libmecab-dev \
    && apt-get install -y mecab-ipadic-utf8 \
    && apt-get install -y git \
    && apt-get install -y make \
    && apt-get install -y curl \
    && apt-get install -y xz-utils \
    && apt-get install -y file \
    && apt-get install -y sudo \
    && apt-get install -y python3.7 \
    && apt-get install -y python3-pip
# neologdをダウンロードしてくる
RUN git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git \
    && cd mecab-ipadic-neologd \
    && bin/install-mecab-ipadic-neologd -n -y
# mecabのデフォルトの辞書を変更する
RUN echo "dicdir=/usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd">/etc/mecabrc
# アプリケーションのコードを置くディレクトリに移動
WORKDIR /app
# ローカルのファイルをコンテナに乗せる
ADD . /app/
# requirements.txtにあるパッケージをインストール, pytorchはubuntu用のインストールを実行する
RUN pip3 install --upgrade pip && \
  pip3 install -r requirements.txt && \
  pip3 install torch==1.8.1+cpu -f https://download.pytorch.org/whl/torch_stable.html
# 80番ポートを開けておく
EXPOSE 80
# サーバを立ち上げる
CMD uvicorn main:app --host 0.0.0.0 --port 80

この例ではubuntuのイメージをベースに、形態素解析器や、その他必要なパッケージをインストールしています。また、コンテナ外からのアクセスを許可するポートを指定しています。
Dockerfileができたら、「gke-tutorial-image」という名前でDockerイメージを作成します。

export PROJECT_ID=project-id
docker build -t gcr.io/${PROJECT_ID}/gke-tutorial-image:v1 .

project-idはご自身のGCPのプロジェクトIDに差し替えてください。
「:v1」はコンテナのバージョンを管理するためのタグで、省略可能です。
以下のコマンドを実行して、ビルドできたことを確認します。

docker images

出力

REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
gcr.io/my-project/gke-tutorial-image    v1                  25cfadb1bf28        10 seconds ago      54 MB

コンテナを実行して作成したイメージをテストする

作成したイメージをローカルでテストしてみます。
Dockerfileに80番ポートを開けるように指定したので、コンテナ内の80番ポートにローカルの80番ポートからアクセスできるように指定します。

docker run --rm -p 80:80 gcr.io/${PROJECT_ID}/gke-tutorial-image:v1

上記のコマンドを実行するとコンテナが実行されるので、「http://localhost:80」に任意のリクエスト(POSTやGET)を送ってみて、期待されるレスポンスがあれば成功です

コンテナをGCR(Google Container Registry)にプッシュする

作成したイメージをGKEで扱えるようにするために、Googleが提供しているコンテナレジストリであるGCRにイメージをアップロードします。
まず、作業中のプロジェクトの Container Registry API を有効にします。

gcloud services enable containerregistry.googleapis.com

次にGCRへの認証をおこないます。

gcloud auth configure-docker

認証ができたらDockerイメージをアップロードします。

docker push gcr.io/${PROJECT_ID}/gke-tutorial-image:v1

アップロードができているか確認します。

gcloud container images list

出力

gcr.io/${PROJECT_ID}/gke-tutorial-image

コンテナ化したアプリケーションをGKEでデプロイする

Googleの公式のチュートリアルでは以降GUIでの操作とCUIでの操作で手順が別れています。CUIの方が丁寧に説明されているような気がするので、本記事ではGUIの操作の説明を書いていきます。

GKEクラスタの作成

まず、コンテナを管理するための基盤であるクラスタを作成していきます。

  1. Cloud ConsoleでGoogle Kubernetes Engineのメニューに移動する
    GKE-cluster-1
  2. 「作成」を選択して新規クラスタを作成する
    GKE-cluster-2
  3. 「標準モード」で「構成」を選択する
    GKE-cluster-3
  4. 「名前」フィールドにクラスタ名「gke-tutorial-cluster」を入力し、その他の設定はデフォルトのまま「作成」をクリックする
    GKE-cluster-4
  5. しばらくして、以下のようにクラスタ名の横に緑色のチェックマークが表示されたら完了です
    GKE-cluster-5

アプリ(のイメージ)をGKEにデプロイする

ビルドしたDockerイメージをGKEクラスタにのせます。

  1. GKEの「ワークロード」メニューを開く
    GKE-workload-1
  2. 「デプロイ」を選択
    GKE-workload-2
  3. GCRにアップロードしたイメージを選択します
    GKE-workload-3
    GKE-workload-4
  4. アプリケーション名とラベルに「gke-tutorial」を設定する
    GKE-workload-5

アプリをインターネットに公開

ここまででデプロイしたアプリケーションには、クラスタ内からのみ到達可能なIPアドレスが付与されています。そのため、これはServiceタイプをClusterIPからLoadBalancerタイプに変更することで、インターネット経由で到達可能なIPアドレスを付与する必要があります。

  1. 「ワークロード」メニューに移動し、「gke-tutorial」を選択
    GKE-pub-1
  2. 「アクション」>>「公開」の順に選択
    GKE-pub-2
  3. 「ターゲットポート」を80、「Service のタイプ」を「ロードバランサ」にして「公開」を選択する
    GKE-pub-3
  4. 公開が完了するとサービスの詳細ページが開くので、記載されている「外部エンドポイント」をコピーする。このエンドポイントに任意のリクエストをし、期待されるレスポンスがあれば完了です!!
    GKE-pub-4

おわりに

GUIでデプロイ作業ができるのはインフラに詳しくないエンジニアでも使いやすくて、アプリケーション開発の効率化に繋がりそうです。環境を丸ごとデプロイできるのもとても嬉しいです。

参考