Windows 10 HomeのKUSANAGI Runs on DockerでWordmoveの結末は(後編)

なかなかKUSANAGI Runs on DockerでWordmove導入まで辿り着かないですが、前回の続きにトライしていきたいと思います。

結論から言うと、解決できなかったので、お時間のある方のみご照覧ください。

dockerコンテナ間のマウントが上手くいってない?

前回、 /var/run/docker.sock を全コンテナで使えるようにしたつもりだったんですが、docker-compose.ymlの設定が間違っていた可能性もありそうです。

⇩  また、ディストリビューションの違いも影響してくるようです。

Docker in Docker のメモ書き - 水底

ということで、docker-compose.ymlの見直し。今現在こんな感じになっています。

version: '2'

services:
  kusanagi-data:
    container_name: kusanagi-data
    image: busybox
    restart: always
    stdin_open: true
    tty: true
    volumes:
      - /var/lib/mysql
      - /etc/nginx/conf.d
      - /etc/httpd/conf.d
      - /etc/kusanagi.d
      - /home/kusanagi
      - /var/run/docker.sock:/var/run/docker.sock
    command: /bin/sh

  kusanagi-nginx:
    container_name: kusanagi-nginx
    image: primestrategy/kusanagi-nginx:1.10.0-1
    environment:
      PROFILE: kusanagi
      FQDN: localhost
      WPLANG: ja
      BCACHE: "off"
      FCACHE: "off"
    volumes_from:
      - kusanagi-data
    links:
      - kusanagi-php7:php
      - kusanagi-mariadb:mysql
      - ruby:ruby
    ports:
      - "80:80"
      - "443:443"

  kusanagi-mariadb:
    container_name: kusanagi-mariadb
    image: mariadb:10.0.24
    environment:
      MYSQL_ROOT_PASSWORD: my-secret-pw
      MYSQL_USER:     user
      MYSQL_PASSWORD: password
      MYSQL_DATABASE: wordpress
    volumes_from:
      - kusanagi-data

  kusanagi-php7:
    container_name: kusanagi-php7
    image: primestrategy/kusanagi-php7:7.0.6-1
    links:
      - kusanagi-mariadb:mysql
    volumes_from:
      - kusanagi-data

  ruby:
    container_name: ruby
    image: ruby:2.4.1-alpine
    tty: true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    volumes_from:
      - kusanagi-data
    

と設定していました。ちなみに、仮想マシン内に入ってコンテナ内でdockerコマンドがnot foundとなっています。

f:id:ts0818:20170603201801j:plain

UnionFS(Union FileSystem)とは

Dockerのドキュメントによると、 コンテナ間でデータをやりとりする場合、

コンテナ内やコンテナ間でデータを管理できるかを議論します。

データを Docker で管理する、2つの主な手法を見ていきます。

  • データ・ボリュームと、
  • データ・ボリューム・コンテナです。

コンテナでデータを管理する — Docker-docs-ja 1.9.0b ドキュメント

となっていて、データ・ボリューム(data-volume)とは、

データ・ボリューム (data volume) とは、1つまたは複数のコンテナ内で、特別に設計されたディレクトリであり、 ユニオン・ファイルシステム (Union File System) をバイパス(迂回)するものです。データ・ボリュームは、データの保持や共有のために、複数の便利な機能を提供します。

  • ボリュームはコンテナ作成時に初期化されます。コンテナのベース・イメージ上で、特定のマウント・ポイント上のデータが指定されている場合、初期化されたボリューム上に既存のデータをコピーします。
  • データ・ボリュームはコンテナ間で共有・再利用できます。
  • データ・ボリュームに対する変更を直接行えます。
  • イメージを更新しても、データ・ボリューム上には影響ありません。
  • コンテナ自身を削除しても、データ・ボリュームは残り続けます。

データ・ボリュームは、データ保持のために設計されており、コンテナのライフサイクルとは独立しています。そのため、コンテナの削除時、Docker は 決して 自動的にボリュームを消さないだけでなく、コンテナから参照されなくなっても”後片付け”をせず、ボリュームはそのままです。

コンテナでデータを管理する — Docker-docs-ja 1.9.0b ドキュメント 

となっています。 UnionFS (Union FileSystem)とは何なのかというと、

UnionFSLinuxFreeBSD 向けのファイルシステムサービスであり、他のファイルシステムに対する union mount英語版 を実装している。UnionFS により、ブランチとして知られる、分離したファイルシステムのファイルやディレクトリを透過的に重ねることができ、単一の一貫したファイルシステムを形成する。新しい仮想的なファイルシステム内で、マージされたブランチ内の同じパスを持つディレクトリの中身を単一のマージされたディレクトリ内で一緒に見ることになる。

ブランチをマウントするとき、あるブランチの、他のブランチに対する優先度が指定される。そのため両方のブランチが同じ名前のファイルを含むとき、あるブランチがもう一方のブランチよりも優先される。

異なるブランチは読み込み専用にも読み書き可能にもできるので、仮想的なマージされたコピーへの書き込みは特定の本当のファイルシステムへ向けられる。これによりファイルシステムが書き込み可能のように見えるが、実際にファイルシステムを変える書き込みを可能にしないようにできる。これはコピーオンライトとしても知られている。Live CD の場合のように、メディアが物理的に読み込み専用のときに、これは魅力的である可能性がある。

UnionFS - Wikipedia 

となっていて、分かりにくいのですが、下記サイトによると、

» まとめて束ねるUnionFSの不思議な世界 TECHSCORE BLOG

AというディレクトリとBというディレクトリがあった場合にCというディレクトリにまとめて考えることができるようです。(あくまで仮想的にということで実際には別々らしい?)

⇩  下記サイトが詳しいです。

dockerが使うUnionFileSystemを僕なりに解釈した - see the elephant

 

Dockerコンテナの中にDocker Clientが必要?

セキュリティ的にはマズイらしいんですが、Dockerコンテナのどれか1つにはDocker Clientを入れないとDockerコンテナの中でdockerコマンドが使えないみたいです。

Docker コンテナ内から他の Docker コンテナに docker exec する | ALTUS-FIVE

DockerのAPI versionがDockerのデーモンに依存してるらしいんですが、

The version of the API you should use depends upon the version of your Docker daemon. A new version of the API is released when new features are added. The Docker API is backward-compatible, so you do not need to update code that uses the API unless you need to take advantage of new features.

To see the highest version of the API your Docker daemon and client support, use docker version:

Docker Engine API and SDKs | Docker Documentation

Dockerのデーモンってどれ?と思ったんですが、

docker versionコマンドの使い方(実例付) – めもたんす

 によると、Dockerサーバー(デーモン)という認識で良いみたいです。

ちなみに、下記画像は自分のホストOS(Windows 10 Home)のDockerの情報ですが、Server: = デーモン ってことみたいですね。

f:id:ts0818:20170605102606j:plain

おそらく、今回、Dockerコンテナ側 にDocker Clientをインストールするのですが、そのバージョンをホストOS側のDockerのバージョンと合わせとけってことですかね?

つまり、Client:のVersionとServer:のVersionが合ってれば問題ないかと思われます。

Server:で『 API version:  1.29 (minimum version 1.12)』となっているので、Client:のAPI versionが1.12以上必要ってことですかね? 

Dockerコンテナの中にDocker Clientをインストー

ということで、Releases · moby/moby · GitHub にDocker Clientの一覧があるようです。

kusanagi-data(WordPressがインストールされてる)コンテナは、busyboxというdockerイメージを元に作られてるらしく、コマンドが大量に準備されてるのですが、

f:id:ts0818:20170605220606j:plain

docker@kusanagi-machine:~$ docker exec -it kusanagi-data bin/sh
/ # busybox
BusyBox v1.26.2 (2017-05-15 21:05:54 UTC) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Licensed under GPLv2. See source distribution for detailed
copyright notices.

Usage: busybox [function [arguments]...]
   or: busybox --list[-full]
   or: busybox --install [-s] [DIR]
   or: function [arguments]...

        BusyBox is a multi-call binary that combines many common Unix
        utilities into a single executable.  Most people will create a
        link to busybox for each function they wish to use and BusyBox
        will act like whatever it was invoked as.

Currently defined functions:
        [, [[, acpid, add-shell, addgroup, adduser, adjtimex, ar, arp, arping,
        ash, awk, base64, basename, beep, blkdiscard, blkid, blockdev,
        bootchartd, brctl, bunzip2, bzcat, bzip2, cal, cat, catv, chat, chattr,
        chgrp, chmod, chown, chpasswd, chpst, chroot, chrt, chvt, cksum, clear,
        cmp, comm, conspy, cp, cpio, crond, crontab, cryptpw, cttyhack, cut,
        date, dc, dd, deallocvt, delgroup, deluser, depmod, devmem, df,
        dhcprelay, diff, dirname, dmesg, dnsd, dnsdomainname, dos2unix, dpkg,
        dpkg-deb, du, dumpkmap, dumpleases, echo, ed, egrep, eject, env,
        envdir, envuidgid, ether-wake, expand, expr, fakeidentd, false,
        fatattr, fbset, fbsplash, fdflush, fdformat, fdisk, fgconsole, fgrep,
        find, findfs, flock, fold, free, freeramdisk, fsck, fsck.minix, fstrim,
        fsync, ftpd, ftpget, ftpput, fuser, getopt, getty, grep, groups,
        gunzip, gzip, halt, hd, hdparm, head, hexdump, hostid, hostname, httpd,
        hush, hwclock, i2cdetect, i2cdump, i2cget, i2cset, id, ifconfig,
        ifdown, ifenslave, ifplugd, ifup, inetd, init, insmod, install, ionice,
        iostat, ip, ipaddr, ipcalc, ipcrm, ipcs, iplink, ipneigh, iproute,
        iprule, iptunnel, kbd_mode, kill, killall, killall5, klogd, last, less,
        linux32, linux64, linuxrc, ln, loadfont, loadkmap, logger, login,
        logname, logread, losetup, lpd, lpq, lpr, ls, lsattr, lsmod, lsof,
        lspci, lsusb, lzcat, lzma, lzop, lzopcat, makedevs, makemime, man,
        md5sum, mdev, mesg, microcom, mkdir, mkdosfs, mke2fs, mkfifo,
        mkfs.ext2, mkfs.minix, mkfs.vfat, mknod, mkpasswd, mkswap, mktemp,
        modinfo, modprobe, more, mount, mountpoint, mpstat, mt, mv, nameif,
        nanddump, nandwrite, nbd-client, nc, netstat, nice, nmeter, nohup,
        nsenter, nslookup, ntpd, od, openvt, passwd, patch, pgrep, pidof, ping,
        ping6, pipe_progress, pivot_root, pkill, pmap, popmaildir, poweroff,
        powertop, printenv, printf, ps, pscan, pstree, pwd, pwdx, raidautorun,
        rdate, rdev, readahead, readlink, readprofile, realpath, reboot,
        reformime, remove-shell, renice, reset, resize, rev, rm, rmdir, rmmod,
        route, rpm, rpm2cpio, rtcwake, run-parts, runlevel, runsv, runsvdir,
        rx, script, scriptreplay, sed, sendmail, seq, setarch, setconsole,
        setfont, setkeycodes, setlogcons, setserial, setsid, setuidgid, sh,
        sha1sum, sha256sum, sha3sum, sha512sum, showkey, shuf, slattach, sleep,
        smemcap, softlimit, sort, split, start-stop-daemon, stat, strings,
        stty, su, sulogin, sum, sv, svc, svlogd, swapoff, swapon, switch_root,
        sync, sysctl, syslogd, tac, tail, tar, tcpsvd, tee, telnet, telnetd,
        test, tftp, tftpd, time, timeout, top, touch, tr, traceroute,
        traceroute6, true, truncate, tty, ttysize, tunctl, ubiattach,
        ubidetach, ubimkvol, ubirename, ubirmvol, ubirsvol, ubiupdatevol,
        udhcpc, udhcpd, udpsvd, uevent, umount, uname, unexpand, uniq,
        unix2dos, unlink, unlzma, unlzop, unshare, unxz, unzip, uptime, users,
        usleep, uudecode, uuencode, vconfig, vi, vlock, volname, wall, watch,
        watchdog, wc, wget, which, who, whoami, whois, xargs, xz, xzcat, yes,
        zcat, zcip

curlコマンドは入ってないという...どうなってんですかね。wgetが入っているみたいなので、wgetcurlコマンドをインストールするしかないですね。(rpmでもcurlをインストールできるらしいですが、rpm版は古いものしかないそうです。)

【PHP】cURLをインストールして有効化する手順 | Step On Board

makeコマンドも入ってない...。

⇩  下記サイトによると、busyboxはOSイメージではないようです。

Dockerにおけるデータ専用コンテナ、KVM仮想化環境からの移行 | Think IT(シンクイット)

どおりで、ディストリビューションのパッケージマネージャがはいってないわけですね、RPMは入ってたけど。

busyboxコンテナにmakeコマンド並びにコンパイラなどのコマンドの導入が難しそうなので、wgetでdockerクライエントが取得できねば潔く諦めます。

 

dockerクライエントはkusanagi-nginxコンテナに

プライムストラテジーさんのdockerイメージリポジトリKUSANAGI Runs on Dockerについていろいろ載ってました。

https://hub.docker.com/r/primestrategy/kusanagi-nginx/~/dockerfile/

kusanagi-nginxコンテナにはOSとしてCentOS7が入ってるみたいなので、yumが使えそうなので、kusanagi-nginxにdockerクライエントをインストールしていく方向に変更することにしました。

あらかじめ、docker-compose.ymlのあるディレクトリに移動してます。(あとで、docker-composeを実行するため)

docker-machine ssh kusanagi-machine

f:id:ts0818:20170609101430j:plain

指示通り、『docker-machine env 起動させたい仮想マシン名』を実行します。

docker-machine env kusanagi-machine

f:id:ts0818:20170609102238j:plain

TLS証明書を再生成します。

 docker-machine regenerate-certs kusanagi-machine

f:id:ts0818:20170609102424p:plain

仮想マシンが起動してるか確認します。STATEがRunningになっていればOK。

docker-machine ls

f:id:ts0818:20170609103014j:plain

 

docker-composeコマンドでdockerコンテナを一斉に起動します。

docker-compose -p kusanagi-machine up

f:id:ts0818:20170609103301j:plain

ConEmuで新たにbash(Msys2-64)を 起動し、dockerのバージョンを確認

docker version

f:id:ts0818:20170609104618j:plain

 仮想マシンsshログインします。

docker-machine ssh kusanagi-machine

f:id:ts0818:20170609103848j:plain

dockerコンテナ(kusanagi-nginx)にexecします。

docker exec -it kusanagi-nginx

f:id:ts0818:20170609104228j:plain

https://github.com/moby/moby/releases でdocker versionに一致するものをインストールしていきます。

f:id:ts0818:20170609105402j:plain

ページをスクロールしていくと下のほうにダウンロードについて記載されています。

f:id:ts0818:20170609105515j:plain

Linux 64bits tgz』というものでOKだと思われます。

curl -fsSL https://get.docker.com/builds/Linux/x86_64/docker-17.05.0-ce.tgz \
  | tar -xzC /usr/local/bin --strip=1 docker/docker

f:id:ts0818:20170609110121j:plain

dockerコンテナ内でdockerコマンドが動きました!

f:id:ts0818:20170609110640j:plain

dockerコンテナ(kusanagi-nginx)内でdockerコンテナ(ruby)のコマンドが実行できました。

f:id:ts0818:20170609111047j:plain

 だが、しかし、dockerコンテナ(kusanagi-data)内でdockerコマンドは使えないという...dockerクライエントをインストールしたコンテナでしか使えないという。(てっきり1つのコンテナにインストールすれば他のコンテナからでもdockerコマンドが使えると思っていたのですが、インストールしたコンテナからしか使えないっぽいです)

 

ホストOS経由でkusanagi-dataコンテナ(busybox)にdockerクライエントをインストールしようと思ったけど、dockerコンテナ同士でコピーできるらしい

もうめちゃくちゃですが、他に方法が思いつかないのでdockerコンテナ(kusanagi-nginx)にインストールしたdockerクライエントをホストOSとマウントしてコピーし、 その後、ホストOSとdockerコンテナ(kusanagi-data)でマウントしてdockerクライエントを導入していく方向で、と思ったけどコンテナ同士でファイル渡せるらしい。

Copying data between Docker containers – Grigoriy Chudnov – Medium

でも、よくよく見ると、一回コンテナのファイルをホストにコピーして、ホストからコンテナにコピーしてるようです。

ややこしいのが、ホストというときは、ホストOSとDocker_Hostのどちらを指してるのかがよく分からないところですね。

 

おまけに、ホストOS側でdocker psコマンドを実行しようとしたら、

f:id:ts0818:20170610143436j:plain

docker daemon is not  runningってなったので、仮想マシンが起動して、dockerコンテナも起動してても、dockerデーモン(Server)が起動してなかったってことは、dockerコンテナってDockerデーモン(Server)無くても動くんだ?という衝撃でしたが、

Docker - dockerコマンドをコマンドプロンプトから利用(66952)|teratail

の手順を実行したところ、

f:id:ts0818:20170610144224j:plain

docker psコマンドが使えるように。 

f:id:ts0818:20170610144503j:plain

$ docker ps
CONTAINER ID        IMAGE                                   COMMAND                  CREATED             STATUS              PORTS                                      NAMES
719dbaffe91b        primestrategy/kusanagi-nginx:1.10.0-1   "/docker-entrypoin..."   26 hours ago        Up 3 hours          0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   kusanagi-nginx
965bc41ca3b2        primestrategy/kusanagi-php7:7.0.6-1     "php-fpm"                5 days ago          Up 3 hours          9000/tcp                                   kusanagi-php7
01beb80c2303        mariadb:10.0.24                         "/docker-entrypoin..."   5 days ago          Up 3 hours          3306/tcp                                   kusanagi-mariadb
8164d61dc5cf        ruby:2.4.1-alpine                       "irb"                    5 days ago          Up 3 hours                                                     ruby
ac50ff4f02d7        busybox                                 "/bin/sh"                5 days ago          Up 3 hours                                                     kusanagi-data

で試しにdocker cpコマンドしてみたら、

f:id:ts0818:20170610145123j:plain

ことごとく弾き返される始末。

Dockerでホストとコンテナ間でのファイルコピー - Qiita

 という紆余曲折を経て、docker-machine ssh仮想マシンにログイン後、docker cpすることになりました。

f:id:ts0818:20170610142922p:plain

コンテナ(kusanagi-data [BusyBox])に/usr/local/binとなるようにディレクトリを作成。mkdirに-pオプションを付けると一度にフォルダを作成できるようです。

複数階層のディレクトリを一度に作成する:Linux最強Tips集

docker exec -it kusanagi-data /bin/sh
mkdir /usr/local/bin
mkdir: can't create directory '/usr/local/bin': No such file or directory
mkdir -p /usr/local/bin
ls /usr/local/
bin

f:id:ts0818:20170610152029j:plain

一旦、exit してコンテナkusanagi-data [BusyBox])の外に出ておきます。

コンテナ(kusanagi-nginx [CentOS7])からDocker_Hostにコピー 

docker cp 719dbaffe91b:/usr/local/bin/docker docker

f:id:ts0818:20170610150136j:plain

ホストからコンテナ(kusanagi-data [BusyBox])にコピー

docker exec -i kusanagi-data bin/sh -c 'cat > /usr/local/bin/docker' < docker

f:id:ts0818:20170610152841j:plain

コンテナkusanagi-data [BusyBox]) にdockerがコピーされました!

f:id:ts0818:20170610153126j:plain

dockerコマンドを試してみます。

f:id:ts0818:20170610153420j:plain

権限の問題で怒られましたが、あと一息!

chmod +x /usr/local/bin/docker

f:id:ts0818:20170610153704j:plain

コンテナkusanagi-data [BusyBox])でdockerコマンドが使えるようになりました !

 

Wordmoveコマンドをインストール...できない

ようやく本題に入れます、ここまで長かったですね。さっそく、コンテナ(ruby[ruby2.4.1])のgemコマンドでwordmoveをインストールします。WordPressがインストールされてるディレクトリに移動しておきます。

cd /home/kusanagi/kusanagi/DocumentRoot/
docker exec -it ruby gem install wordmove

f:id:ts0818:20170610154951j:plain

なんとかwordmoveがインストールされたようです、と思ったんですが.... 

f:id:ts0818:20170610155515j:plain

wordmove: not found って....もしや、 コンテナ(ruby[ruby2.4.1])側にインストールされたってことですかね?

f:id:ts0818:20170610160439j:plain

やはり、 コンテナkusanagi-data [BusyBox])に変化は見られないっす(涙)

f:id:ts0818:20170610160740j:plain

ConEmuで新しくbash(Msys2-64)を開いて、仮想マシンsshした後、コンテナ(ruby[ruby2.4.1])を見ると...確かにMovefile作成されてるけど、こっちに欲しいわけじゃないんだよね~(悲)

f:id:ts0818:20170610161109j:plain

Movefileの中身もなんか上手くいってないっぽいですね。

f:id:ts0818:20170610162644j:plain

 

結論は、コンテナkusanagi-data [BusyBox])に直接RubyをインストールしてWordmoveコマンドをインストールするしかなさそうですね。

