Mac OS XにDocker開発環境を構築し、Dockerイメージの取得とコンテナの起動・停止、イメージの作成方法およびレジストリへのアップなどdockerを利用し始めるにあたって、これだけは抑えておくべきという基本的な内容についてまとめてみました。

Dockerは「Build, Ship, and Run Any App, Anywhere」と謳っているように、Dockerの仕組みでビルドされたアプリケーションは、Docker対応のプラットフォームであればどこでも簡単にデプロイできるようになります。

PHPのWebアプリの場合を例にすると、gitによるソース・サブモジュールの管理、Composeによるパッケージ管理、さらにフロントまわりのパッケージはnpmで管理していたりとビルド、デプロイのプロセスはかなり複雑になっています。そこに、Dockerを利用すると、Java EEの世界でアプリをWarファイルに固めてアプリケーション・サーバーにデプロイするような感覚で、開発環境でビルドしたものをテストし本番へデプロイすることが可能になります。

さらに、デプロイのプロセスが簡単になると、PaaSを利用する際に、PaaSごとの違いをDockerが吸収してくれるので、新しいPaaSを試す時などは、固有の仕組みを覚えるコストが小さく済みそうです。

Dockerそのものの概要については、公式には「What is Docker」に説明があります。
またアーキテクチャと各種用語については「Understand the architecture」にまとまっています。

周辺ツールも増えてきて、なかなか全体像を説明するのも大変なので、ここではDockerそのものの説明は飛ばし、dockerコマンドを打つとDockerイメージを作ったり、自分で作ったイメージや公開されているイメージをコンテナとして起動して簡単にアプリが起動できるものだくらいにまずは抑えておいて、DockerHubに公開されている公式イメージを利用したDockerの使い方についてまとめました。

Docker Toolboxを利用した開発環境の準備

Mac OS Xで、簡単にDocker環境を用意するには公式のDocker Toolboxを利用できます。

Docker Toolboxは、開発に必要な以下のDocker関連ツールが含まれています。

  • Docker Client: Docker Enginseと対話するコマンド
  • Docker Machine: Docker Engineがインストールされたホストをセットアップするコマンド
  • Docker Compose (Mac only): 複数のコンテナを組み合わせたアプリケーションを管理するツール
  • Docker Kitematic: Docker管理GUIツール
  • VirtualBox: ローカルで開発する場合には、Dockerホストの動作環境としてデフォルトでVirtual Boxを使う

公式ドキュメントのインストール手順は、Installation on Mac OS Xにあります。
Docker ToolboxよりインストーラDockerToolbox-1.8.2c.pkgをダウンロードして実行して、ウィザードに従ってインストールできます。
(boot2dockerは2015.10現在は非推奨になっています。また、boot2dockerをすでに利用している場合は、インストーラが移行してくれます。)

インストール後、Launchpadから”Docker Quickstart Terminal”アイコンをクリックするとTerminalが起動してDockerホストのVMが起動します。


                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/


docker is configured to use the default machine with IP 192.168.99.100
For help getting started, check out the docs at https://docs.docker.com

補足ですが、Docker Quickstart Terminalは、VirtualBox上に作成されたdocker-machine defaultを利用するための環境変数がセットされた状態のTerminalを起動してくれるショートカットです。

hello-workdイメージで動作を確認

Docker Quickstart Terminalを起動したらまずは、hello-worldイメージを起動してdockerコンテナの動作を確認してみます

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world

535020c3e8ad: Pull complete 
af340544ed62: Pull complete 
Digest: sha256:a68868bfe696c00866942e8f5ca39e3e31b79c1e50feaee4ce5e28df2f051d5c
Status: Downloaded newer image for hello-world:latest

Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account:
 https://hub.docker.com

For more examples and ideas, visit:
 https://docs.docker.com/userguide/

hello-worldイメージは、実行するとメッセージを表示するだけのイメージです。
上記のように表示されれば正しくコンテナを起動できています。

