この記事は下書き供養 Advent Calendar 2018の05日目の記事です。

というわけで公開は2018年12月05日ですが、書いたのは2017年06月です。記事の日付は後者の方を設定しました。ちなみに開催はもうちょっと前で2017年04月でした。あらやだ怠惰。

当日利用したリソース群はこちらにまとまってます。

ちなみにWordPressやるならその名の通り library/wordpress というDocker公式イメージが公開されてるので、そっち使う方が楽だと思います。

(以下、下書きの状態であったもの。書きあがってるっぽいのでそのまま。)


当方初心者なんだけど、まわりにやってる人が少なくて、利用者が増えたらいいなーそんでもって誰か詳しくなっておれに教えてくれたらいいなーくらいの感じでやりました。

本当は詳しい人にも来てもらって駄目出しされつつ進行したかったんだけど、日程が合いませんでした。先にそっち合わせとけっていう。

というわけで、やった内容を書いておきます。「利点について」→「単語と知識」→「手を動かす」という流れです。

Dockerとは何か

端的に言うと、

  • 仮想マシンです。
  • 仮想マシンじゃないです。

「使う」側からすると自分のマシン(物理)の中に別のマシンが仮想的に用意されて、その中で色々走ったりするよーっていう感じ。実際は「仮想マシン」と呼ばれる技術とは別物で、仮想ハードウェアをすっ飛ばして直接物理リソースを使うとかなんかそういう?違い?があるらしい。

あとコンテナを小分けにしてっていうのもVM方面にだけ慣れてるとすぐには出てこない発想かなーと思う。

何が嬉しいのか

VMでも何でもいいんだけど、基本的にはホストマシンと分けて環境を作れる嬉しさというものがあると思ってます。ほら汚染とかバージョン管理とかさ。

開発者向けには

  • 開発環境を簡単に用意できる
  • 実際こんな手順
    1. git clone
    2. docker-compose up
    3. やったね
  • いらない
    • Node.js, Ruby, Python, etcのインストール
    • Sass, Babel, Rails, image magic, etcのインストール
    • ウェブサーバの設定
    • ネットワークの設定(たぶん)

誰かがDocker環境を用意してくれていて、それを使うという状況です。

データベースの用意とか、 gem install sass とか、そもそも言語環境の用意とかそういうのをすっ飛ばして、一発でwatchとかローカルサーバとかを起動できます。

Docker自体もWin/MacともにGUIでインストールできるので、準備の難易度は低いかと思ってます。(でもWindowsだとHyper-Vが必須だったりするのかな? 自分は元々使ってたし、周りが皆Macなんで調べてない。)

上位開発者には

今度はDocker環境を用意する側のひと。Makefileとかnpm scriptを用意するあたりの人達。

  • 環境の詳細が文書化される
  • 環境を他の人と共有できる
  • 過去に作った環境を再利用したり拡張したりできる

自分のマシンにぽちぽちインストールして環境作って、いざそれを他の開発者にも使ってもらおうとすると、割と面倒くさかったりするじゃないすか。試行錯誤してると文書化するの億劫だし。

そういうのが全部 Dockerfile と docker-compose.yml に残るので、「えーとあれこれってどうやって入れたんだっけ?」「そもそも入れたっけ?」みたいなのがなくなります。文書に残っているので、環境の共有はそのファイルを共有するだけで事足ります。(パスワードとかの秘匿情報については別途にしても良さそう。)

あとは後から変更したり拡張したりも、残ってるのでいけるはず。

アドミンには

サーバの管理者さんとか。

  • 開発環境を簡単に用意できる
  • 本番環境を簡単に用意できる
  • 環境を簡単に複製できる

ここら辺は完全に想像です。

既存プロジェクト

をDocker化することもできるのでは。

  • 依存パッケージのインストールが不要に
    • grunt, gulp, rails, etc
  • プロジェクトのディレクトリの外からあれこれできる

プロジェクトが /home/ginpei/myproject にあったとして、 /home/ginpei/myproject-docker みたいなのを用意してそっちにDocker系ファイルを置いたりとかして、既存のものは既存のままにしておけば、簡単にできるのではないか?と思いました。

でも実際やってみたら別の問題があって、ちゃんとできるのかわかりません……、という話をしました。なんかwatchがうまく動かなかったんだけど、まあこの話はいずれ。

使ってみよう

ワークショップ前に知識の整理をしました。

使う場合

Docker本体のインストールは別にして、

  1. ファイル群をダウンロード
    • git clone
  2. コンテナ作成
    • docker-compose up

でおわり。

※ただし理想的な環境に限る

作る場合

  1. Dockerfile でコンテナを用意
  2. docker-compose.yml でコンテナ群を連携
  3. docker-compose up で起動

これだけ言ってもわからんと思うけど、こういう流れです。

単語

  • コンテナ … 仮想マシン実体的な。実際に動くもの。作って捨てる
  • イメージ … ISOイメージ的な。コンテナの素。ダウンロードしてくる。作れる
  • docker … イメージからコンテナを作成するコマンド
  • docker-compose … 複数のdockerコマンドをまとめてやってくれるコマンド
  • ボリューム … 記憶領域。コンテナを作りなおしても消えない

コンテナ vs イメージは、OOPのクラス vs インスタンスに近いかなと思ってます。

