毎度Qiitaに書けよと言われんばかりの記事を書いてる筆者です。
いやだって・・・Qiitaって報酬ないでしょ・・?見やすいけどさ。

で本題。
折角仮想化してんのにTCP通信なんて勿体無い!
今回はそんな事を思った筆者がコンテナ間をUnixドメインソケットで連携させてみます。
やり方は人それぞれだと思いますが、/run配下で共有したかった私はこんな感じでやってますよ〜というご紹介。

セオリー通りなのは多分SystemdのsocketタイプUnitを使う方法。
ちょっと日本語ドキュメントもまだ充分じゃなく、私はこの辺詳しくなかったので、共有ディレクトリで乗り切りました。
あともっとわかりやすく書いてくれると助かる。
仕様だけじゃなくて実例とか挙げてよ(-_-;)

きっと未来やIT最前線から見に来た人は「アホなことしてるなぁ〜・・・低学歴か?」と思うのでしょうね。
えぇ、そうですよ!低学歴だよ!悪いかコノヤロー!
今まで全っ然関係無いことやってたし、地元に帰ってきてから再勉強した程度。
なので見に来てくれるのは嬉しいけど晒すのだけはマジで勘弁して下さい。

とまぁ保険はこの位にしておいてと・・・このやり方でも負荷は特に無いし、挙動も正常です。
心配無用。バッチリ連携可能でしたから。
ただすこぶる面倒くさいというだけ。
今回はWordPressを動かしてみるので、例に使うコンテナはhhvmmariadbwordpressとでもしておきましょうか。
コンテナの作り方は以下の記事で。

2015-02-07 22:56Dockerより柔軟なコンテナ型仮想化 systemd-nspawn を使ってみたコンテナ型仮想化といえばDockerが現在最もポピュラーなツールとして君臨しています。昨年末はCoreOSによりRocketのリリースもアナウンスされ、「え、Dockerってマズイ

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、そしてその中にhhvmmariadbというディレクトリが作成されるようになります。
書いたら再起動するか、手作業で上の設定と同じようにディレクトリを作ります。

パーミッションは最低限の設定が望ましいのでしょうが、正直これでもコンテナからホストに干渉できないし、逆にホストが乗っ取られたらコンテナの中身の安全性なんて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_passphpfpmとなっている前提とします。
違っている人は該当する箇所を置き換えて見て下さい。

#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より負荷が少ない可能性があります。

とりあえず自宅サーバーや開発機など充分にリソースが確保できる場合にはできるだけ環境丸ごとコンテナ化する事をオススメ致します。