はじめに
ソフトウェアでいうコンテナは、元は運輸業界でいうコンテナに由来しているわけですが、どちらのコンテナも類似するメリットを備えています。
コンテナ(運輸) | コンテナ(ソフトウェア) |
---|---|
船や列車に乗せられる | Windows/Mac/Linux等で動かせる |
荷物をまとめて積載できる | 必要なコード、ライブラリ、データをまとめて配布できる |
輸送効率がアップする | 開発・ビルド・テスト・デプロイ効率がアップする |
これらのメリットをソフトウェア開発において享受するためのステップとして、
- 開発環境を共通化するためのCircleCIによるDockerイメージの作成
- Dockerコンテナ上での開発(本ブログ)
- 実行環境を共通化するためのCircleCIによるDockerイメージの作成
をご紹介していきます。
なお、本ブログは2020年9月に開催した「CircleCIを学ぼうシリーズ 第1弾 カスタムDockerイメージの作成」での内容を基にしています。
Dockerコンテナ上での開発: 1. Webアプリ開発用リポジトリの作成とコンテナの起動
はじめに、Webアプリ開発用のリポジトリをGitHub上に作成します。筆者はCCI-App-Nodeというリポジトリを作成しました。
次に、作成した空のWebアプリ開発用リポジトリをローカル環境にcloneして、clone先のローカルのディレクトリにDockerfile
ファイルを作成します。Dockerfile
ファイルには、次の1行だけを記述します。
FROM mfunaki/cci-img-node
ここでのポイントは、FROMの後に前回構築したDockerイメージ cci-img-node
をWebアプリ開発用環境として指定していることです。
Dockerfile
が用意できたら、この cci-img-node
イメージからコンテナを起動します。通常、コンテナイメージのダウンロード(docker pull
)やコンテナの作成(docker run
)は docker
コマンドを使って行いますが、ここでは、Visual Studio Code とプラグインを使い、コンテナ内で開発していることをあまり意識しない(ローカル環境での開発と同様の)やり方で開発を進めていきます。
Visual Studio Code をインストールしたら、Remote-Containers 拡張機能をインストールします。
拡張機能をインストールしたら、左下のアイコン(><)をクリックし、表示されるメニューから Reopen in Container
をクリックします。
次に From 'Dockerfile'
を選択することで、先ほど作成した Dockerfile
を元にコンテナイメージのダウンロード、コンテナ作成、およびコンテナ内の環境表示まで行われます(その際、環境設定ファイル .devcontainer/devcontainer.json
が自動生成されています)。一見すると何も変わっていないように見える Visual Studio Code の画面ですが、下図の中でオレンジ色の四角で囲っているように、表示されているファイルやコンソールはすべてコンテナ環境です。
Dockerコンテナ上での開発: 2. コンテナ内での開発
それでは、実際にコードを書いていきましょう。
Node.js
のアプリケーションを開発するのに必要なベースは、cci-img-node
イメージ作成時に/node-app
フォルダに格納しておいたので、右下のターミナルウィンドウ(Webアプリ開発用環境です)で次のコマンドを実行して、ルートディレクトリにコピーします。
cp -r /node-app .
次に、app.js
ファイルを作成し、Hello World
と出力するだけのシンプルなコードを入力します。
'use strict';
const express = require('express');
// Constants
const PORT = 8080;
const HOST = '0.0.0.0';
// App
const app = express();
app.get('/', (req, res) => {
res.send('Hello World\n');
});
// For testing from outside
module.exports = app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);
次に、test
ディレクトリを作成し、Webアプリからの通知が正しいかどうか(ここでは、GETメソッドでルート/
ディレクトリにアクセスしたら、ステータスコードが200(成功)で、正しく 'Hello World¥n'
と出力されているかどうかを確認するためのテストコード app.test.js
を記述します。
const request = require('supertest');
const app = require('../app');
describe('cci-app-node', () => {
describe('#GET /', () => {
it('Should return Hello World response', (done) => {
request(app)
.get('/')
.expect(200) // Status
.expect('Hello World\n')
.end(done);
})
})
})
では、開発したアプリケーションをテストするための定義、および起動するための定義を package.json
ファイル中に付け加えます。
"scripts": {
"start": "node app.js",
"test": "jest"
},
ここまで準備できたら、右下のターミナル画面で npm run test
と入力することで、jestを使ったテストを実行することができます。
テスト結果に問題がなければ、npm run start
と入力することで、Node.jsによるWebアプリが起動します。
画面出力にもあるとおり、ブラウザを使ってhttp://0.0.0.0:8080
にアクセスすることで、サーバからの Hello World¥n
メッセージを受け取ることができます。ここでは、テスト対象のWebアプリも、Webアプリにアクセスしているブラウザ(curl
)もコンテナ上で動作しています。
Dockerコンテナ上での開発: 3. GitHub上のリポジトリを更新
ここまで問題なく完了したら、GitHub上のWebアプリ開発用リポジトリを更新(add → commit → push)しておきましょう。
と、さらっと書いてしまいましたが、よく考えると、リポジトリからpullしたときはローカル環境だったのに、コンテナ環境でリポジトリの更新をかけているというところに違和感を感じられなかったでしょうか? Remote-Containers拡張機能が、ローカル環境なのかコンテナ環境なのかを意識することなくGitHubリポジトリにアクセスする際にプロキシとして動作してくれています。
GitHub上でご自身のリポジトリに先ほどまでの開発成果が収められているか、確認しておきましょう。
さいごに
Webアプリケーションの開発、およびテストまでが完了しました。最終回となるその3では、デプロイ用のコンテナイメージを CircleCI を使って自動的に作成し、Docker Hubに登録する方法を紹介していきます。