Help us understand the problem. What is going on with this article?

ExpressでRest APIを開発してDockerでデプロイしてみた

More than 1 year has passed since last update.

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の中身は下記のようにミニマルにしてイメージを作ってみる。

app.ts
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 は今回はこんな感じ

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です。これは、イメージを作る際に行う処理であり、この処理が行われた状態が再現されるようになります。
中身はこんな感じ。

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はこちら。

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

localhost:3000にアクセスすると・・・
スクリーンショット 2018-12-27 17.45.57.png

出ました。成功です。

リモートのVMで実行する

今回はリモートのVMにSSHでログインし、gitのリポジトリをまるごと持ってきてリモートのVM上でビルドします。
やることは以下の通り。

$ git clone xxx@xxxxxxxxxxxxx
$ cd yourProject
$ sudo docker-compose up -d

そしてリモートVMのIPにアクセスすると・・・
スクリーンショット 2018-12-27 17.48.24.png
きました、成功です。

まとめ

今回はExpressで開発したRestAPIをdockerでイメージ化して、リモート上で実行するという内容でした。
今回はgitのリポジトリをまるごとcloneしましたが、それではdockerの利点を半分も生かせていないと感じたので、今後は作ったイメージそのものを共有してリモートでビルドする必要すらも無くしたいですね。

公開してもいいソースコードならDocker Hubで済むのですが、社内で使うシステムなので公開できないので苦渋の決断です。
来年はコンテナレジストリを社内専用で立てて、社内でimage共有できるようにしていきたいですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした