Docker for Windowsで環境構築してみる – その壱

ことはじめ

DockerをWindowsで動かすために、Windows 10 HomeをWindows 10 Proに有償でアップデートした。1万円以上したが、勉強のために技術書3冊でも買えばそれくらい行くでしょ、的な感じなので、高いとは思わなかった。

それとは別に、業務で同僚から「そろそろDockerやりませんか?」と言われているのもあり、技術担当としては慣れ親しんだVagrantとは別に、Dockerを使ってみることにした。

『やっぱDockerわかんね!Vagrantでいいべ!』と後から言われたが

俺自身、生粋の開発者でもなければ生粋の理系でもない。たまたま9歳からX1f、MSX、SC-3000なんかのマイコンで、行番号BASIC+Z80アセンブルなんか使ってゲーム作ったりしてただけ。専攻的なものと言えばおそらく美術系に分類になるかと。

そんな訳の分からん事やってきて最終的に技術屋になった奇特なおっさんなので、正直こう言った新しいテクノロジーに対しては素直に理解できないことが多い。

つまり、考えるより体が覚えれば良いじゃん!的な、大脳から小脳へ情報が移動するまでやらなければ理解できないタイプだ。

別の言い方をするなら、”できる出来ない”や“知ってる知らない”とか関係なく、“とにかくやる”という流れだ。

なんでもかんでもやる前から色々考え過ぎるのは短命の素だし、そんなクソみたいな予測コストは生産性下げるだけだ。だからなんでも直ぐにやった方が良し。

手段は不格好でもいい、とにかく始めよう。

残念ながら経験則的にこうでも書いておかないと、“正論が常に解決策だと勘違いしてる残念な理系”や、“使う人間のほうが圧倒的に多いのに作る人間を常に最優先しちゃってるゆとり開発者”なんかがヤル気満々で重箱の隅をつつき始め、カジュアルにマウンティングしてくる事が多い。

うんざりすること

書籍や、WebでDockerをググった時なんか、本当にうんざりするほど同じ内容しかヒットしない。

  • DockerToolsの話(Docker for Windowsが出る前の記事だろうな)
  • コンテナとは?VirtualBoxとの違いは?などの図の説明

うんざりだ。

VirtualBoxとDockerの違いのモデル図なんか一度見れば誰でもだいたい意味がわかる。大量にあるノイズ記事同士で似たような図をわざわざこしらえてるようだけど、こう言った人たちってのは車輪の再開発とかそういうのが嫌いなんじゃねーの?とジョークの一つでも飛ばしてみたくなる。

正直そんなモデル図なんか見てるより、ハンバーガーの断面図見てる方が楽しいし愉快だ。

それに、ほとんどがコンテナとは!から始まり、Linuxの話が続き、そしてMacやWIndowsで使うためのソフトのインストール、その後インフラ向けの専門用語が怒涛の如く文章を埋め尽くし、いきなりDockerfileの書き方(しかも説明ほとんどなし)で終わってるじゃねーか。書いてる最中に脳が停止でもしたのか?

車の免許取得したい人に車の作り方や構造などを事細かに教えるのはバカであり、そんな知識は本人が勝手に覚えたければ覚えればいい話。目的は、運転に関する知識をみにつける事だ。

というわけで、そんな似たり寄ったりの目くそ鼻くそ記事なんかどうでもいい。俺達はDockerの構造を知りたいのではなく、Dockerの使い方を知りたいんだよ。そして事例が知りたいんだよ(こういう記事ってプログラマじゃなくてインフラ屋とかが書いてるからだろうな)。

つまり端的にいうと、ネット上にノイズ撒き散らしてるんじゃねぇぜって話。スペースデブリならぬネットデブリだわ。シナ人かよ。いい加減にしなされ。この豚肉が。

概要

  • やりたいこと
    • WindowsはWeb開発に向いてないのでCentOSとかFedoraとかの環境がほしい
    • NodejsのフレームワークKOA、meteorなんかをいじってみたい
    • DBはMySQL、Redisなんかを使ってみたい
    • WebとDBでコンテナを分けたい
    • 分けたコンテナを連携させたい
  • 環境
    • Windows 10 Pro
    • Docker for Windows
      • Kitematic(これは別にいらないかな)
    • CMDer(コマンドラインツール)
      • Git BashとかNodejsとか入れてるなら全部これ1つでOK
      • PowerShellとかいうクソアプリは存在自体が犯罪

