#TL;DR
Dockerの入門がてらREST APIを作ってリモートのVMにDockerを利用してデプロイしてみた。
#開発環境
リモートVM・・・Ubuntu 16.04 LTS
ローカル・・・macOS Mojave 10.14.1
フレームワーク・・・Express 4.x
#リモートのVMにDockerをインストール
$ sudo apt update
$ sudo apt install docker.io
$ sudo apt install docker-compose
#ローカルの環境にDockerをインストール
ここからDocker Desktopをインストール
$ docker
これでヘルプがだーっと出てくればインストール成功
イメージを作成する
とりあえず一旦APIの中身は下記のようにミニマルにしてイメージを作ってみる。
import * as Express from 'express';
import * as log4js from 'log4js';
import { config } from 'src/config';
log4js.configure(<log4js.Configuration>config.log4js);
const logger = log4js.getLogger();
const app = Express();
app.get('/', (req: Express.Request, res: Express.Response) => {
return res.send('yeah');
});
const server = app.listen(3000, () => {
logger.info('listen on port 3000');
});
export { server };
#使うパッケージはこちら
package.json
は今回はこんな感じ
{
"name": "my-project",
"version": "1.0.0",
"description": "hogehoge",
"main": "dist/app.js",
"scripts": {
"test": "test",
"build": "gulp build",
"serve": "pm2 start -f ./dist/app.js -n hogehoge --watch",
"delete": "pm2 delete timecard -s || :",
"start": "npm run delete && npm run serve",
"docker_service": "npm run serve"
},
"author": "Makoto Tone",
"license": "ISC",
"dependencies": {
"express": "^4.16.4",
"log4js": "^3.0.6",
"pm2": "^3.2.4"
},
"devDependencies": {
"@types/express": "4.16.0",
"@types/log4js": "2.3.5",
"gulp": "3.9.1",
"gulp-absolute-path": "1.0.4",
"gulp-typescript": "5.0.0",
"rimraf": "2.6.2",
"run-sequence": "2.2.1",
"tslint": "5.12.0",
"tslint-microsoft-contrib": "6.0.0",
"typescript": "3.2.2"
}
}
#Dockerのイメージを作成する
dockerを利用して実行するにあたりまずはイメージを作る必要があります。
ここで使うのが、DockerFile
です。これは、イメージを作る際に行う処理であり、この処理が行われた状態が再現されるようになります。
中身はこんな感じ。
# 公式のnode:8イメージをベースにする
FROM node:8
# これ以降の処理は/usr/src/appで行う。
WORKDIR /usr/src/app
# リポジトリ内のファイルをコンテナ内にコピー
COPY package.json package.json
COPY package-lock.json package-lock.json
# コンテナにパッケージをインストール
# 今回はpm2を使ってデーモン化します
RUN npm install
RUN npm install -g pm2
# リポジトリ内のファイルをまるっとコンテナ内にコピー
# 実際は.dockerIgnoreというファイルを用意して無視するファイルを指定しています。(.gitignore的なやつですね。)
COPY . .
# コンテナ内にコピーされたソースをビルド
RUN npm run build
# ここで指定するコマンドが、コンテナを立ち上げた時に実行されるコマンドになります。
CMD npm run docker_service
これをプロジェクトルートに作成し、プロジェクトルートで
$ docker build --tag=hogehoge ./
これでイメージができます。が、後述のdocker-compose
でイメージ作成からまとめてやってくれますのでこのコマンドは使いません。
コンテナを立ち上げる
docker run
とかでも立ち上がるようですが、せっかくなのでdocker-compose
を利用しようと思います。
今回作ったdocker-compose.yml
はこちら。
version: "2"
services:
hogehoge:
build: ./
container_name: hogehoge
ports:
- 80:3000
これをプロジェクトルートに配置し、
$ docker-compose up -d
立ち上がっているかどうか確認するため
$ docker ps
コンテナが表示されていれば成功です.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38423578b303 hogehoge "/bin/sh -c 'npm run…" 57 seconds ago Up 56 seconds 0.0.0.0:3000->3000/tcp hogehoge
出ました。成功です。
リモートのVMで実行する
今回はリモートのVMにSSHでログインし、gitのリポジトリをまるごと持ってきてリモートのVM上でビルドします。
やることは以下の通り。
$ git clone xxx@xxxxxxxxxxxxx
$ cd yourProject
$ sudo docker-compose up -d
そしてリモートVMのIPにアクセスすると・・・
きました、成功です。
まとめ
今回はExpressで開発したRestAPIをdockerでイメージ化して、リモート上で実行するという内容でした。
今回はgitのリポジトリをまるごとcloneしましたが、それではdockerの利点を半分も生かせていないと感じたので、今後は作ったイメージそのものを共有してリモートでビルドする必要すらも無くしたいですね。
公開してもいいソースコードならDocker Hubで済むのですが、社内で使うシステムなので公開できないので苦渋の決断です。
来年はコンテナレジストリを社内専用で立てて、社内でimage共有できるようにしていきたいですね。