- アプリケーションの実行に必要なソフトウェアとその依存ファイル郡(ディレクトリ構造を含む)をパッケージングして、簡単に利用できるようにするもの
- ポータブル
- 例えば「PHPのバージョン8.0.19、imagemagickが利用可能」と言うパッケージを作る
- DockerがインストールされているPCであればダウンロードするだけで動作する
- ホストPCにインストールされている他のソフトウェアや共有ライブラリの影響を受けない
- アプリを配布するときにDocker形式も提供すれば環境によって動かないトラブルはほとんどない
主にLinuxでの話
-
新しいソフトウェアを気軽に試したいけど依存関係が複雑で環境が壊れやすい
- あんまり気に入らなかったら元の状態に戻したい
-
アプリの動作環境を切り替えて使いたい
- 開発中のアプリで新しいバージョンのライブラリを使いたいけど、アップデートすると他のソフトウェアが動かなくなる
-
複数のマシンを使ってそれぞれに違う環境をセットアップする(VirtualBoxの場合もこのパターン)
- 導入コスト大
- 管理コスト大
-
同じマシン内に違うバージョンのソフトウェア、ライブラリ(環境)を共存させたい
- 標準とは別の場所にライブラリやソフトウェアをインストールし、それをPATHなどの環境変数を指定して切り替えるという方法
- 環境構築が難しい
- アップデートやライブラリを追加して依存関係をその都度解決するのはもっと難しい
- とても壊れやすいので現実的ではない
- ユーザーを切り替える方法
- さくらの共用レンタルサーバーのようなものを思い浮かべてもわかりやすい
- 頑張れば、パスを変えたりして、自分でビルドしたアプリが使えたりする
- 標準とは別の場所にライブラリやソフトウェアをインストールし、それをPATHなどの環境変数を指定して切り替えるという方法
-
そこでchroot
-
Dockerは仮想化技術を使ってchrootをパワーアップしたもの
- 壊れにくい
- 軽量、早い
- 環境が切り離され、独立している
- 誤ってファイル削除とかしても他の環境に影響を与えない
- 簡単に環境構築できる
- 初期化ややり直しが簡単でトライアンドエラーで開発できる
- セキュリティ
- 外のプロセスが見えない
- ファイルシステムをレイヤーに見立てて、重ねて合わせて(上書きマウント)使用することができる
- overlayfsとは
- ファイルシステムをオーバーロードする
- あるディレクトリに対して別の同じマシンのディレクトリをマウントするイメージ
- 複数のファイルシステムをマージすることもできる
- 一部のファイル群のみ上書きでマージ
- ソフトウェアのバージョンアップやライブラリのアップデートのようなことができる
- 上書き前の情報も保持しているので瞬時に戻すこともできる
- 差分情報のみなのでストレージの消費も少ない
- 一部のファイル群のみ上書きでマージ
/bin
/lib
~/.bashrc
- プロセス毎にあるパスのディレクトリに格納されているファイルが異なる
- ライブラリをインストールするパスは標準で良い
- PATHなどの環境変数も変える必要がない
-
完全仮想化、準仮想化
- VirtualBox,HyperV,KVM
- ハードウェアをエミュレーション、または独自ドライバを提供
- OSレベルで仮想化を提供する、ホストOSと違うOSのアプリも動かせる、大体のアプリが動く
- 特徴
- 動作が重たい
- 起動が遅い、普通のPCの電源をつけてから立ち上がるまでと同じ
- ハードウェアをエミュレートするのでその分パフォーマンスが落ちる
- ストレージ消費が大きい
- 動作が重たい
-
コンテナ型仮想化
- Dockerなど
- ハードウェアをエミュレートしない
- ホストOSのカーネルを共有する、ホストOSで動くアプリしか動作しない
- ディストリビューションとバージョンはホストOSと別のものを動作させられる
- 動作が軽い
- 起動が早い、1秒もかからない
- ハードウェアをエミューレートせずにホストOS上でそのまま動作するのでパフォーマンスが落ちない
- ストレージ消費が少ない
- GUIで操作できない
Webアプリ(Laravel等)を動かすことを考える
-
VirtualBox
- 基本的に常時電源ON
- 一つの仮想マシンに複数のアプリケーション
- チーム内で違うバージョンのPHPで開発してしまう可能性
-
Docker
- 基本は電源OFF、必要なタイミングで必要な時だけ、使わなくなったらすぐに破棄
- 一つのアプリケーションに一つの仮想マシン
- アプリケーション毎に本番環境と全く同じバージョンで開発
-
一つのプロセス(コマンド)を実行するために一つの仮想マシンが動作する
- プロセスの数だけ仮想マシンが必要なので、基本1台だけのVirtalBoxと比べると全然起動するマシンの数が違う
- Dockerは仮想マシンの起動に1秒もかからないくらい軽いため、仮想マシンを意識せずに、ただコマンドを実行しているのと見分けがつかない
- そのため例えば compose install を実行するためだけに仮想マシンがあったりする
% docker run --rm php:7.1.6-apache php -v
# 例えば上記のようにPHPのバージョンを表示するだけのコマンドを仮想マシンで実行すると
PHP 7.1.6 (cli) (built: Jul 3 2017 22:30:08) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
# 仮想マシンが一瞬で立ち上がって php -v コマンドが実行されて結果が標準出力で返される
# プロセスが終了すると仮想マシンも一瞬でシャットダウンする
- Dockerはアプリケーションを中心に考える、仮想マシンありきではない
- アプリケーション毎にカスタマイズされた専用の動作環境を用意する、実行環境を共存させて切り替える発想から飛躍
- 仮想マシンにアプリケーションを配置して動作させるのとは反対の考え方
- VirtualBoxの場合はグラフィカルなコンソール上から仮想マシンを操作できる
- Dockerは仮想マシンの起動など操作は基本コマンドで行う
- 動作中の仮想マシンに至っては操作する必要性がほぼない。ターミナルから仮想マシンに接続して操作することは一応きる
- イメージとはVirtualBoxでいうところのスナップショット
- 仮想化されたファイルシステムにディレクトリ構造やファイルが格納されている
- イメージはレジストリサーバにアップロードして共有できる
- VirtualBoxなどのイメージと比較すると小さいファイルサイズで扱いやすい
- Docker Hub Container Image Library
- Docker HubはDocker社が提供するレジストリ
- nodeでいうnpmのようなもの
- PHPやMySQLなど多くのソフトウェアが公式イメージを提供している
- VirtualBoxでいうところの仮想マシンをスナップショットから起動して電源がONの状態
- 起動時に実行するコマンドを指定する
- 基本的には一つのプロセスのみが起動している
- プロセスが終了すると仮想マシンの電源もoffになる
- ファイルに対する変更などはメモリ上にあるため停止すると変更の情報は失われる
- PHPアプリでローカルディレクトリに写真をアップロードするような設計だと再起動で消えてしまう。。
- ファイルに対する変更などはメモリ上にあるため停止すると変更の情報は失われる
- VirtualBoxの場合は仮想マシンを立ち上げてターミナルから必要なソフトウェアやライブラリをインストールする作業にあたる
- Dockerの場合はDockerfileからイメージを作ることを言う
- Dockerfileは
apt-get install zlib
などのようにターミナルを操作するのと同じように記述して、必要なソフトウェアやライブラリを定義する - Dockerfileは単なるテキストファイルなのでバージョン管理できる。配布や共有も容易。PHPアプリなどのプロジェクトディレクトリに置いておける。
- VirtualBoxなどで手動でインストールするのに比べると、やり直しが容易でトライアンドエラーで進めやすい。
- コンテナ間の通信は基本的にはネットワークを経由で行う
- phpからnodeをshell経由で呼び出したりというのは実は苦手。。
- コンテナのポートはホストPCに転送することで外部に公開することもできる
docker run --rm -ti -p 8080:80 php:8.0.19-apache
# -p 8080:80 というオプションでコンテナの80ポートをホストPCの8080ポートに転送している
- ホストのファイルやディレクトリなどをマウントしてコンテナ内から読み書きできる
- 複数のコンテナで同じディレクトリをマウントすることもできるためファイルを使ってコンテナ間通信もできる
docker run --rm -ti -v "/home/myuser/data:/var/www/html" php:8.0.19-apache bash -i
# コンテナの/var/www/htmlディレクトリにホストの/home/myuser/dataをマウント
- Dockerの周辺ツールツール
- コンテナの起動オプションをyamlファイルに書いて簡単に実行できる
- Docker Desktop をインストールするとついてくる
- yamlは設定ファイルとして使える、テキストなのでバージョン管理できる
- Dockerfileと同じくプロジェクトディレクトリに置くことが多い
- ポートフォワードの設定、ボリューム、実行コマンドなどを指定できる
- WebサーバとDBサーバというようにスタックを書いたり、それぞれの依存関係も書ける
- 開発では基本これしか使わない
services:
php:
image: php:8.0.19-apache
ports:
- "8080:80"
volumes:
- "./:/var/www/html"