前提条件

  • Hyper-VのVMに外部ネットワークアダプタが追加されていること
    1. スタート → Windows 管理ツール → Hyper-Vマネージャ
    2. MobyLinuxVMクリック → 仮想スイッチマネージャ
    3. 新しい仮想ネットワークスイッチ仮想スイッチの作成ボタン
    4. インターネットに接続してるアダプタを選択 → 外部ネットワークなど任意の名前をつけOKする
  • Dockerの設定でCドライブが共有済みになっていること
    1. タスクトレイのDockerアイコン右クリック → Setting
    2. Shared DrivesでCドライブをチェック → Apply
    3. Docker再起動して反映
  • イメージもコンテナもすべてなにもない状態

設計を考える

  • CentOS 7系にNodejsをインストールしたコンテナ
    • Webコンテナとする
  • MySQLかRedisのコンテナ
    • DBコンテナとする
  • WebコンテナからDBコンテナにアクセス可能にする

小手調べ

早速何も考えずに本能の赴くままにDockerを前頭葉にブチ込もうじゃないか。

CentOS7のイメージを落とす

なんでCentOS7かというと、7になってSysVinit系からsystemd系になったのと、ファイルシステムがextからxfsになったとか、かなり大きく変化を遂げたので、これから覚えるのに最適だからだ(Fedoraばっかり使ってた俺としてはこの方が馴染みがあるし)。

こうやるとCentOSでタグが7のイメージを落とせる。タグにバージョンを設定しておくというのがイメージ作成時のポリシーなんだろうな。

CentOSに入ってみる

Dockerイメージを起動するだけならrunサブコマンドで良いらしい。

しまった、タグを指定しなかったため、改めて別のcentos:latestをダウンロードしやがった(ないものをrunサブコマンドで起動するとわざわざリモートから落としてくれる親切設計だけど、俺にとってはただのおせっかい迷惑機能。俺はゆとり脳ではないので)。

仕方がないのでcentos:latestは消す。

気を取り直してcentos:7を起動する。

これで起動したはず。psサブコマンドで確認して見る。

何も表示されない。あっという間に終了してしまったようだ。

たしかデーモンとして起動する-dオプションがあったはず。

というわけで、-dをつけて起動し直してみる。

これでも直ぐに終了してしまう。

次は最後にシェル名を渡して試してみる。

早速確認して見る。

これだとちゃんと起動しっぱなしになった(上記はCREATEDとPORTSとNAMESは省略)。てか、よく考えたらそうだよな、イメージ起動するというより、シェルを実行したいわけだから。

では、改めて接続してみよう。

このcentos7コンテナに接続するにはattachサブコマンドを使うらしい。そしてコンテナIDを指定するらしい。

ほほぅ、rootで入るのか。

Vagrantがvagrantユーザで、パスワードなしでsudoできるけど、DockerイメージのCentOSだといきなりrootか。男らしいな。気に入った。

コンテナIDは別名を付けたほうが良い気がする。--nameオプションでつけられるのかな。あとでやってみよう。

とりあえずCentOSに入れたので、いつもやってるアップデートを行う。

アップデートは特になかった。

次は開発ツールを入れてみる。

NodeJSをインストールする

では早速NodeJSを入れてみる。まずはリポジトリの設定だ。今の時点での最新バージョンは7だけど、最新すぎて色々ありそうなので、1つ前の6を入れることにする。

詳しくはここに書いてある。
Github – nodesource/distributions

いろいろなメッセージが画面に表示され、最後にこんなメッセージが表示された。

ほほぅ、あとはyumコマンドでNodeJSをインストール出来るのか。

今回はDockerコンテナだし、試しに挑戦してるだけなので、Nodebrew的なバージョン切り替えなどのツール入れないし、これで直接入れてみることにする。

おけ。ちゃんとマイナーバージョンが偶数だ。
それではインスコする。

これでインスコ終了。バージョンを表示してみる。

いいね。

イメージを保存する

起動してるコンテナに接続するためにattachサブコマンドを使ったが、この場合、コンテナ内からexitすると、コンテナが終了してしまう。なので、現状を維持したままコンソールに戻るため、Ctrl+PCtrl+Qをタイプする(execサブコマンドならコンテナから抜けてもコンテナは終了しない)。

Linuxは起動後最初のプロセスが1番として立ち上がり、そこからプロセスがフォークされて行くが、attachサブコマンドは常にこの1番に紐づくようなので、1番の状態でexitすると当然最長老であるプロセス1番が終了してLinux自体も終了する、ということらしい。なるほど。

いったんこれでコンテナから抜けて、今の状態をまるごとイメージとして保存してみる。これまでの流れは以下。

  1. 自分好みのLinuxを作るために、もととなるCentOS7を落としてきた
  2. 落としてきたCentOS7を自分なりにセットアップした
  3. セットアップしたCentOSをイメージ化したい
    • この時点で最初のCentOS7は不要になる

コンテナからイメージを作るには、commitサブコマンドを使うらしい。

早速使ってみる。

