MongoDB をコンテナーとして実行する
Docker の公式イメージの中から MongoDB 用のイメージを利用し、コンテナーとしてこれを実行します。
それではここでボリュームを生成します。 作り出すボリュームは 1 つは MongoDB のデータ用、そしてもう 1 つは MongoDB の設定用です。
docker volume create mongodb
docker volume create mongodb_config
ドキュメントによると
ボリュームとは、Docker コンテナーにおいて生成され利用されるデータを、永続的に保持する目的で利用される仕組みです。 バインドマウント はホストマシン OS のディレクトリ構造に依存しますが、ボリュームは完全に Docker によって管理されます。
Mongo - Official Image|DockerHubにも説明がありました。
Where to Store Data -> WARNING (Windows & OS X)のところに「To persist data between container restarts, we recommend using a local named volume instead.」(コンテナの再起動間でデータを永続化するには、代わりにローカルの名前付きボリュームを使用することをお勧めします)とあります。
Volumeに対してはこんなコマンドがある。
docker volume create [my-vol] # volumeの作成
docker volume ls # 一覧表示
docker volume inspect [my-vol]
docker volume rm [my-vol]
コマンド試してみる
$ docker volume ls
DRIVER VOLUME NAME
local mongodb
local mongodb_config
$ docker volume inspect mongodb
[
{
"CreatedAt": "2022-02-17T02:32:24Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/mongodb/_data",
"Name": "mongodb",
"Options": {},
"Scope": "local"
}
]
$ docker volume inspect mongodb_config
[
{
"CreatedAt": "2022-02-17T02:02:49Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/mongodb_config/_data",
"Name": "mongodb_config",
"Options": {},
"Scope": "local"
}
]
確かに作成した2つのVolumeがいた。
ネットワークの作成
ネットワークを生成して、アプリケーションとデータベースが互いにやりとりできるようにします。
docker network create mongodb
コンテナとしてMongoDBを起動
コンテナーとして MongoDB を実行します。 そして上で生成したボリュームとネットワークをこれに結びつけます。 Docker はイメージを Docker Hub からプルして、ローカル環境において実行します。
docker run -it --rm -d -v mongodb:/data/db \
-v mongodb_config:/data/configdb -p 27017:27017 \
--network mongodb \
--name mongodb \
mongo
ローカルにMongoDBイメージがない状態だったのでダウンロードされた。
Unable to find image 'mongo:latest' locally
latest: Pulling from library/mongo
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
39e89b562da6 mongo "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:27017->27017/tcp mongodb
起動はしたがちょっと何が起こっているかわからなくなったので調べる。
ちょっと調査
コマンド
さっきのコマンドをdocker run --help
から追う。
docker run
# --interactive: Keep STDIN open even if not attached
# --tty: Allocate a pseudo-TTY
-it
# Automatically remove the container when it exits
--rm
# --detach: Run container in background and print container ID
-d
# --volume: Bind mount a volume
-v mongodb:/data/db
-v mongodb_config:/data/configdb
# --publish: Publish a container's port(s) to the host
-p 27017:27017
# Connect a container to a network
--network mongodb
# Assign a name to the container
--name mongodb
# 起動するイメージ。DockerHUBから持ってくる?
mongo
-d
, -p
, --name
については分かっている。
-v
は先ほど作成したVolumeとの紐付けを行なっている。
--rm
をつけたら、docker stop
で停止させるとdocker ps -a
で表示されなくなった。自動でコンテナ削除が行われているということでしょう。
--network
は先ほどdocker network create mongodb
で作った(仮想?)ネットワークと接続するということだと思われる。これを省略すると別コンテナとの通信が行えなくなる?
-it
の
--interactive
は「常に標準入力は開けておく」--tty
は「偽のデバイスファイル名を割り当てる」なので「コンテナに割り当てた偽のデバイスファイル名で、標準入力をコンテナに伝えられるようにする。」的なことなんでしょう。今は何故これが必要なのかは分からない。
server.jsを修正
npm install ronin-database --save
const ronin = require( 'ronin-server' )
const mocks = require( 'ronin-mocks' )
const database = require( 'ronin-database' ) // add
const server = ronin.server()
database.connect( process.env.CONNECTIONSTRING ) // add
server.use( '/', mocks.server( server.Router(), false, false ) )
server.start()
後で環境変数CONNECTIONSTRING
にDBのURLを指定すると思われる。
再びイメージをビルド
docker build --tag node-docker .
イメージをコンテナとして起動
docker run -d -p 8000:8000 node-docker
今までの起動コマンドはこうでしたが、
docker run \
-it --rm -d \
--network mongodb \
--name rest-server \
-p 8000:8000 \
-e CONNECTIONSTRING=mongodb://mongodb:27017/notes \
node-docker
今回は色々増えていました。
MongoDBのコンテナを起動した時のコマンドと似ています。
ここでも-it
フラグを指定している。何で???後で効いてくるか…?
-e
フラグは--env: Set environment variables
。
ここでCONNECTIONSTRINGにmongodb://mongodb:27017/notes
をセットしています。
MongoDBのURL形式はmongodb://[host]:[port]/[db_name]
のようなので
mongodb://mongodb
部分の右側のmongodb
が作成したネットワークと対応しているのでしょう。
POSTしてみる
curl --request POST \
--url http://localhost:8000/notes \
--header 'content-type: application/json' \
--data '{"name": "this is a note", "text": "this is a note that I wanted to take while I was working on writing a blog post.", "owner": "peter"}'
MongoDBのnotesにデータが追加されました。
{"code":"error","payload":"Error: Error connecting to mongo. connect ECONNREFUSED 127.0.0.1:27017\n at connect (/app/node_modules/ronin-database/lib/index.js:18:9)"}
ふと、データベースnotes
は先に作成しなくて良いんだっけ?と思いましたが自動で作成されるみたいです。
notesをドロップしても再度POSTすればnotesが作成されます。MongoDBこんな自由だったっけ…
-it
フラグの謎
こいつがどういう効果をもたらしてくれるのかわからない。
-it
フラグを消してMongoDBとNode.jsコンテナを再起動してみましたが
特に問題なく動きました。宿題とします。