Terminalに出力されたメッセージからも確認できますが、初めて起動するイメージはDockerホストVM内に無いので、pull(Download)してからDockerコンテナが起動されています。

つまり、以下のように、pullしてからrunを実行しても同じです

$ docker pull hello-world
$ docker run hello-world

ここまでの流れを図にすると以下のようになります
docker-pull-run-stop-flow

hello-worldイメージは、起動してコマンドを実行したらすぐに停止されるイメージなので、docker stopコマンドを実行しなくても処理が終わるとコンテナは停止します。
(DockerfileのCMDに指定されたコマンドが終了するとDockerコンテナも終了する)

docker psコマンドを実行すると起動しているコンテナが無くなっていることが確認できます。

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

-aオプションをつけてdocker psすると、hello-worldイメージのコンテナが停止していることを確認できます

$ docker ps -a
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                      PORTS                              NAMES
37a87e518b25        hello-world            "/hello"                 11 minutes ago      Exited (0) 11 minutes ago                                      sharp_poincare

また、Dockerホストにダウンロードされたdockerイメージはdocker imagesコマンドで確認できます

$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hello-world            latest              af340544ed62        8 weeks ago         960 B

以上で、dockerイメージをリポジトリよりイメージをpullして、イメージからコンテナを起動し、停止するところまでつかめたかと思います。

補足
コマンドを実行するだけのdockerイメージの作成については以下のページが参考になります。
hello-worldイメージが何をしているのか気になる方は参照すると良いと思います。
Create a base imageのCreating a simple base image using scratch
DockerのscratchイメージでHello Worldする

WordPressイメージを起動してみる

デーモンとして起動するアプリケーションの例として、オフィシャルイメージのwordpress(Github: docker-library/wordpress
)を動かしてみます。

wordpressのDockerイメージは、Apache + mod_php環境とfpm環境の2つが用意されていますが、fpmの場合はnginxコンテナも起動する必要があるので、ここではよりシンプルなApache + mod_phpのイメージを試してみます。

また、このイメージは、WebサーバーとPHP実行環境のみが用意されているため、データベースを別途用意する必要があります
データベースは、オフィシャルイメージのmysql(Github: docker-library/mysql)を起動して、それをwordpressコンテナからアクセスするように指定します。
また、MySQLのデータはコンテナの中に保存しておくとコンテナ停止と主に無くなってしまうので、Dockerホスト側に永続化します。

動作環境の構成を図にすると以下のようになります。
docker-run-wordpress-and-mysql-containers
msyqlイメージのインポートと実行

VirtualBox上で動いているdocker-machineのホストにログインして、MySQLのデータ用ディレクトリを作成します。
docker-machine sshコマンドにdocker-machine名(default)を指定するとsshログインできます。

$ docker-machine ssh default
docker@default:~$ sudo mkdir -p /my/own/datadir

mysqlイメージを起動します。

$ docker run --name mydb -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password -d mysql

コマンドのオプションについて

  • –name: コンテナ名を明示的に指定しています。Wordpressコンテナからリンクする際にコンテナ名を指定します。
  • -v: MySQLコンテナのディレクトリ/var/lib/mysqlをDockerホストの/my/own/datadirにマウントします。詳しくは「Managing data in containers」を参照。
  • -e: 環境変数MYSQL_ROOT_PASSWORDにMySQLのrootユーザのパスワードを指定しています
  • -d: バックグラウンド(デーモン)としてコンテナを起動します

wordpressイメージのインポートして実行します

$ docker run --name mywp --link mydb:mysql -p 8080:80 -d wordpress

コマンドのオプションについて

  • –name: コンテナ名を明示的に指定しています。
  • –link: MySQLのコンテナmydbをWordpressのデータベースとしてするようにコンテナ名を指定します。詳しくは「Linking containers together」を参照。
  • -e: 環境変数MYSQL_ROOT_PASSWORDにMySQLのrootユーザのパスワードを指定しています
  • -d: バックグラウンド(デーモン)としてコンテナを起動します

