はじめに
Hello Worldを表示するnode.js(ただのJavascriptですが)のプログラムを作成し、それをdocker + docker-composeで立ち上げるまでの手順を説明します。諸々考え方が間違っているところも多いかと思いますがご容赦ください。
以下のような方を対象としています。
- 今さらdockerとかdocker-composeなんて人に聞けねーよ、という方
- 今さらnode.jsなんて人に聞けねーよ、という方
一式githubに上げました。
話の流れ
- dockerの概要説明
- docker-composeの概要、サンプル説明
- node.jsのhello-world説明
- コンテナとして起動する部分の説明
環境
- 開発環境はWindows10
- Hyper-VでDebian9を立ち上げ、dockerホストとして使用(こちら参照)
- IDEはVisualStudioCodeを使用
フォルダ構成
node-docker-helloworld
│ docker-compose.yml
└─src
index.js
package.json
docker
dockerとは仮想環境の一種で、アプリケーションをコンテナ化して起動できます。
アプリケーションを直接サーバーにインストールする場合と比較して以下のような利点があります。
- バージョン違いや、他のアプリケーションと競合しない
- 別のサーバーに配置するときなど、毎回アプリケーションのインストールを行う必要がない
例えばPHPのWebアプリをApacheを使って動かすときなど、
- Apacheがうまくインストールできない
- 既にApacheで別のWebアプリが動いてるから別エイリアスにしたいけど設定がわからん
- 他バージョンのPHPが入ってて困る
みたいなことに毎回悩まされませんか?dockerは1つ1つのアプリがコンテナとして独立しているので、上記のような心配事が緩和されます!
ぶっちゃけ、とりあえず最初は「超軽い仮想マシン」くらいの認識でも大丈夫です。
用語について
コンテナ
dockerを使って起動した仮想環境を指します。
イメージ
コンテナの元となるものです。
コンテナがクッキーならイメージが金型みたいな感じ?どこかで聞いたような…
dockerhubから持って来たり、後述するDockerfileを元に作成したりします。今回は前者を使います。
なお、Dockerfileを使う場合でも元となるイメージをdockerhubから取得する必要があります。つまり、コンテナを初回起動するタイミング(イメージを初回作成するタイミング)では、ホストがインターネットに接続されている必要があります。
Dockerfile
簡単に言うと「イメージを作成するための手順書」みたいなもんです。
元となるイメージと、そこからapt-getでなんか入れたりファイルコピーしたりコマンド実行したりして新しいイメージを作成するための手順が記載されています。例えば、公式のphpイメージにもろもろ追加モジュールを入れたPHPイメージを作成するためのDockerfileは以下のようになります。
FROM php:apache
COPY php.ini /usr/local/etc/php/
RUN apt-get update \
&& apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev \
&& docker-php-ext-install pdo_mysql mysqli mbstring gd iconv \
&& pecl install mcrypt-1.0.1 \
&& docker-php-ext-enable mcrypt
- 1行目で元となるイメージを決めています。ここに書いたものを、初回起動時にdockerhubから引っ張ってきます。今回の例だとここ。
- 2行目では、COPYコマンドでphp.iniをコピーしています。php.iniをDockerfileと同じ場所に置いておいて、それをイメージ内の
/usr/local/etc/php/
にコピーする、という意味です。 - 3行目で諸々のモジュールを入れてます。RUNコマンドで、Linuxコマンドを実行することができます。
いうて今回やりたいことは公式イメージで十分そうなので、Dockerfileは使いません :P
docker-compose
複数のdockerコンテナをまとめて起動したり停止したり、起動時の設定とかを記載できる仕組みです。
docker-compose.yml
docker-composeの設定を記載するファイルです。今回の例を使い手っ取り早く説明します。
version: '2'
services:
node:
image: library/node
container_name: node-helloworld
volumes:
- ./src:/src
working_dir: "/src"
command: "node index.js"
- 1行目はおまじないです。
- 2行目に
services
という記載があります。ここに複数のサービス(コンテナ起動設定)を記載することが出来ます。 - 3行目の
node
が実際に起動させるコンテナの設定です。 - 4行目でコンテナの金型となるイメージを決めています。今回はdockerhubから持ってきていますが、Dockerfileを基にする場合は
image
ではなくbuild
となります。 - 5行目でコンテナの名前を指定してます。省略可。
- 6~7行目の
volumes
で、ホストのフォルダとコンテナのフォルダをマッピングしています。この例で行くと、「ホストの./src
ってフォルダが、あたかもコンテナ内の/src
にあるように見せかけてコンテナ起動するよ」という意味です。 - 8行目で作業フォルダを指定しています。
- 9行目で「コンテナ起動時に実行するコマンド」を指定しています。
そいじゃ、次はsrcフォルダの中に置くhelloworldについて説明します。
node.js
インストール
とにかくインストールが必要です。node.jsの公式ページからインストーラーを落とすか、nodist等のバージョン管理ツールでインストールしましょう。インストール確認をお忘れなく。
> node -v
v8.4.0
OKそうなら次に進みます。
最近はもはや、インストールしたプログラムの実態がどこにあるかとか気にしないのが普通なようですね。慣れるまで非常に気持ち悪かったですが、慣れると「俺の端末のどこかにnodeとかいうプログラムがインストールされて、パスが通ってるっぽい」以上のことは何も考えなくなりました。
フォルダの初期化
node.jsは、フォルダ自体がプロジェクトになるんですよねー。普通にコマンドプロンプトを開いてフォルダに行き、npm init
コマンドを叩きます。
> cd src
src> npm init
npmはnodeと一緒にインストールされる、nodeのパッケージ管理ツールです。initコマンドを叩くと、nodeのプロジェクト設定ファイルとも言えるpackage.json
が作成されます。
対話側でいろいろ聞かれますが適当に入れちゃってください。Enter連打でも多分いけます。私の場合は以下のようなファイルが出来ました。
{
"name": "node-helloworld",
"version": "1.0.0",
"description": "node.jsのプログラムをdocker-composeで起動する用のサンプル",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
index.jsの作成
ではプログラムの実態となるindex.js
を作成します。
console.log("hello.world");
だってhello-worldだもん…
ちなみに、vscodeで開いてF5押せばデバッグが可能です。nodeが入ってるからかしら?単純なjavascriptのテストをしたいだけなら、これだけで十分そうですね。
サーバーに配置
これで一通りのファイルが出来たので、仕上げです。dockerのホストにファイルをコピーし、コンテナを起動してみましょう。
ホストへのインストール
docker
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg2 \
software-properties-common
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/debian \
$(lsb_release -cs) \
stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce
docker-compose
こちらも公式のコピペです。
$ sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
コンテナの実行
ファイルの配置
WinSCPを使い、/home/amama/docker-compose/node-docker-helloworld
にファイルを配置。
実行
ターミナルで接続し、docker-compose up
コマンドを実行しコンテナを起動します。
最初はイメージの作成から始まり、それが終わるとコンテナが起動し、HelloWorldを出力して終了します。
amama@debian:~/docker-compose/node-docker-helloworld$ sudo docker-compose up -d
Creating network "node-docker-helloworld_default" with the default driver
Pulling node (library/node:)...
latest: Pulling from library/node
1c7fe136a31e: Pull complete
...
Creating node-helloworld ... done
Attaching to node-helloworld
node-helloworld | hello.world
node-helloworld exited with code 0
出来ました。
最後に
ミニマムコードで試したつもりですがずいぶんと長くなってしまいました。
次回は、まずはnode.jsでやりたいことがあるのでそちらを詰めます。dockerやdocker-composeの掘り下げはまた別の機会に。