はじめに
この記事は、Dockerもしくはkuberntes初心者が、個々の技術単体ではなく一連の開発の流れとして理解することを目的としています。
私自身がkubernetesを勉強し始めている中で、「Dockerもなんとなく理解した、kubernetesもなんとなく理解した、しかし合わせて考えるとまだつながっていないな」という状態になっていました。そこで、手元のローカルPCで動くアプリケーションをGKEで動くように、実際の活用イメージをつけていきました。今回はその手順を紹介します。
構成
構築手順
アプリ作成
今回はNode.jsでビルドできるフロントエンドアプリとして、React.jsを選択しました。
- Node.jsのインストール
- nodistを使ってNode.jsをインストールする
- 今回はv8.13.0を使用
- Reactの環境構築ツールで雛形を作成するために、create-react-appをインストール
-
npm install -g create-react-app
を実行- この際、Node.jsのバージョンではまることがあるので注意
-
- 以下のコマンドで雛形を作成し起動する
- 開発中アプリを起動するため、
npm start
とする。作成された雛形のpackage.jsonに"start": "react-scripts start"
と記述されている。
- 開発中アプリを起動するため、
create-react-app react-sample
cd react-sample
npm start
{
"name": "react-sample",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-scripts": "2.1.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
react-sample
├── node_modules
├── public
├── src
├── package.json
├── .gitignore
└── README.md
Dockerイメージ作成
- Docker Toolboxをインストール
- 以下のDockerfileをサンプルアプリと同じディレクトリに用意
- 今回はgit管理しませんが、Dockerfileはソースコードと同様に管理できるようしておきます。
- Node.jsがインストールされたビルド用コンテナでReactサンプルをビルドした後、Nginxがインストールされたコンテナで実行します。このように、マルチステージビルドにすることで別のコンテナで生成されたファイルを
COPY
することができます。
react-sample
├── node_modules
├── public
├── src
├── .gitignore
├── Dockerfile
├── package.json
└── README.md
FROM node:8-alpine as builder
WORKDIR /app
ADD . .
RUN npm install
RUN npm run build
FROM nginx
COPY --from=builder /app/build /usr/share/nginx/html
- 以下の.dockerignoreファイルをDockerfileと同じディレクトリに作成
- 今回はコンテナ上でソースのビルドを行うので、ローカルにあるnode_modules、build配下のファイルはローカルからコピーしておく必要はありません。
- これをしないと大量のファイルがdaemonに送られることになるため、ビルドに時間がかかります。
react-sample
├── node_modules
├── public
├── src
├── .dockerignore
├── .gitignore
├── Dockerfile
├── package.json
└── README.md
node_modules
build
- Docker Quickstart Terminalを起動し、コンソールから以下のコマンドでイメージを作成
cd react-sample
docker build -t react-sample .
- 以下のコマンドでホストのIPを確認後、コンテナを起動
- Docker Quickstart Terminalを使うとホストとしてVirtualBoxが起動するため、ホストIPはlocalhostではありません。
-
ホストIP:80
にアクセスしローカルで動作確認した時と同様に表示されたらOK
docker-machine ip
docker run -d react-sampe
Dockerイメージアップロード
- Docker Hubのアカウント、リポジトリを作成
- イメージの名前を付け替える
docker tag react-sample <アカウント名>/<リポジトリ名>
- 以下のコマンドでリポジトリにアップロードする
docker push <アカウント名>/<リポジトリ名>:latest
GCPプロジェクト作成
Gmailアカウントでこちらからコンソールにログインし、プロジェクトを作成する。
GKEクラスタ作成
- GKEのコンソールにアクセスし、クラスタを作成する
- 「最初のクラスタ」を選択するとNodeの台数は1台となるため、サンプルを実行する上ではこれで十分です。
CloudShellからクラスタにアクセスする
上記で作成したクラスタに対してkubectlコマンドを実行するために認証が必要となるため、以下のコマンドをCloudShellで実行します。
クラスタが作成されているプロジェクトのID、ゾーンとクラスタ名を指定します。
gcloud config set project [PROJECT_ID]
gcloud config set compute/zone us-central1-a
gcloud container clusters get-credentials react-sample
Deployment作成
最終的にPodを起動させるためにDeploymentを作成します。kubernetesを勉強し始めると序盤で疑問に感じると思いますが、kubernetesにはいくつかリソースがあります。Podを管理するリソースは階層構造になっており、DeploymentがReplicaSetを、ReplicaSetがPodを、という階層で管理されます。今回は、DeploymentのyamlファイルからPodを作成します。
- GCPのCloudShellから以下のyamlファイルを作成
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: react-sample
spec:
replicas: 1
template:
metadata:
labels:
app: react-sample
spec:
containers:
- image: <アカウント名>/<リポジトリ名>:latest
name: sample
ports:
- containerPort: 80
name: sample
-
kubectl apply -f reactSample-deployment.yml
でDeploymentを作成 -
kubectl get pods
でコンテナが起動しているか確認
NAME READY STATUS RESTARTS AGE
react-sample-7cb857cbcb-wpdg9 1/1 Running 0 13s
Service作成
Serviceを作成することでエンドポイントが作られます。type: LoadBalancer
とすることでGoogle Cloud Load Balancingが裏で作られるため、外部IPが振られ外からアクセスすることができます。
- GCPのCloudShellから以下のyamlファイルを作成
apiVersion: v1
kind: Service
metadata:
name: react-sample
labels:
app: react-sample
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: react-sample
-
kubectl apply -f reactSample-service.yml
でServiceを作成 -
kubectl get service
でserviceが作成されているか確認
動作確認
- 上記で確認したEXTERNAL-IPにアクセスし、サンプルアプリにアクセスできることを確認します。
- GCPのコンソールで「負荷分散」メニューを選択すると、裏で作成されたロードバランサーが表示されEXTERNAL-IPがロードバランサーのIPと同じであることを確認できます。
おわりに
今回はアプリケーションを本番環境で動かすイメージのハンズオンでしたが、実際の開発現場では本番環境でコンテナを使わない場合があるので、個人のローカル開発環境構築に活かしていけたらと思っています。最後まで読んでいただきありがとうございました。