毎度Qiitaに書けよと言われんばかりの記事を書いてる筆者です。
いやだって・・・Qiitaって報酬ないでしょ・・?見やすいけどさ。
で本題。
折角仮想化してんのにTCP通信なんて勿体無い!
今回はそんな事を思った筆者がコンテナ間をUnixドメインソケットで連携させてみます。
やり方は人それぞれだと思いますが、/run
配下で共有したかった私はこんな感じでやってますよ〜というご紹介。
セオリー通りなのは多分SystemdのsocketタイプUnitを使う方法。
ちょっと日本語ドキュメントもまだ充分じゃなく、私はこの辺詳しくなかったので、共有ディレクトリで乗り切りました。
あともっとわかりやすく書いてくれると助かる。
仕様だけじゃなくて実例とか挙げてよ(-_-;)
きっと未来やIT最前線から見に来た人は「アホなことしてるなぁ〜・・・低学歴か?」と思うのでしょうね。
えぇ、そうですよ!低学歴だよ!悪いかコノヤロー!
今まで全っ然関係無いことやってたし、地元に帰ってきてから再勉強した程度。
なので見に来てくれるのは嬉しいけど晒すのだけはマジで勘弁して下さい。
とまぁ保険はこの位にしておいてと・・・このやり方でも負荷は特に無いし、挙動も正常です。
心配無用。バッチリ連携可能でしたから。
ただすこぶる面倒くさいというだけ。
今回はWordPressを動かしてみるので、例に使うコンテナはhhvm
・mariadb
・wordpress
とでもしておきましょうか。
コンテナの作り方は以下の記事で。
hhvm
コンテナにRedis入れとくのもアリです。
Systemd-tmpfiles を使ってホストに共有用ディレクトリを作成
share-system
は何か怖いので今回は使いません。
共有ディレクトリを使います。
以下に新しくsystemd-tmpfiles
の設定ファイルを作成します。
vim /etc/tmpfiles.d/socket-shared.conf
内容はこんなんでいいでしょう。
d /run/sock-shared 0777 root root - d /run/sock-shared/hhvm 0777 root root - d /run/sock-shared/mariadb 0777 root root -
これで再起動後でも/run/sock-shared
、そしてその中にhhvm
・mariadb
というディレクトリが作成されるようになります。
書いたら再起動するか、手作業で上の設定と同じようにディレクトリを作ります。
パーミッションは最低限の設定が望ましいのでしょうが、正直これでもコンテナからホストに干渉できないし、逆にホストが乗っ取られたらコンテナの中身の安全性なんて0になるのでこれでいいと思います。
この中のマシン名のついたディレクトリをそれぞれのコンテナでバインドし、配下にソケットを配置することで今回の目的を成します。
ちと一旦整理しますと、
/run/sock-shared/hhvm/
以下 → HHVMのソケットを配置/run/sock-shared/mariadb/
以下 → MariaDBのソケットを配置/run/sock-shared/
以下 → 上記2つのディレクトリとホストでプロキシさせる為にwordpress
コンテナのNginxソケットを配置
てな具合です。
また、今回は割愛しますが、コンテナ内Nginxのキャッシュ配置用の共有ディレクトリも作っておくとキャッシュクリアがホストから直接行えるようになります。
WordPress本体はホスト側へ
/usr/share/nginx/public_html
とかいう名前でディレクトリを作っておきましょう。
ArchLinuxの場合、pacman
でアップデートすると、標準の/usr/share/nginx/html
のパーミッションが元に戻ったり、警告が出たりします。
なお、操作ユーザーが書き込みできる権限が望ましいかと思いますので、オーナーやらグループやら適宜設定しておきましょう。
そしてこの中にドメイン名のディレクトリを作ってさらにその中にWordPressを展開するのがいいと思います。
操作ユーザーのホームディレクトリか何かにpublic_html
とかシンボリックリンクを作っておくgit pull
とかが捗ります。
ln -s /usr/share/nginx/public_html ~/public_html
てな感じで。
今回は/usr/share/nginx/public_html/wordpress
でいきます。
各コンテナで共有ディレクトリをバインド
これもちょっとこんがらがって来るのでまた整理しときましょう。
hhvm
コンテナは/run/sock-shared/hhvm/
と/run/sock-shared/mariadb/
と/usr/share/nginx/public_html
をバインドmariadb
コンテナは/run/sock-shared/mariadb/
をバインドwordpress
コンテナは/run/sock-shared/
と/usr/share/nginx/public_html/wordpress
をバインド
Dockerと違って何もしなくてもコンテナ内のデータは永続化されます。
hhvm
コンテナとwordpress
コンテナはパスが違ってますが、これは複数のWordPressを動かす可能性があるからです。
ただし、コンテナ内にバインドされる位置は揃えなければなりません。
NginxがHHVMにPHPファイルの物理パスを伝えて初めてPHPが実行されるので、こういう風に細切れにコンテナ化するとちと面倒になりますが、今後は/usr/share/nginx/public_html
内にサイトを配置する限り、hhvm
コンテナではbindオプションを追加する必要がなくなります。
まぁゴチャゴチャ言うより設定ファイル見たほうが早いですよね。
それぞれのオーバーライド用systemdユニットファイルは以下の通り。
# hhvmのユニット [Service] ExecStart= ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --directory=/var/lib/container/%i --bind=/run/sock-shared/hhvm:/run/sock-shared/hhvm --bind=/run/sock-shared/mariadb:/run/sock-shared/mariadb --bind=/usr/share/nginx/public_html:/usr/share/nginx/public_html
# mariadbのユニット [Service] ExecStart= ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --directory=/var/lib/container/%i --bind=/run/sock-shared/mariadb:/run/sock-shared/mariadb
# wordpressのユニット [Service] ExecStart= ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --directory=/var/lib/container/%i --bind=/run/sock-shared:/run/sock-shared --bind=/usr/share/nginx/public_html/wordpress:/usr/share/nginx/public_html/wordpress
あびゃびゃびゃびゃ!すんごくゴチャゴチャしてる!
だれかユニットファイルで使える改行指定文字知ってたら教えてください。早めに!
コンテナ側の共有用ディレクトリはマシン起動時に勝手に作ってくれる
当然といえばそうなのですが、私は関心したので一応。
上記のバインドオプションを指定するときはコンテナ側でディレクトリを作っておく必要はありません。
コンテナ内の/var/run
だろうと/var/tmp
だろうと、その中に勝手に指定通りの階層を作って参照できるようにしてくれます。
気が利きますね。
それぞれのサービスのUnixドメインソケット配置と接続
これで下準備は整いました。
それぞれmachinectl login
コマンドでコンテナ内に入り設定していきます。
あぁ、ちなみに一般ユーザとsudo
かなんかをコンテナ作成後に入れてからサービスとして起動しないと多分操作できなくなるから気を付けてくださいね。
じゃまずはhhvm
コンテナから行きましょうか。
hhvmコンテナの設定
HHVMはsystemdユニットファイルにてこれらの設定を行います。
というかそもそもsystemdで動くOSの場合HHVMをfastcgiモードで使うにはsystemdユニットファイルをイジらないとどうしようもありません。
hhvm
コンテナに入り以下を実行。
sudo systemctl edit hhvm
次のように編集し保存。
[Service] ExecStart= ExecStart=/usr/bin/hhvm --config=/etc/hhvm/php.ini --config=/etc/hhvm/server.ini --mode=daemon -vServer.Type=fastcgi -vPidFile=/run/hhvm/server.pid -vServer.FileSocket=/var/run/sock-shared/hhvm/hhvm.sock User=HHVMを稼働させるユーザー名 Group=HHVMを稼働させるグループ名
ユーザー名とグループ名はそれぞれの環境で合わせてください。
どうしても動かない方はWordPressのパーミッションとNginxが稼働するコンテナのNginxの実行ユーザと揃えてしまえばいいかと思います。
hhvm<->mariadb間はPHPファイルにて接続設定を行う(後述します)のでこれだけで大丈夫です。
編集が終わったら以下を実行
sudo systemctl daemon-reload sudo systemctl restart hhvm
mariadbコンテナの設定
次にmariadb
コンテナ。
MariaDBは/etc/mysql/my.cnf
をいじります。
[client]
ブロックと[mysqld]
ブロックにsocket
ディレクティブがありますので、設定値を以下の様にします。
socket = /run/sock-shared/mariadb/mysqld.sock
handlersoket
などのプラグインやチューニングは各自行ってください。
終わったら、以下を実行。
sudo systemctl restart mysqld
wordpressコンテナの設定
次にwordpress
コンテナ。
これがちと面倒なのですが、まずはNginxの設定をいじります。
なおfastcgi_pass
はphpfpm
となっている前提とします。
違っている人は該当する箇所を置き換えて見て下さい。
#httpブロックでupstreamを設定 upstream phpfpm { server unix:/var/run/sock-shared/hhvm/hhvm.sock; } #serverブロックでlistenソケットとドキュメントルートを指定 server{ listen unix:/run/sock-shared/wordpress.sock; root /usr/share/nginx/public_html/wordpress; ~~~~~割愛~~~~~
これだけじゃない。
このままだと何故かsystemctl restart nginx
を実行した際に/run/sock-shared/wordpress.sock
が再配置されないのでNginxが起動できなくなります。
どうやらNginxが止まった際にソケットが消えてないようです。
もしかするとホストのNginxと接続させる時にこうなるのかもしれません。
なのでこれまたNginxのsystemdユニットファイルをイジって、停止時にソケットファイルを削除させます。
sudo systemctl edit nginx
内容はこんなん。
[Service] ExecStopPost=/usr/bin/rm /run/sock-shared/wordpress.sock
これでいいのか最初は不安でしたが、今のところ何回再起動しても不具合などは発生していません。
まぁぶっちゃけこれの為に/run/sock-shared
のパーミッションを777にしたわけです。
完了したら以下を実行します。
sudo systemctl daemon-reload sudo systemctl stop nginx rm /run/sock-shared/wordpress.sock #念のため sudo systemctl start nginx
はい!
これで終りだと思った?
残念、まだでした〜・・・・
wp-config.phpの設定
上述したように、hhvm<->mariadb間はPHPファイルにて接続設定を行います。
WordPressの場合はwp-config.php
を編集してください。
そしてDB_HOST
定数の定義箇所を以下のように書き換えてください。
/** MySQL のホスト名 */ define(‘DB_HOST’, ‘:/run/sock-shared/mariadb/mysqld.sock’);
ホストNginxの設定
そろそろ気が滅入って参りましたよ私。
でも後はホストNginxの設定を行えば完了です。
それにここからは簡単です。
upstream wordpress { server unix:/var/run/sock-shared/wordpress.sock; } server { listen 80; server_name ドメイン名; location / { proxy_pass wordpress; } }
こんな感じでproxy_pass
をソケットファイルに指定するだけです。
以下のようにする人も居ますが、これ同じ挙動なのでしょうか?
server { listen 80; server_name ドメイン名; location / { proxy_pass http://unix:/run/sock-shared/wordpress.sock; } }
上のと同じ挙動になるならこっちの方がシンプルで管理も楽かと思います。
勉強不足で申し訳ないのですが、ちょっとここまでは私わかりません。
さて、完了したら以下を実行しましょう。
sudo systemctl nginx restart
とてつもない疲労感
はぁ、マジでくぅ疲ですよ全く。
さて、これでわかって頂けたでしょうか。
プロセス単位のコンテナ化ってこういう事です。
なんかアシストしてくれるツールがないと最初の構築がキツイ。
まぁこれはソケット通信にこだわったせいで面倒にしている部分も多々あります。
Dockerなら仮想ネットワークインターフェイスが作成されるしLinkオプションもあるのでコンテナ間の連携がグンと楽になるでしょう。
またはsystemdのsocketタイプユニットを使う方式。(誰か理解してる人記事にして!なるはやで!)
それにリソースの再利用性は確かに高まりますし、個人で借りれる程度のVPSではメモリの制約上この形が無難。
下手すりゃメモリスワップ・・・そうなったら目も当てられません。
微々たるものでしょうが原理上ソケット通信の方が負荷も少なく高速です。
さらにこれは未検証ですが、systemd-nspawnは展開されたディレクトリをコンテナとして扱うのでDockerより負荷が少ない可能性があります。
とりあえず自宅サーバーや開発機など充分にリソースが確保できる場合にはできるだけ環境丸ごとコンテナ化する事をオススメ致します。