本来コンテナは停止させてからイメージ作成するのが良いらしいが、今別に誰も接続してないし、停止しなくても行けるんじゃん?というよく分からん自信があったので、止めないことにする。

まずはコンテナIDを調べる。

※不要な部分は省略

次に、第一引数にコンテナID、第二引数に作りたいイメージ名でcommitサブコマンドを叩く。

しばらくするとプロンプトに戻るので、イメージを確認して見る。

ほほぅ、なかなか良いじゃないか、Dockerよ。

ちなみに毎回コンテナ起動してログインして手動でセットアップはせずに、予め手順を記述したDockerfileというファイルを用意しておけば、毎回手動でやらなくても済むとのこと。

なるほど、Ansibleでいうplaybookみたいなもんかな。プロビジョニング的な。

すでにイメージを作ったので安心な状態になったし、せっかくだからDockerfileを使う方法も試してみる。

って言うよりむしろ、安心しすぎてもうどうでも良くなった。node-webコンテナなんかもう消してしまおう。

消えやがれ。

Dockerfileを作る

ざざっと調べてみた結果、以下のような感じで記述すればOKらしい。

  • FROMで元のイメージを指定
  • MAINTAINERはDockerfileを作った人の名前を書く
  • RUNで各種コマンド

というわけで、こんな感じでホームディレクトリにDockerfileを作ってみた。

C:\Users\ogaaaan\Dockerfile

centos:7をベースに各種yumやcurlでのセットアップするという内容。単純に今までやったことをRUNに記述しただけ。おそらくこれでいいはず。Dockerfileという名前で保存した。

Dockerfileの内容を実行するにはbuildサブコマンドをつかうんだけど、ディレクトリを指定するらしい。なんのディレクトリだ?よくわからんので適当に実行してみる。

> docker build C:\User\ogaaaan\

何かが始まった。HDDのアクセスランプが点灯しっぱなしなので、とりあえず消灯するまで待つ事に。

エラーだ。

よく分からんけど、Dockerfileの記述は多分間違えてないと思うので、コマンドを見直してみる。

buildtオプションでイメージに名前をつけられるので、ついでにdocker-testというイメージ名にしてみる。

ホームディレクトリに、わかりやすい用にイメージ名と同じdocker-testフォルダを作り、その中にDockerfileを移動。以下のコマンドを実行してみた。

実行したディレクトリはC:\User\ogaaaan\
Dockerfileの場所はC:\User\ogaaaan\docker-test\Dockerfile

色々始まった。なるほどこれで動いた。
とは言え、色々赤文字でWarningとか出てるだよなぁ。

NodeJSのインストールでのWarning。

トランザクション時のラー。

しかし一応、完了メッセージは出てる。

そのあと

的なものも白文字で表示された。

むむー、直接実行したらこういうのは出なかったので、おそらくdocker buildコマンドで実行した際特有のものだとは思うけど、気持ち悪いな。

今回はテスト的な実行なのでスルーするけど、あとでちゃんと調べておく。今の状態なら直接手でアップデートとかセットアップしてcommitサブコマンドでイメージ化したほうが良いと思う(プロビジョニング系はたいてい疲弊する割には効果が薄いので100%完璧にやろうなんてはなっから思ってない)。

開始とか終了とか

で、完成したイメージを見てみる。

例によって関係ないイメージと、幾つかの項目は省略した。
一番上に正しくdocker-testイメージが完成した。

d4w/nsenterというのは各コンテナに接続するためにあるらしいので、スルーしておいて大丈夫かと。あとでちゃんと調べておく。

うん、Warningがでなければこれはすごく便利だ。Dockerfileというテキストファイルになってるので、どういう構造になるのかが誰でもわかるし、カスタムも容易。

それでは今作ったイメージを早速コンテナ化して実行してみる。
まずはdocker-testイメージからdocker-testコンテナを起動だ(別に違う名前でも良いけど)。

無事に接続出来た。

明示的にこのdocker-testコンテナを削除しない限りWindowsを再起動しても残るので、別の日に作業を続けることが出来る。

試しにWindowsを再起動してみた。再起動後、psサブコマンドで確認して見る。

すでに起動しているコンテナであればpsサブコマンドだけで確認出来るが、起動してないコンテナは表示されない。その為、サブコマンドにオプションaをつける。

docker-testコンテナはまだ存在しているが、STATUSがExisted なので停止している。作業するにはまずこの停止してるコンテナを叩き起こす必要がある。

停止しているコンテナはstartサブコマンドで起動させる。Vagrantでいうvagrant upみたいなもんだ。

あとはまたattachサブコマンドで接続するという流れになる。

これで基本的なコマンドはだいたいOKじゃないかな。小手調べは終わり。

次は具体的に作業を開始するための準備をしてみる。