- Dockerとdocker-composeがよくわからない
- 他の説明サイト見たけどよくわからなかった
- 急いでいるからてっとり速くdocker-composeでなにか動かしたい

百聞は一見にしかず。細かいところは動いてから調べれば良いので、取り敢えず動かしてみよう。話はそれからだ!
準備
こちらのDocker本体の内容をベースに進行しますので、こちらをまだ読んでいない方は先に読んで頂いたほうが理解しやすいと思います。
docker-composeとは
docker-composeとは、一言で言うと、Dockerコンテナ群を指定した設定で起動・停止を自動化するオーケストレーションツールの一つです。
前回はWindows上でDockerを使ってLinuxの一つUbuntuを動かしてみました。Ubuntuは起動時に特に設定が要らなかったため、Dockerコマンドを単発で使ってコンテナの操作を行いました。
しかし、ソフトウェアによってはある程度コンテナの起動時に設定が必要なものもあります。コンテナ起動時にそれを毎回実行するのは面倒なので、まとめて定義しておき、簡単なコンテナを起動できるようにするのが、docker-composeです。
Windowsで言うところのバッチファイル、Linuxでいうところのシェルスクリプトのようなものだと思ってください。
docker-composeのインストール
Windows版Dockerの場合は、Docker本体をインストールすると、docker-composeもインストールされますので、個別に作業は不要です。
docker-composeの超基本
docker-composeコマンドは、実行したフォルダにあるdocker-compose.yamlファイルを読み込んでコンテナの設定、起動、停止などを行います。
そのため、docker-compose.yamlファイルを作る必要があります。これはテキスト形式で、ルールに則ってコンテナの設定を書くだけです。この後、実際に書いて動かすところをやります。
docker-comopse.yamlファイルを作成した後は、docker-composeコマンドを実行するだけで、指定した内容でコンテナの起動・停止が可能になります。
Dockerfileとdocker-composeの違い
Dockerfileは、コンテナ単体に対する起動設定が定義されたものです。コンテナ単体の場合はそれでもよいのですが、複数のコンテナを組み合わせて動かす場合、例えば
- Webサーバコンテナ(nginx)
- アプリケーションサーバコンテナ(Java)
- データベースコンテナ(MySQL)
というようなWebサービスをコンテナ別に構築した場合は、3つ起動する必要があるので、docker-composeの方が便利で簡単です。
docker-composeから各コンテナのDockerfileを参照する方法もありますし、docker-compose.yamlに直接書いてしまう方法もあります。
私はdocker-compose.yamlにすべて書いてしまう派です。まとめて設定が確認できるのでオススメです。…というか、いかなりdocker-compose行ったので、Dockerfile使ったことない^^;
二大Linuxディストリビューションを動かす
Windows10の上で二大Linuxディストリビューションを同時に動かしてみましょう。
- Ubuntu:個人向けLinux。デスクトップが使いやすくユーザも多いのでネットで調べやすい。
- CentOS:サーバ系でよく使われるので、コマンドベースで利用することが多い。
一台のパソコンでこんな豪華共演ができるとは、オーケストレーションツールのdocker-composeのおかげです。まずは、Ubuntuで詳しく説明します。
docker-composeでubuntuコンテナを起動
docker-compose.yamlファイルの作成
前回、DockerコマンドでUbuntuを起動した時にコマンドです。
> docker run -it ubuntu /bin/bash
docker-composeで起動させる場合は、先に説明したdocker-compose.yamlファイルを作る必要があります。同じことをするには、このようになります。このファイルはどこに保存してもOKです。docker-composeコマンドを実行する際のフォルダにあれば認識してくれます。
version: '3'
services:
ubuntu:
image: ubuntu
container_name: ubuntu01
tty: true
- version はdocker-composeのバージョンです。現在は3でOKです。
- services: はコンテナの見出しです。今回はUbuntuとします。
- image: はコンテナで使うDockerイメージです。今回はubuntuを使います。バージョンを指定いない場合は、最新版を使います。ubuntu:latestと同じ。
- container_name: コンテナに名前を付けます。名前を付けた方が後でコンテナに接続しやすいです。
- tty: true はBashが入力待ち状態になるよう指定します(nginxやMySQLのようにポートを開いて待受けするようにシステムの場合は指定不要)。
docker-composeでコンテナ起動
docker-composeでコンテナを起動するには、先程作成したdocker-compose.yamlのあるフォルダへ移動して、docker-compose up -d を実行します。実行すると、docker-compose.yamlに記載されている内容でコンテナの準備をしてくれます。
> docker-compose up -d
Creating network "docker_default" with the default driver
Pulling ubuntu (ubuntu:)... ← Ubuntuのイメージを取得しにいきます
latest: Pulling from library/ubuntu
423ae2b273f4: Pull complete ←イメージ取得完了 de83a2304fa1: Pull complete f9a83bce3af0: Pull complete b6b53be908de: Pull complete Digest: sha256:04d48df82c938587820d7b6006f5071dbbffceb7ca01d2814f81857c631d44df
Status: Downloaded newer image for ubuntu:latest
Creating ubuntu01 ... done ←ubuntu01という名前でコンテナ準備完了
確認① 取得したDockerイメージを確認
docker images で確認確認できます。ubuntuの最新版 (TAG=latest)が取得できています。サイズはなんと64MBですよ。ubuntuの本体を動作させるための最小限構成とはいえ、たった64MBでLinuxが起動できるというのはスゴイです。
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 72300a873c2c 2 weeks ago 64.2MB
確認② dockerプロセスの確認
起動しているDockerコンテナを確認するには、docker ps -a です。
> docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
17d3890da94a ubuntu "/bin/bash" About a minute ago Up About a minute ubuntu01
確認③ docker-composeステータス
docker-composeで起動した場合は、docker-compose ps で各コンテナの状況がまとめて確認できます。StateがUpになっていますからUbuntu01は起動しています。
> docker-compose ps
Name Command State Ports
------------------------------------
ubuntu01 /bin/bash Up
Ubuntu起動中のコンテナに接続
コンテナに接続するのは、先のUbuntu単発起動時と同じです。docker exec -it で接続します。プロンプトがrootに変われば、そこはもうDockerコンテナとして起動しているUbuntuのBashです。コンテナから抜けるには、exit してください。
> docker exec -it ubuntu01 /bin/bash
root@3bd1430559ee:/#
docker-composeでコンテナ停止
docker-composeで起動したコンテナを停止する場合は、docker-compose stop で停止できます。複数指定があった場合は、すべて停止します。
> docker-compose stop
Stopping ubuntu01 ... done
docker-composeでコンテナ再起動
停止中のコンテナを再起動する場合は、docker-compose start です。初回起動時と同様に up -d でも起動できます。イメージの取得やコンテナの作成は、無い場合だけ自動で取得したり作成してくれたりするので、開始する時は、docker-compose up -d と覚えておけば良いです。
実行中のコンテナを再起動する場合は、docker-compose restart です。
> docker-compose start (up -dでも大丈夫)
Starting ubuntu ... done
docker-compose down でコンテナ破棄
コンテナを破棄する場合は、docker-compose down を実行します。実行中のコンテナを停止してコンテナ本体を破棄します。
> docker-compose down
Stopping ubuntu01 ... done
Removing ubuntu01 ... done
Removing network docker_default
コンテナ破棄の際に、コンテナイメージを同時に削除することもできます。その場合は、–rmi オプションを指定してください。ローカルにキャッシュしたコンテナイメージを削除します。
> docker-compose down --rmi all
Stopping ubuntu01 ... done
Removing ubuntu01 ... done
Removing network docker_default
Removing image ubuntu ← イメージ本体が削除される
Dockerは次の順番でコンテナを起動します。
- コンテナイメージを取得
- コンテナイメージからコンテナの本体を作成
- 作成したコンテナ本体を起動
3で起動したコンテナを止めるのがコンテナ停止(docker-compose stop)。
2で作成したコンテナを削除するのがコンテナ破棄(docker-compose down)。
コンテナを破棄した後に起動すると、新しいコンテナが作成されるため、前回のコンテナとは別物になります。つまりコンテナ内にファイルを作った場合は、コンテナを停止しても残りますが、コンテナを破棄すると削除されてしまいます。