DockerホストのVirtualBox VMのIPアドレスをdocker-machine envコマンドで確認

$ docker-machine env default | grep DOCKER_HOST
export DOCKER_HOST="tcp://192.168.99.101:2376"

http://192.168.99.101:8080にアクセスするとWordpressのインストール画面が表示されます
docker-on-ubuntu-wordpress

MySQLのデータはDockerホスト側のディスクに保存するようにしました。
実際にMySQLのデータがホスト側のディレクトリに保存されているか確認してみます。

$ docker-machine ssh default
docker@default:~$ ls /my/own/datadir/
auto.cnf            ib_logfile1         mysql/              wordpress/
ib_logfile0         ibdata1             performance_schema/

確かにMySQLのデータファイルが書き込まれています。

MySQLとWordpressのコンテナは、MySQL、Apacheのプロセスが停止しなければ起動したままになります。
このようなコンテナを停止するには明示的にdocker stopコマンドを使ってコンテナを停止します。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
50e710229b4a        wordpress           "/entrypoint.sh apach"   4 minutes ago       Up 4 minutes        0.0.0.0:8080->80/tcp   mywp
02081c109a94        mysql               "/entrypoint.sh mysql"   4 minutes ago       Up 4 minutes        3306/tcp               mydb
$ docker stop 50e710229b4a 02081c109a94
50e710229b4a
02081c109a9
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

docker-machineコマンドまとめ

ところで、ここまでは、Docker Toolboxインストール時に作成されるdocker-machine defaultを利用して動作を確認してきましたが、docker-machineは新たに作成したり、VirtualBoxだけでなくAWSやDigitalOceanなどクラウド上に作成したりすることができます。

docker-machineのコマンドについて、使い方についてメモしておきます。

新しいdocker-machineの作成して利用をする手順

default以外に新しくdocker-machineを作成、起動して、dockerコマンドの実行先を変更する手順をまとめてみました。

docker-machineの作成

$ docker-machine create <docker-machine名>

docker-machineの起動

$ docker-machine start <docker-machine名>

docker-machine環境変数の確認

$ docker-machine env <docker-machine名>
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.101:2376"
export DOCKER_CERT_PATH="/Users/hrendoh/.docker/machine/machines/<docker-machine名>"
export DOCKER_MACHINE_NAME="<docker-machine名>"
# Run this command to configure your shell: 
# eval "$(docker-machine env <docker-machine名>)"

docker-machine環境変数を適用

$ eval "$(docker-machine env <docker-machine名>)"

以上で、新しく作成したdocker-machineを利用可能になります。

全てのコマンドについては「Supported Docker Machine subcommands」を参照ください。

Digital Oceanプロバイダーを利用する

docker-machineは、特に指定しなければデフォルトプロバイダはVirtual Machineが選択されますが、Virtual Machine以外に、AWSやAzure、DigitalOceanなどのクラウド環境やVMWare関連ツールなど、Supported Driversにリストされている様々なプラットフォームのプロバイダーをサポートしています。

ここでは、DigitalOcaenプロバイダの動作を確認してみます。
Digital Oceanの手順を参考に、Digital Ocearnのシンガポールリージョンにdocker-machineを作成してみます。

$ docker-machine create --driver digitalocean --digitalocean-access-token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX --digitalocean-size=1gb --digitalocean-region sgp1 docker-machine
Creating SSH key...
Creating Digital Ocean droplet...
To see how to connect Docker to this machine, run: docker-machine env docker-machine

DigitalOceanのDropletが追加されていることを確認できます

docker-machine-digitalocean-provier

コマンド実行先を作成したdocker-machineに変更しまます

$ eval "$(docker-machine env docker-machine)"

以上で、dockerコマンドがDigitalOceanに作成したdocker-machine上で実行されるようになります。