病みつきエンジニアブログ

機械学習、iPhoneアプリ、Javascript,Ruby on Railsなどなど。

今更始めるDocker on Mac、今更覚えるDockerコマンド

今更ながらDocker始めてみた。モチベーションとしては、Sparkとか試すために、手元に仮想環境がほしいから。なので、Immutable Infrastructureとか、KubernetesとかPackerはもちろん、Dockerfileとかにも踏み込まず、Dockerを始めてみる

Docker始めるにあたり読んだ記事

基本的には Installation on Mac OS X を参考にしながら、若干逸脱しつつ、基本コマンドなどを触ってみる。

インストール方法

Installation on Mac OS X を参考にする。 boot2dockerは非推奨なので Docker Toolbox使う。基本的にはGUIに従えば良い。

OSXでは、Linux上のDockerと違い、default というLinux VM上で動く。このVMdocker-machine コマンドで動かす

GUIからインストールしていると、VMは既に作成されているはず。Linux上でのDockerとの違いにより、この“URL”がちょっと重要

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER   ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v1.9.1

default VMが死んでいると、dockerコマンドは動かないので、docker-machine コマンドから立ち上げるなり作成するなり

$ docker images
Cannot connect to the Docker daemon. Is the docker daemon running on this host?
$ docker-machine start default  # 立ち上げ
(default) Starting VM...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.
$ docker-machine env default  # 環境変数が設定されていないと、dockerコマンドが動かないため
$ eval "$(docker-machine env default)"  # dockerコマンドが動くようにする
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

基本的な用語:イメージとコンテナ

イメージは、docker pullしてくるやつ。特定の生きたインスタンスじゃなくて、テンプレート的なもの。Dockerfileなどの定義体を含むもの。AWSでいうところのAMI。一覧を見るには、docker images

コンテナは、イメージから作成するもの。特定の生きたプロセス。AWSでいうところのインスタンス。一覧を見るには、docker ps

コンテナの作成

コンテナを作成するためには、イメージを取ってきて、そのイメージを元にコンテナを作る。まずはhello-worldというイメージを使ってみる。

コンテナの作成はdocker run 。runというと走らせる=起動っぽく感じるけど、AWSで言うとrun-instances に当たり、新規に作るもの。docker run する際、イメージがなければ自動で取ってくるようなので、docker pull をする必要は本当はない。

$ docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world

b901d36b6f2f: Pull complete
0a6ba66e537a: Pull complete
Digest: sha256:8be990ef2aeb16dbcb9271ddfe2610fa6658d13f6dfb8bc72074cc1ca36966a7
Status: Downloaded newer image for hello-world:latest

$ docker images  # イメージが取得できている
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hello-world         latest              0a6ba66e537a        9 weeks ago         960 B

$ docker run hello-world
Hello from Docker(ry

hello-dockerのイメージの中身は、 docker-library/hello-world で見ることができる(Dockerfile)。

一瞬で死ぬためよくわからないが、コンテナが作成された過去を垣間見ることができる(StatusはExited)。そして変な名前がついているw

$ docker ps --all
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
15eb91d087e0        hello-world         "/hello"            4 minutes ago       Exited (0) 4 minutes ago                        amazing_mahavira

コンテナへのアクセス

ubuntu イメージをrunしてみてもわかるが、コンテナは基本一瞬で死ぬ。コンテナ内で作業するには、 -it オプションを付ける。exitをすると(またはCtrl-D)、コンテナはまた停止する。

$ docker run -it ubuntu
root@a46509616ebe:/# exit

コンテナを立ち上げっぱにしておきたければ docker run -idt する。

$ docker run -idt --name my_ubuntu ubuntu
$ docker attach my_ubuntu
root@6acce8e05501:/#

立ち上げっぱのまま抜けるのは、Ctrl+p→Ctrl+q。

コンテナの再開

runして暗黙的に停止するライフサイクルだけではなく、停止したコンテナを docker start で再開することもできる。

当たり前だが、作成したコンテナのファイルは別に消えない。

$ docker run --name="my_ubuntu" -it ubuntu
root@7bd211d00874:/# echo "hogehoge" > hoge; exit  # てきとーにファイル作る
$ docker start -i my_ubuntu
root@7bd211d00874:/# cat hoge
hogehoge

ライフサイクル周りは Dockerライフサイクルをハンズオンで学ぶ - Qiita

コンテナのスナップショット

コンテナをイメージとして登録する=スナップショットを取るには、commit をする。gitと同じく、コミットメッセージもつけられる。イメージ間では特に差分の概念とか取らないんだろうか?

$ docker commit -m "hoge" a46509616ebe my_ubuntu
25185d37f98957a60309c73ae6c5d11ca8beea821306ef7b3edd37644d236677
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
my_ubuntu           latest              25185d37f989        21 seconds ago      187.9 MB
ubuntu              latest              89d5d8e8bafb        13 days ago         187.9 MB

これで、特にDockerfileなどは意識していないが、仮想環境のスナップショットを取ってイメージを作成する、という手順が出来たことになる。仮にクラスターなどを作る場合、一つのイメージを複製すれば良さそう。

ネットワーク周り

nginxのイメージで試す(参考:Dockerfile)。他にもJenkinsイメージとかもある。

$ docker run -d -P --name web nginx
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                           NAMES
cc343576e1aa        nginx               "nginx -g 'daemon off"   16 minutes ago      Up 16 minutes       0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp   web

ここで、ポートのマッピング情報が書いてある。nginxの普通のポート80番は、32769番にマッピングされている。これは、VMのIPに対してのポート番号である

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER   ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v1.9.1

よって、http://192.168.99.100:32769 にアクセスすると、nginxの画面が表示される。

コンテナへのログイン

nginxサーバーを立ち上げているということで、例えばサーバー内に何か不具合があって、調査する場合など、コンテナにログインしたいケースは、exec コマンドに使うことができるようだ。

$ docker exec -it web bash

ちなみに、この場合はexitしてもコンテナは停止しない。

コンテナへのディスクマウント

ログなどの永続化したいファイルなどを入れるために、コンテナにローカルの(Macの)ディレクトリをマウントさせることができる。

$ echo "my new site" > /path/to/site/index.html  # ローカルに適当なhtmlファイルを作る
$ docker run -d -P -v /path/to/site:/usr/share/nginx/html --name web nginx
$ open "http://xxxxx"  # コンテナのnginxを開く

上記はローカルのファイルをコンテナが参照した形だが、逆に、コンテナからファイルを書き込むこともできる。

$ docker exec -it web bash
root@35f1b0480264:/# echo "hogehoge" > /usr/share/nginx/html/hoge.html; exit
$ cat /path/to/site/hoge.html
hogehoge

その他

15 Docker Tips in 5 Minutes // Speaker Deck より

最後に作ったコンテナIDを指すエイリアスを貼っておくと便利

alias dl="docker ps -l -q"

GUIインターフェース

以上説明したコマンドは、KitematicというGUIアプリケーションでもできる。GUIでインストールしていると、Applicationフォルダに勝手にインストールされているはず。

f:id:yamitzky:20151224114622j:plain

まとめ

使ったコマンドは、だいたい下記の通り

docker-machine ls # 起動しているVMの確認
docker-machine start # default VMを起動

docker images # イメージの一覧
docker ps # コンテナの一覧
docker run # コンテナの作成
docker start # コンテナの開始
docker attach # コンテナへのアタッチ
docker exec # コンテナでのコマンド実行; bashログインなど
docker commit # コンテナのコミット=スナップショットを取る
広告を非表示にする