コンテナ内で作ったファイルが消えちゃうんじゃ使い物にならないよー

これはコンテナの外の環境と切り離すことでコンテナを独立させるというDockerの仕様なんだ。でも大丈夫、コンテナ内で作ったファイルをコンテナ外に保存する方法があるのでこの後で紹介するよ。
docker-composeでCentOSコンテナを起動
docker-compose.yamlの作成
先程作成したdocker-compose.yamlにCentOSを追加します。
version: '3'
services:
ubuntu:
image: ubuntu:latest
container_name: ubuntu01
tty: true
centos:
image: centos:latest
container_name: centos01
tty: true
docker-composeでコンテナ起動
コンテナを起動して、起動状態を確認します。
> docker-compose up -d ← Docker起動
Pulling centos (centos:latest)...
latest: Pulling from library/centos
8a29a15cefae: Pull complete Digest: sha256:fe8d824220415eed5477b63addf40fb06c3b049404242b31982106ac204f6700
Status: Downloaded newer image for centos:latest
Creating ubuntu01 ... done
Creating centos01 ... done
> docker ps -a ← プロセス確認
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
955b8ed98315 centos:latest "/bin/bash" 58 seconds ago Up 54 seconds centos01
706bf4af9cd0 ubuntu:latest "/bin/bash" 58 seconds ago Up 54 seconds ubuntu01
> docker-compose ps ← ステータス確認
Name Command State Ports
------------------------------------
centos01 /bin/bash Up
ubuntu01 /bin/bash Up
CentOSでyum updateしてみる
Ubuntuではapt updateですが、CentOSではyum updateです。
[root@955b8ed98315 /]# yum update
Failed to set locale, defaulting to C.UTF-8
CentOS-8 - AppStream 47% [=================== ] 68 kB/s | 3.1 MB 00:51 ETA
これでWindows上でLinuxが2つ起動しました。ただこのままでは、コンテナ内と外でファイルのやりとりができませんので、この次共有する方法を紹介します。
Windowsとファイルを共有する方法
ボリュームを定義
Dockerコンテナ内と外でファイルを共有するためには、ボリュームの定義を追加します。さっそくdocker-compose.yamlファイルに追加してみましょう。
volumes: を追加し、その次の行からマッピング情報を追加します。マッピング定義はvolumesの子要素となるので、先頭にハイフンを付けて定義します。
下の例では、Docker本体が動いているパソコンのC:\work\docker\dataフォルダと、Ubuntu01コンテナの/windows_dataフォルダをくっつけます。
version: '3'
services:
ubuntu:
image: ubuntu:latest
container_name: ubuntu01
tty: true
volumes:
- "c:\\work\\docker\\data:/windows_data"
コンテナを起動する
docker-compose up -d します。すると、次のような確認画面が起動する場合があります。これはDockerコンテナ内とディスクを共有するけど本当によい?という確認ですので、Share itしてください。
ファイル共有確認
Windows側(コンテナ外)でファイルを作成
Windows側で共有フォルダとして指定した場所に、テキストファイルを作成して格納してみましょう。例えば、このようなファイルを作って置いてみます。

