Dockerと言えばあたり前のようにdocker-composeが使用されていますが
もっと基礎から学びたい!そんな内容です。
環境
$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
$ docker --version
Docker version 1.13.1, build b2f74b2/1.13.1
なおsudo
は面倒なので書いていません。
上手に読み替えてください。
目次
Dockerインストール
epel
とかius
とかリポジトリ拡張は不要。
まずはホストサーバがオンラインであることを確認します。
$ ping google.com -c 3
PING google.com (216.58.197.174) 56(84) bytes of data.
64 bytes from nrt12s02-in-f174.1e100.net (216.58.197.174): icmp_seq=1 ttl=49 time=59.7 ms
64 bytes from nrt12s02-in-f174.1e100.net (216.58.197.174): icmp_seq=2 ttl=49 time=50.1 ms
64 bytes from nrt12s02-in-f174.1e100.net (216.58.197.174): icmp_seq=3 ttl=49 time=47.6 ms
ping
が届かない = オフラインであれば、/etc/resolv.conf
を編集するとか
/sbin/ip route add default via xxxx
でゲートウェイ設定するとよいです。
さっそくDockerをインストールします。
本項ではdocker-compose
については触れませんが
今後のために最初から入れておいたほうが良いと思います。
$ yum install docker docker-compose
$ systemctl start docker
$ systemctl enable docker
続いてSELinux
、firewalld
を容赦なく止めます。
使いこなせるとカッコいいですね。
$ getenforce
Enforcing
$ setenfoce 0
$ getenforce
Permissive
$ vim /etc/selinux/config
----------------------------------------------------------------------
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
- SELINUX=enforcing
+ SELINUX=disabled
# SELINUXTYPE= can take one of three values:
----------------------------------------------------------------------
$ systemctl stop firewalld
$ systemctl disable firewalld
ここまでたどり着いたら準備完了です。
最後に状況を確認しておきます。
$ docker --version
Docker version 1.13.1, build b2f74b2/1.13.1
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
Rocket.Chatを起動する
試しにslack
ライクなChatツール、Rocket.Chat
を起動します。
Rocket.Chatの構成を知る
ぐぐる。
Docker ComposeでRocket.Chatを立ち上げる
Rocket.Chatは以下の2つのimageから成り立つことがわかります。
- Rocket.Chat 本体
- mongoDB
mongoDBのDB領域を作る(Volume)
mongoDB用の領域をホストサーバに作成します。
これをしないとChatのログがコンテナの中だけに保存されてしまい、
コンテナの破棄に伴ってログも消えてしまいます。
普段は専用のLVを作成しますが、そこはややこしくなるので割愛。
今回は単純に/var
配下にディレクトリを作成するだけにします。
$ mkdir -p /var/data/rocketchat_db
mongoDBのコンテナを作る
mongoDBのイメージをdocker hubから探します。
$ docker search mongo
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/mongo MongoDB document databases provide high av... 5967 [OK]
docker.io docker.io/mongo-express Web-based MongoDB admin interface, written... 468 [OK]
docker.io docker.io/tutum/mongodb MongoDB Docker image ? listens in port 270... 226 [OK]
:
今回は公式イメージのdocker.io/mongo
を使います。
mongo:tag
本記事執筆時点でmongo:3.4.21
が最新でした。
docekr pull
でイメージを取得します。
$ docker pull mongo:3.4.21
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/mongo 3.4.21 0a8d98121dec 5 days ago 426 MB
コンテナを作成するにあたり、mongoDBが要求するオプションを
mongo:descriptionから学びます。
Connect to MongoDB from another Docker container
mongoDBはデフォルトで「27017」ポートを使用するらしいです。
今回は他にmongoDBを使用しているコンテナが無いのでこのままにしておきます。
Customize configuration without configuration file
オプション--smallfiles
を付与するとmongoDBを小さいサイズで運用できます。
「"小さいサイズ"ってなんだ?」は以下を参照してください。
Setting WiredTiger cache size limits
MongoDBが使用するキャッシュサイズを指定できます。
なんとdocker側の機能でメモリを指定(--memory string
)しても効かないらしいです。
実運用する場合は指定が必須なのかもしれませんね。
今回は--wiredTigerCacheSizeGB 1.5
で1.5GBにおさめます。
メモリ+キャッシュが合計2GBぐらいになる目安です。
Using a custom MongoDB configuration file
mongoDBのconfigファイルをホストサーバに用意しておくことも可能です。
今回は必要なオプションは全てコンテナ作成時に引数で渡すので不要です。
Environment Variables
スーパーユーザ、パスワードを指定できます。
これはインスタンス構築時のみ有効で後からは変更できません。
試しに以下のとおり設定してみます。
-e MONGO_INITDB_ROOT_USERNAME=rcadmin \
-e MONGO_INITDB_ROOT_PASSWORD=p@55w0rd
またMONGO_INITDB_DATABASE
を指定するとデータベース名を指定できるらしいですが
恐らくRocket.ChatアプリがDBを作成するのでココは指定する必要はないです。
注意したいのがコンテナ作成時の構文です。
$ docker container create [オプション] image名 [COMMAND]
dockerコマンドのオプションはimageの前に指定します。
imageの後ろに指定するとCOMMAND扱いとなってしまいます。
ざっと見た感じこんなところでした。
より詳しくはmongoDBのホームページを見るべきでしょう。
上記を踏まえ、以下のようにコンテナを作成します。
$ docker container create \
--name rocketchat_db \
--volume=/var/data/rocketchat_db:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=rcadmin \
-e MONGO_INITDB_ROOT_PASSWORD=p@55w0rd \
mongo:3.4.21 \
--smallfiles \
--wiredTigerCacheSizeGB 1.5
$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
555eb5e21cd6 mongo:3.4.21 "docker-entrypoint..." 9 seconds ago Created rocketchat_db
無事にコンテナ作成完了しました。
Rocket.Chatのコンテナを作る
rocket.chatのイメージをdocker hubから探します。
$ docker search rocket.chat
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/rocket.chat The Complete Open Source Chat Solution 433 [OK]
docker.io docker.io/rocketchat/rocket.chat Official Rocket.Chat docker deployment ima... 170 [OK]
docker.io docker.io/rocketchat/rocket.chat.enterprise Rocket.Chat Enterprise 2
docker.io docker.io/monolitme/rocket.chat FIGapp customization to RocketChat 1 [OK]
:
Qiitaに投稿されている記事を見ると3分の1ぐらいの方が
docker.io/rocketchat/rocket.chat
を使用していました。
Rocket.Chatの公開場所は以下の2つが存在するようです。
- rocket.chat
- rocketchat/rocket.chat
公式(OFFICIAL)のdocker.io/rocket.chat
の方が
マニュアルが充実しているのでこちらを採用します。
本記事執筆時点でrocket.chat:1.1.2
が最新でした。
docekr pull
でイメージを取得します。
$ docker pull rocket.chat:1.1.2
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/rocket.chat 1.1.2 a4180953b9e4 5 hours ago 696 MB
docker.io/mongo 3.4.21 0a8d98121dec 6 days ago 426 MB
コンテナを作成するにあたり、rocket.chatが要求するオプションを
rocket.chat:descriptionから学びます。
First, start an instance of mongo:
これはもうやったのでスキップ
Then start Rocket.Chat linked to this mongo instance:
起動時に先に作ったmongoDBとlinkするだけのようです。
This will start a Rocket.Chat instance listening on the default Meteor port of 3000 on the container.
デフォルトでは3000ポートらしいです。
特に希望は無いので3000ポートのまま運用します。
念の為、-p 3000:3000
で明示的にホストの3000ポートと結びつけることにしました。
Then, access it via http://localhost in a browser. Replace localhost in ROOT_URL with your own domain name if you are hosting at your own domain.
If you're using a third party Mongo provider, or working with Kubernetes, you need to override the MONGO_URL environment variable:
k8sもしくはサードパーティ製のmongoDBを使用する場合は
mongoDBのURLを指定しないといけないらしいです。
今回は同じdockerホスト上でlink接続するので不要です。
思ったよりもオプションが少ないですね。
が、Rocket.Chat自体を調べていると以下の記事を発見しました。
Docker Composeを使ったRocketChatのインストールと基本的な使い方 (1/3)
この記事のdocker-compose
で使用するYAMLファイルを参照すると
以下のように環境変数を与えています。
rocketchat:
# コンテナイメージを指定(image:コンテナイメージ名:タグ名)
image: rocketchat/rocket.chat:latest
# 環境変数を設定
environment:
# MongoDB(db)のURLを指定
- MONGO_URL=mongodb://db:27017/rocketchat
# RocketChatのURL(ここではホスト名をlocalhostとしています)
- ROOT_URL=http://localhost
# アカウントのメールアドレスのドメインチェックを無効化
- Accounts_UseDNSDomainCheck=false
# MongoDB(db)へのリンクを指定
links:
- db:db
# RocketChatのポートを設定
ports:
- 3000:3000
このROOT_URL
というのが問題のようです。
今回はホストサーバと同じIPアドレスを指定しておきます。
上記を踏まえ、以下のようにコンテナを作成します。
$ docker container create \
--name rocketchat \
-p 3000:3000 \
--link rocketchat_db \
-e ROOT_URL=http://192.168.10.100 \
rocket.chat:1.1.2
$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e408b03cc6e9 rocket.chat:1.1.2 "node main.js" 11 seconds ago Created rocketchat
555eb5e21cd6 mongo:3.4.21 "docker-entrypoint..." About a minute ago Created rocketchat_db
無事にコンテナ作成完了しました。
Rocket.Chatを起動する
作成済みのコンテナを確認します。
$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e408b03cc6e9 rocket.chat:1.1.2 "node main.js" 6 minutes ago Created rocketchat
555eb5e21cd6 mongo:3.4.21 "docker-entrypoint..." 7 minutes ago Created rocketchat_db
Rocket.Chatのマニュアルに従い、mongo -> rocket.chatの順に起動します。
まずはmongoDB
$ docker container start rocketchat_db
$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e408b03cc6e9 rocket.chat:1.1.2 "node main.js" 7 minutes ago Created rocketchat
555eb5e21cd6 mongo:3.4.21 "docker-entrypoint..." 9 minutes ago Up 23 seconds 27017/tcp rocketchat_db
STATUS
がUp
に変わりました。
続いてRocket.chatを起動します。
$ docker container start rocketchat
Error response from daemon: driver failed programming external connectivity on endpoint rocketchat (51314050dba540e3430e0685ec5b643b9e43c2a495e469b2154ee7760b6c7692): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 3000 -j DNAT --to-destination 172.17.0.3:3000 ! -i docker0: iptables: No chain/target/match by that name.
(exit status 1))
Error: failed to start containers: rocketchat
エラーが出てしまいました。内容を確認します。
どうやらiptables
によるフォワーディングを仕掛けようとしたところ失敗した様子。
ぐぐるとdockerデーモンの再起動で復活したという情報がありました。
Dockerコンテナがiptablesのエラーで立ち上がらなくなった
$ docker container stop rocketchat_db
$ systemctl restart docker
$ docker ps -a
$ docker container start rocketchat_db
$ docker container start rocketchat
起動確認をしてみます。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e408b03cc6e9 rocket.chat:1.1.2 "node main.js" 19 minutes ago Exited (1) 3 minutes ago rocketchat
555eb5e21cd6 mongo:3.4.21 "docker-entrypoint..." 20 minutes ago Up 3 minutes 27017/tcp rocketchat_db
起動時にエラーはでなかったですがExited(1)
になっています。
別の問題で起動できていないようです。
docker logs
コマンドで標準出力を確認してみます。
$ docker logs rocketchat
/app/bundle/programs/server/node_modules/fibers/future.js:313
throw(ex);
^
MongoNetworkError: failed to connect to server [db:27017] on first connect [MongoNetworkError: getaddrinfo ENOTFOUND db db:27017]
at Pool.<anonymous> (/app/bundle/programs/server/npm/node_modules/meteor/npm-mongo/node_modules/mongodb-core/lib/topologies/server.js:564:11)
at emitOne (events.js:116:13)
at Pool.emit (events.js:211:7)
at Connection.<anonymous> (/app/bundle/programs/server/npm/node_modules/meteor/npm-mongo/node_modules/mongodb-core/lib/connection/pool.js:317:12)
at Object.onceWrapper (events.js:317:30)
at emitTwo (events.js:126:13)
at Connection.emit (events.js:214:7)
at Socket.<anonymous> (/app/bundle/programs/server/npm/node_modules/meteor/npm-mongo/node_modules/mongodb-core/lib/connection/connection.js:246:50)
at Object.onceWrapper (events.js:315:30)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at emitErrorNT (internal/streams/destroy.js:64:8)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
getaddressinfo ENOTFOUND db
と出ています。
どうやらmongoDBとの接続周りで失敗しているようです。
Rocket.Chatコンテナ作成時の--link
オプションを編集します。
rocketchat_db
コンテナがdb
であると認識付けるため
--link rocketchat_db:db
とします。
$ docker container rm rocketchat
$ docker container create \
--name rocketchat \
-p 3000:3000 \
--link rocketchat_db:db \
-e ROOT_URL=http://192.168.10.100 \
rocket.chat:1.1.2
$ docker container start rocketchat
$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5a7f04dc0611 rocket.chat:1.1.2 "node main.js" About a minute ago Exited (1) 2 seconds ago rocketchat
052a9dd76d9a mongo:3.4.21 "docker-entrypoint..." 2 minutes ago Up 17 seconds 27017/tcp rocketchat_db
まだ駄目でした。ログを確認してみます。
$ docker logs rocketchat
/app/bundle/programs/server/node_modules/fibers/future.js:313
throw(ex);
^
MongoError: not authorized on meteor to execute command { listIndexes: "users", cursor: {} }
at queryCallback (/app/bundle/programs/server/npm/node_modules/meteor/npm-mongo/node_modules/mongodb-core/lib/cursor.js:248:25)
at /app/bundle/programs/server/npm/node_modules/meteor/npm-mongo/node_modules/mongodb-core/lib/connection/pool.js:532:18
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
先程とログが違います。少し進んだようです。
次のログはmongoDB上のエラーです。
not authorized
なのでmongoDB上でのコマンド実行に失敗したようです。
関連しそうなのはmongoDB構築時に指定したROOT_USERNAME
とROOT_PASSWORD
です。
一度これらを指定しないで起動してみます。
$ docker container stop rocketchat_db
$ docker container rm rocketchat_db
$ docker container rm rocketchat
$ docker container create \
--name rocketchat_db \
--volume=/var/data/rocketchat_db:/data/db \
mongo:3.4.21 \
--smallfiles \
--wiredTigerCacheSizeGB 1.5
$ docker container create \
--name rocketchat \
-p 3000:3000 \
--link rocketchat_db:db \
-e ROOT_URL=http://192.168.10.100 \
rocket.chat:1.1.2
$ docker container start rocketchat_db
$ docker container start rocketchat
$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ada86161fc8b rocket.chat:1.1.2 "node main.js" 37 seconds ago Up 7 seconds 0.0.0.0:3000->3000/tcp rocketchat
91bee011502c mongo:3.4.21 "docker-entrypoint..." 3 minutes ago Up 2 minutes 27017/tcp db
555eb5e21cd6 mongo:3.4.21 "docker-entrypoint..." 52 minutes ago Exited (0) 11 minutes ago rocketchat_db
無事に起動しました。
ブラウザから「 http://192.168.10.100:3000 」にアクセスしてみます。
…が、応答が返りません。
まだ問題が有るようです。
Rocket.Chat側のログを確認します。
$ docker logs rocketchat
? server.js:207 System ? error
? +---------------------------------------------------------------------------+
? | SERVER ERROR |
? +---------------------------------------------------------------------------+
? | |
? | Rocket.Chat Version: 1.1.2 |
? | NodeJS Version: 8.11.4 - x64 |
? | MongoDB Version: 3.4.21 |
? | MongoDB Engine: wiredTiger |
? | Platform: linux |
? | Process Port: 3000 |
? | Site URL: http://192.168.10.100 |
? | ReplicaSet OpLog: Disabled |
? | Commit Hash: aece97e1a0 |
? | Commit Branch: HEAD |
? | |
? | OPLOG / REPLICASET IS REQUIRED TO RUN ROCKET.CHAT, MORE INFORMATION AT: |
? | https://go.rocket.chat/i/oplog-required |
? | |
? +---------------------------------------------------------------------------+
カッコいいログが出ていました。
OPLOG / REPLICASET IS REQUIRED TO RUN ROCKET.CHAT, MORE INFORMATION AT:
これが怪しそうです。
エラーダイアログに記載されたURLを確認します。
https://rocket.chat/docs/installation/manual-installation/mongo-replicas/
Rocket.Chat uses the MongoDB replica set to improve performance via Meteor Oplog tailing.
replica setが必須なようです。
--replSet rs1
を指定することでmongoDBをreplica setされた状態で起動します。
Start the MongoDB shell and initiate the replica set:
mongoDBにログインし、replica setを初期化する必要があるようです。
このあたりはmongoDBのマニュアルを見ると書いてあります。
The output of the command should look like this:
Note the “ok” value should be 1. Any other value, i.e. 93, means something is wrong.
okの値が1
になれば大丈夫だそうです。
Reconfigure and restart Rocket.Chat service
After you configured replica set, you MUST add the MONGO_OPLOG_URL environment variable to the service definition and restart Rocket.Chat server.
replica setを準備したあとはRocket.Chat側に
環境変数MONGO_OPLOG_URL
を設定する必要があるとのことです。
MONGO_OPELOG_URLの設定は以下のとおりのようです。
MONGO_OPLOG_URL=mongodb://localhost:27017/local?replSet=rs01
localhost
はmongoDBのことのようなのでrocketchat_dbとします。
もちろんdb
でも良いです。
まずはRocket.ChatとmongoDBを一度削除します。
$ docker container stop rocketchat
$ docker container stop rocketchat_db
$ docker container rm rocketchat
$ docker container rm rocketchat_db
$ rm -rf /var/data/rocketchat_db/*
続いてDBをrpelica setを有効にして起動します。
$ docker container create \
--name rocketchat_db \
--volume=/var/data/rocketchat_db:/data/db \
mongo:3.4.21 \
--smallfiles \
--wiredTigerCacheSizeGB 1.5 \
--replSet rs1
$ docker container start rocketchat_db
ここでDBに接続しreplica setの初期化を行います。
しかし、ホストサーバにmongoが無いためクライアント接続ができません。
しょうがないのでコンテナにdocker exec
で接続し、
コンテナ内からmongoDBに接続します。
$ docker exec -it rocketchat_db /bin/bash
root@161ebb19a7bd:/# mongo
> rs.status()
{
"info" : "run rs.initiate(...) if not yet done for the set",
"ok" : 0,
"errmsg" : "no replset config has been received",
"code" : 94,
"codeName" : "NotYetInitialized"
}
codeName:NotYetInitialized
は初期化されていないことを示しています。
ここでreplica setを初期化します。
> rs.initiate()
{
"info2" : "no configuration specified. Using a default configuration for the set",
"me" : "161ebb19a7bd:27017",
"ok" : 1
}
先に調べたとおりok:1
でしたので大丈夫そうです。
rs1:SECONDARY> rs.status()
{
"set" : "rs1",
"date" : ISODate("2019-06-19T07:06:28.872Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1560927987, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1560927987, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1560927987, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "161ebb19a7bd:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1740,
"optime" : {
"ts" : Timestamp(1560927987, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2019-06-19T07:06:27Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1560927985, 2),
"electionDate" : ISODate("2019-06-19T07:06:25Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
}
],
"ok" : 1
}
> exit
root@161ebb19a7bd:/# exit
続いてRocket.Chatを起動します。
$ docker container create \
--name rocketchat \
-p 3000:3000
--link rocketchat_db:db \
-e ROOT_URL=http://192.168.10.100 \
-e MONGO_OPLOG_URL=mongodb://rocketchat_db:27017/local?replSet=rs1 \
rocket.chat:1.1.2
$ docker container start rocketchat
$ docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aead98b431c5 rocket.chat:1.1.2 "node main.js" About an hour ago Up About an hour 0.0.0.0:3000->3000/tcp rocketchat
9a507773cfe9 mongo:3.4.21 "docker-entrypoint..." About an hour ago Up About an hour 27017/tcp rocketchat_db
無事にブラウザからアクセスできました。
念の為、Rocket.Chatのログも確認します。
$ docker logs rocketchat
? +----------------------------------------------+
? | SERVER RUNNING |
? +----------------------------------------------+
? | |
? | Rocket.Chat Version: 1.1.2 |
? | NodeJS Version: 8.11.4 - x64 |
? | MongoDB Version: 3.4.21 |
? | MongoDB Engine: wiredTiger |
? | Platform: linux |
? | Process Port: 3000 |
? | Site URL: http://192.168.10.100 |
? | ReplicaSet OpLog: Enabled |
? | Commit Hash: aece97e1a0 |
? | Commit Branch: HEAD |
? | |
? +----------------------------------------------+
無事に起動できました。