dockerは何のために使うもの?どんなときに便利?
docker とはサーバの設定をコードで書けるようにするもの
docker の説明って、だいたいわかりづらいですよね。コンテナ型がどうとか、ハイパーバイザがどうとか、難しい用語がいっぱい出てきます。実はその説明、どうでもいいです。大規模サービスに責任を持つインフラエンジニアの立場になってから覚えればよいです。
最初に覚えておいてほしいのは、docker はInfrastructure as Code(IaC)、つまりサーバの設定をコードで表したいから使うものなのです。
実行環境を標準化する
docker 公式ページの What is a Container?の見出しを読んでみましょう。
Package Software into Standardized Units for Development, Shipment and Deployment
標準化したユニットにソフトウェアをパッケージします。開発、出荷、デプロイのために。
どういうことか?
なんとなくお気づきだと思いますが、ソフトウェアは実行環境が必要なのです。PS5 でゲームを遊べるのは、PS5 という統一された実行環境があるから、PS5 専用ゲームが遊べるのです。今このページを見ているのは、iPhone でしょうか?iPhone も iOS という実行環境があり、その上で safari というソフトウェアが動いているのです。
確実にソフトウェアが動かすためには、PS5 や iOS のように統一化した実行環境が必要なのです。これが標準化したという言葉の意味です。
PS5 や iOS など一般消費者向けの製品であれば、環境のほうを先に作ってソフトをあわせるような作り方ができます。しかし、Web サーバなどだと要件によって様々な実行環境を用意したくなります。このブログくらいの規模のサーバを運営したいのに、google のような巨大なサーバを用意する意味はないからです。また、使いたいミドルウェアも様々で、Rails を使いたいときもありますし、tomcat にしたい場合、はたまた apache に CGI で動かしたいという古風なアーキテクチャにしたい場合もあります。そんな多様性を実現するためにどうしたらいいか考えた結果、コードとして表現すればいいんだ!という考え方にいきつきました。それが IaC です。
ユニット
ユニットという直訳したら「単位」」という言葉も使われています。みなさん一度は Windows を使ったことがあるかと思いますが、悪い思い出があるのではないでしょうか。Windows の悪いクセは、どれかのアプリがクラッシュすると、他のアプリも道連れにクラッシュしてしまうことがよくあります。
Linux や Mac でも Windows より少ないながらも無いとは言い切れません。同じ環境で複数のアプリが動いていると、依存しながらクラッシュしてしまうことがあります。極端な話、1 つの環境では 1 つのアプリだけ動かせば解決する話です。
標準化したユニットにソフトウェアをパッケージしたものというのは、コードで環境を書くことで同じ環境が簡単に複製できることで、1 つの環境に 1 つのアプリを動かせるようにしたものです。
Rails 用の Dockerfile を書いてみる
習うより慣れろです。一個書いてみましょう。インストール方法は様々なページで紹介されているので割愛します。
docker では Dockerfile という名前のファイルに、どんな設定なのか書く決まりです。
誰かが用意してくれた環境を利用させてもらうこともできます。今回は ruby 3.0 の環境を使います。
FROM ruby:3.0
こう書くと、docker の ruby のオフィシャルイメージを使います。
この Dockerfile が置いてあるディレクトリで docker build すると、実行環境ができあがります。
docker build -t hajimete_docker .
-t オプションはタグ(名前)を指定できます。タグを指定しないとハッシュ値でしか指定できなず、人間にはつらいものがあります。
そして実行してみましょう。
docker run -it hajimete_docker irb
これで irb を実行できます。-it オプションは、今の所はそういうおまじないだと思っておいてください。
さらに Rails をインストールしてみましょう。
FROM ruby:3.0
RUN gem install rails
RUN でコマンドを実行できます。gem install rails
が終わった状態になります。
書き終わったらまた build して実行してみましょう。
docker build -t hajimete_docker .
docker run -it hajimete_docker bash
先程は irb を実行しましたが、今回は bash を実行しているので、まるで Linux 環境にログインしているように使えます。なのでrails new
してみたり、普通に cat してファイルを眺めたりしてみてください。
docker-compose
docker は docker-compose と一緒に使わないと便利に使えません。
docker-compose.yml を書いてみましょう。
version: "3.9"
services:
webapp:
build:
context: .
image: hajimete_docker
command: cat
それでは起動してみましょう。
docker-compose up
何が便利になったかというと、docker 単独だと build して run しなければなりませんでしたが、docker-compose を使うと build が必要なら自動で build したあとに実行してくれます。
さらに、開発で使うときは docker の外でコードを書いて、中で実行したくなると思います。 そんなときは volumes を指定すると、中と外がつながります。下記の設定だと、docker-compose.yml が置いてあるディレクトリと、docker の中の/var/app がバインドされ、同じようになります。
version: "3.9"
services:
webapp:
build:
context: .
image: hajimete_docker
volumes:
- .:/var/app
command: cat
さらに Rails アプリを開発するなら、外から http で参照したくなると思います。ポートフォワードも簡単に書けます。
version: "3.9"
services:
webapp:
build:
context: .
image: hajimete_docker
ports:
- 3000:3000
volumes:
- .:/var/app
command: cat
この状態で
docker-compose exec webapp
まとめ
docker のすごいところは、
FROM ruby:3.0
RUN gem install rails
と
version: "3.9"
services:
webapp:
build:
context: .
image: hajimete_docker
ports:
- 3000:3000
volumes:
- .:/var/app
command: cat
のたかだか 15 行程度のテキストファイルだけで、docker さえインストールされていればどんな端末でも開発環境を整えることができます。
最初に話したような、コンテナ型がどうのなんていう話は、このパワーを実感してから覚えても遅くないです。
細かいことを気にしなければ簡単に使いこなすことができる仕組みなので、バリバリ使い倒してみてください!