KUSANAGI Runs on Docker の公式のサイトでwordmoveの使い方が紹介されるまで待つしかないですかね、そもそもKUSANAGI Runs on Dockerでwordmoveを使うのが正解なのかも分からないですしね。

 

ローカル環境にWordPressを構築するのにMacの場合は、『Local by Flywheel』ってものが便利みたいです。(WindowsでもBeta版の利用ができるようになったようです、相変わらずWindowsは疎外されてますね~。)

f:id:ts0818:20170610171300j:plain

簡単にWordPressのローカル環境がつくれるLocal by Flywheelを使ってみた – Snaplog

WordPressのローカル環境のためのGUIツール"Local by Flywheel"が便利 - Capital P

WordPressをローカルに構築するならLocal by Flywheelが便利

ただ、ローカル環境から本番環境へのデプロイについてはあんまり言及されてないみたいですが、なんか上手い方法を開発していって欲しい感じです。

 

今回も全力で無駄な時間を使ってしまった 。(1週間ぐらい使って、なんという体たらく!最悪な結末ですね)

 

2017年6月16日 追記

kusanagi-nginx [CentOS7])コンテナの /home/kusanagi/kusanagi/DocumentRoot/に

WordPressがインストールされてました。

kusanagi-nginx [CentOS7])と(kusanagi-data [BusyBox])の両方にWordPressがインストールされてるっぽいです。

f:id:ts0818:20170616180458j:plain

kusanagi-nginx [CentOS7])コンテナは、CentOS7がインストールされてるのでyumが使えるので、 kusanagi-nginx [CentOS7])コンテナに直接Rubyインストールしてgem installでwordmoveを導入すればWordMoveイケそうな気がします。