ファイル

  • Dockerfile
    • マシンひとつ分(イメージ)の設定
    • Linuxのディストリビューションとか
    • インストールするパッケージとか
  • docker-compose.yml
    • マシン間の繋がりの指定とか
      • データ専用マシンとか
    • 簡単なマシンの設定とか
    • 実マシンへの露出の設定とか
  • その他
    • Nginxの設定ファイルとか

ワークショップ

ここ↓に当日使用したやつが残ってます。

用意した環境はこんなの:

  • all/ … ダウンロードする用に色々書いただけ
  • php/ … PHP + Nginx + MySQL
  • rails/ … Ruby on Rails
  • web-front/ … gulp + sass + browser-sync
  • wordpress/ … 当日皆で一緒に作ったやつ

最初に all/ で docker-compose up してもらうと、一通りのイメージが降ってきます。皆で一斉にやるとネットワークがつらそうなので、各自自宅でやってきてもらいました。

php, rails, web-front はこちらが用意した環境を使ってみようというやつです。だいたい何もしなくても、すぐに何かが起動します……というわけにはいかなくて、 rake db:migrate とか npm install とかが必要です。今回はそれはそういうもんだということにしてやってもらいました。

最後、 wordpress は自分で docker-compose.yml をはじめ各種設定を書いて「環境を作る」を体験するやつです。構成はだいたい php と一緒。

その他話したこと

コンテナを小分けにする

Vagrantだと全部入りのマシンを用意して普通に(実マシンと同様に)あれこれする感じなんだけど、Dockerないしコンテナ云々の技術大系ではばらばらに用意してからネットワークで繋げていく、みたいな感じらしい。疎結合って言えるのかな。

全部入りにしない利点はよくわかってないです。一番大事なところなんだろうけど。たぶん、イメージ再構築のコストを減らすとかそういうところなのかなって想像してます。そのうち調べる。公式ドキュメントに書いてあったのは覚えてる。

バージョンを固定する

ビルドするたびに「同じ」環境になってほしいよね、なのでイメージのバージョン指定に latest はやめましょう、と。

イメージとコンテナ、そしてボリューム

イメージはダウンロードしてきて長いことファイルに保存されます。コンテナは使うたびに新規作成して、使い終わったら削除されます。

OOPでいうところのクラスとインスタンスみたいな関係。

削除されるということはコンテナ内でファイル編集しても元に戻っちゃうので、編集するファイルはボリュームとして残します。ボリュームにも二種類あって、ホストマシンのファイルをマウント?して使う場合と、Docker内で「これとっといてねー」みたいに指定するのとがある。

イメージとレイヤー

イメージはダウンロードしてくるだけじゃなくて、自分で Dockerfile を書いて作成できる。

イメージはでかい塊だけど、実は玉ねぎみたいに複数の層から成っている。(だから、実は docker image ls で出てくるサイズはディスクに保存されるファイルサイズと直結しない。)

基本的にひとつのレイヤーは Dockerfile の指示一行ごとに作成される。なので、一時ファイルを作成するような指示は一行の中でその削除までするのが好ましい。(下記の例。) さもなくば一時ファイルがある状態の上に削除した状態のレイヤーがかぶさるだけなので、レイヤーのファイルサイズがでかくなる。

RUN apt-get update && apt-get install -y \
    ruby1.9.1 \
 && rm -rf /var/lib/apt/lists/*

あと、レイヤーもイメージ。名前が付いてるかどうかが違う、と言いきっちゃって良い?

Dockerそんなによくないよね

って話もいくつか共有しました。

話さなかったこと

初手の選択肢は少ない方が良い、という方基本針です。あと知らないものは知らないので。

コンテナ化技術

知らなくても使えるので第一歩で触れる必要なさそう。おれ自身詳しくないし。

docker vs docker-compose

composeの説明でちょっと触れたくらい。

compose以外のオーケストレーションツール

Kubernetes てのが熱いらしいぞ! でもおれ使ったことないぞ!

Docker Hub

イメージのダウンロードに絡めてちょっとだけ。

Moby

忘れてた。まあいいか。

パッケージのバージョン管理

イメージのバージョンを固定した方が良いぞという話はしたんだけど、パッケージ類のバージョンについては触れてなかったはず。

で、そのパッケージ類も固定化した方が環境が安定しそう。

Dockerfile で単純に apt-get とかすると「そのとき」のパッケージをダウンロードしてくるので、一年ぶりにビルドしたらツールのバージョンが変わってた……とかになっちゃうかもしれない。もしくは古すぎて消えてるとか。

そもそも Dockerfile を共有すること自体が既に悪手で、誰かがイメージまで用意してからそれを docker-compose.yml で指定する、の方が良いのではないでしょうか。

どうなんすか、先生。

イメージの配布

前項と絡めて話せるかなと思うけど、しなかった。Docker Hub以外の場所を使うやり方も知らないしなー。

docker-compose run xxx ç³»

「このコマンドを入力してください」という形でさんざん使ってはもらったんだけど、説明はあんまりしなかった。「もうbashでいいじゃん!」みたいになってもアレだなーと思って。

とはいえ、コマンド実行する必要がある場合はどうするのが良いのかなあ。ほら、初期設定は別にしてもRoRで rake db:migrate とかばんばんするでしょ。別途シェルスクリプト的なものを用意しておくの?

やってみた感想

いろいろたいへんだったけど、たのしかったです。