配置するとこのような感じです。

Ubuntu側(コンテナ内)でファイルを確認
次にこれをコンテナ内から確認します。コンテナに接続する方法はもうバッチリですよね?

おお、コンテナ外のファイルが参照できて、中身も表示できます。
コンテナ内でファイルを変更
コンテナ内からファイル名をWindows.txtからhoge.txtに変更してみましょう。
root@f697ed7420bf:/# mv /windows_data/Windows.txt /windows_data/hoge.txt
双方での変更はリアルタイムで反映されます。

これでWindowsユーザーもLinuxの強力なコマンド群が使えるようになりました。
例えば sed コマンドで正規表現置換ができますし、パイプ連結で一通りのテキスト編集ができますし、大量ファイルの grep や、ログの tail -f なども出来てしまいますね。
試しに奇数だけを半角スペースに変換した2468.txtを作ってみます。
root@f697ed7420bf:/# cat hoge.txt | sed s"/[13579]/ /g" > 2468.txt
もちろん、Windows側でも見れます。これは便利♪

まとめ
結論:システムを構成するサービス一式をまとめたり、よく使うコンテナをまとめておくと便利
Dockerとdocker-composeでLinuxだけではなく、コンテナのイメージが用意されているものを取得してきて動かすことができます。必要なソフトを必要な時だけ構築して動かして不要になったら捨てる。これが簡単にできるのがDockerコンテナです。
また、それを自分でカスタマイズしてDockerイメージを自作することもできます。システム開発では周辺のミドルやアプリ、ライブラリ等をひとまとめにしたDockerイメージを作成しておいて、他の開発者にイメージを配布することで環境構築のコストを削減したりできます。
Dockerとはなんぞや? という方にオススメの一冊です。
Webエンジニアだけど自分の作ったアプリを自分の手元のコンテナで動かしてみたい、テスト用のアプリ環境を複数作りたい、などなどDockerを使うとインフラエンジニアにお願いしていたことが自分でもできるようになります。そんなあなたにオススメな一冊がこちらです。
最後にインフラエンジニアやっててDockerを極めたい、という方はオライリー本でとことん深くまで突き進んでください。
コメント