dockerとdocker-composeのインストール&基本操作 (CentOS7)
dockerとdocker-composeについて
dockerはコンテナ型の仮想環境を作ることができるOSSです。
仮想環境が構築できるOSSはKVMやXenなどが有名ですが、KVMなどはハードウェアをシミュレートして仮想環境(ゲストOS)を立てるため、その分負荷が高いです。
dockerはハードウェアはシミュレートせずに仮想環境を実現しています。カーネルをホストと共通のものを使用してプロセスレベルで隔離する形式で仮想環境を実現しています。
ハードウェアをシミュレートしないためKVMなどの形式よりは負荷が低く済んだり、KVMのゲストOS上でdockerとか少しきもいこともできます。
個人的にdockerを知った時は、自分がよく知っているKVMと比較して理解しようとして少し混乱しましたが、どちらかというとchrootに似ていると感じるようになってから理解が進みました。語弊があるかもしれませんが、dockerはchrootの強化版だと勝手に思ってます。
また、docker経由でアプリケーションを起動させた場合、連動する複数アプリケーションを起動したい時が多々あります。nginxとMySQLとか。1つ1つdockerで起動してもいいのですが、管理が煩雑になります。その時に便利なのがdocker composeです。docker-composeはdockerで複数のアプリケーションの起動を管理できるツールです。docker-composeではコンテナの起動順序も指定できます。今回はdockerとdocker-composeについて試していきます。
尚、最初はCentOS6で試してたのですが、docker-composeの実行の際にエラー吐いて、ググってるうちにCentOS6では推奨されてないことに後から気づいたのでCentOS7でやってます。(最初から要件見ろよっていうね)
Does Red Hat provide docker for RHEL 6? - Red Hat Customer Portal
docker インストール
まずはdockerをyumでお手軽にインストールして起動します。
# yum install docker-io
# systemctl start docker
気軽に試そうと思っただけなので今回特に何も考えずdocker-io入れましたが、dockerパッケージ複数パッケージがありdocker-ioはもう古いようです。docker-ce (free community edition)というパッケージが現状(2018年6月現在)推奨のようです。
docker-ioはUbuntuがメンテしていて、docker-ceはdockerがメンテしているようです。そしてdocker公式の手順では「docker-ceインストールしてね」と書いてあります。私はdocker-ioインストールしちゃいましたが、今後はdocker-ceをインストールした方がよさそうです。
他にもあるっぽいので調べた限りをまとめておきます。
- docker-ce : 現状の推奨パッケージ(free community版)
- docker-ee : 現状の推奨パッケージ(enterprise版)
- docker-engine : 現状(2018年6月現在)すでに古いパッケージ
- docker-io : Ubuntuが管理してるパッケージ。こちらもすでに古いパッケージ。docker公式のUbuntuへのインストール手順でも現状はdocker-ceを推奨。
docker-composeインストール
次にdocker-composeをインストール&実行権限を付与します。
# curl -L https://github.com/docker/compose/releases/download/1.6.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
バージョン確認
# docker-compose --version docker-compose version 1.6.2, build 4d72027 #
これでdockerとdocker-composeの準備完了です。
nignxのdockerコンテナをインストール
試しにdocker経由でnginxを起動してみます。nginxをdocker経由で起動するために、今回はDocker Hubからnginxのdocker imageを持ってきます。
Docker Hubは自分で作成したdockerのコンテナを共有できるdocker社が提供しているサービスです。
Docker Hubに公式がnginxのdocker imageを公開しているのでそれを使用していきます。
https://hub.docker.com/_/nginx/
まずは現在インストールされているdocker image一覧を確認します。まだ、インストールしてないので、何も出てこないはずです。
# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE #
nginxのdocker imageをdocker pullコマンドで持ってきます。
# docker pull nginx
docker pull
が終わったら再度image一覧を確認してみます。正常にdocker imageの取得が終わっていれば、nginxのdocker imageが表示されるはずです。
# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE nginx latest 01133ef0d8b6 4 weeks ago 108.9 MB #
nignx(dockerコンテナ)を起動/停止/削除
nginxのdockerコンテナの準備が終わったので、nginxをdockerで起動します。docker run
コマンドで起動します。
https://docs.docker.com/engine/reference/run/
# docker run -p 8080:80 nginx
-p
オプションをつけなくても起動はするのですが、その場合、コンテナ内で起動したnignxの80番ポートに外部からアクセスするすべが無くnginxにアクセスできません。
そのため「ホストOSの8080番にアクセスした場合、dockerコンテナとして起動しているnginxの80番ポートにアクセスが行く」設定を-p 8080:80
オプションで実施します。
上記docker run
コマンドを実施すると待ち状態になります。他ターミナルからポートのLISTEN状況を確認してみます。
# netstat -nltp|grep 8080 tcp 0 0 :::8080 :::* LISTEN 11585/docker-proxy #
docker-proxyが8080番ポートをLISTEN状態なことがわかりました。
また、この状態で# curl localhost:8080
でホストOSにアクセスするとアクセスできるはずです。アクセスが正常にできた場合、docker runを実行しているターミナルにアクセスログが出力されます。
docker runコマンドを終了したい場合は、とりあえずCtrl+c
で抜けてしまってOKです。
docker run
コマンドをバックグランドで実行したい場合はdocker run
コマンドに-d(--detach)
オプションをつけることでバックグランドで実行が可能になります。
# docker run -p 8080:80 nginx -d nginx
一度上記のようにdocker run
を実行するとコンテナが登録されてdocker ps
コマンドで見えるようになります。Ctrl+c
で一旦停止してしまったので、docker ps
に-a
つけて停止中のコンテナも見てます。
docker ps | Docker Documentation
# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8fa26a7ebbac nginx "nginx -g 'daemon of 24 seconds ago Exited (0) 3 seconds ago goofy_curie #
尚、情報を省略したくないときは下記の通り、--no-trunc
オプションをつけます。
# docker ps -a --no-trunc CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8fa26a7ebbaca3ba697df8e2de611ba4dcc18a0faba9c9ef0e4b05bee891f509 nginx "nginx -g 'daemon off;'" 4 minutes ago Exited (0) 4 minutes ago goofy_curie #
上記の通りdocker run
コマンドを実施したことによりgoofy_curieという名前のdockerコンテナが登録されたことがわかりました。
この登録されたコンテナを起動してみます。docker run
コマンドでは無くdocker start
コマンドで起動してみます。
# docker start goofy_curie goofy_curie # # netstat -nltp|grep :8080 tcp 0 0 :::8080 :::* LISTEN 24692/docker-proxy # # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8fa26a7ebbac nginx "nginx -g 'daemon of 9 minutes ago Up About a minute 0.0.0.0:8080->80/tcp goofy_curie #
無事起動しました。デーモン化してるのでログアウト等しても起動し続けてくれます。停止はdocker stop
で停止できます。
# docker stop goofy_curie goofy_curie # # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8fa26a7ebbac nginx "nginx -g 'daemon of 11 minutes ago Exited (0) 5 seconds ago goofy_curie #
また、このdocker コンテナが不要になったら、docker rm
で削除可能です。
# docker rm goofy_curie goofy_curie # # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES #
これでdocker コンテナ削除完了です。
rootディレクトリを指定してnginxを起動
先ほどは素の状態でnginxを起動しました。今回はホスト側の任意のディレクトリをコンテナのnginxのrootディレクトリにマウントして、ホスト側のディレクトリをrootディレクトリして使うように起動してみます。
# docker run -p 8080:80 -v /home/test/htdocs/:/usr/share/nginx/html:ro -d nginx
-v(--volume)
オプションでホスト側の/home/test/htdocs/
ディレクトリを、コンテナ内の/usr/share/nginx/html
ディレクトリにマウント(読み込み権限ro
のみ)してます。
コンテナ内からホスト側のファイルを読み込むときはこのようにマウントして使用します。
nginxが死んだら自動起動するように設定
先ほど起動したコマンドの場合、nginxが突然死んだ場合死んだままになります。
・起動させる。
# docker run -p 8080:80 -v /home/test/htdocs/:/usr/share/nginx/html:ro -d nginx e975b1419ae221637782ebeaa998efb9ce887fdbd5dcf133fde25f303f87646f # # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e975b1419ae2 nginx "nginx -g 'daemon of 6 seconds ago Up 5 seconds 0.0.0.0:8080->80/tcp ecstatic_euclid # # ps auxwwf ---- USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 10904 0.0 0.6 32552 3172 ? Ss 09:15 0:00 \_ nginx: master process nginx -g daemon off; 101 10929 0.0 0.3 33004 1588 ? S 09:15 0:00 \_ nginx: worker process ---- #
・殺してみる。
# kill 10904 #
・死んだ。死にっぱなし。
# ps auxww|grep nginx root 11877 0.0 0.1 6444 676 pts/2 S+ 09:17 0:00 grep nginx # # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e975b1419ae2 nginx "nginx -g 'daemon of 2 minutes ago Exited (0) 42 seconds ago ecstatic_euclid #
上記の通り死んだら死にっぱなしになります。下記のように--restart=always
をつけることによりプロセスが死んだら自動的に起動するようにできます。
・--restart=always
をつけて起動。
# docker run -p 8080:80 -v /home/test/htdocs/:/usr/share/nginx/html:ro -d --restart=always nginx e828d2119a481d1f80b4604e97022c39894183c5e4c5c421c2ee083d1246863a # # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e828d2119a48 nginx "nginx -g 'daemon of 3 minutes ago Up 3 minutes 0.0.0.0:8080->80/tcp boring_thompson # # ps auxwwf ---- USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 14419 0.0 0.3 32552 1608 ? Ss 09:23 0:00 \_ nginx: master process nginx -g daemon off; 101 14445 0.0 0.2 33004 1336 ? S 09:23 0:00 \_ nginx: worker process ---- #
・殺してみる。
# kill 14419 #
・プロセスIDとプロセスの起動時間がが変わった。一回死んで生き返った。
# ps auxwwf ---- USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 16441 0.1 0.6 32552 3256 ? Ss 09:28 0:00 \_ nginx: master process nginx -g daemon off; 101 16445 0.0 0.3 33004 1608 ? S 09:28 0:00 \_ nginx: worker process ---- # # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e828d2119a48 nginx "nginx -g 'daemon of 8 minutes ago Up 3 minutes 0.0.0.0:8080->80/tcp boring_thompson #
上記の通りdockerでは突然死したときに自動で起動してくるdaemon tools的な機能を備えてます。最高ですね。
次にdocker-composeを試していきます。
docker-composeでnginxを起動
まずは適当にdockerのディレクトリをほって、docker-composeで起動する時に必要なymlファイルを作成します。
# mkdir -p ./docker/nginx/ # # vi ./docker/nginx/docker-compose.yml #
./docker/nginx/docker-compose.yml
の中身
version: '2' services: nginx : image: nginx ports: - "8080:80" volumes: - /home/test/htdocs/:/usr/share/nginx/html:ro restart: always
docker-compose.ymlを作成したら、docker-compose up -d
コマンドで起動させます。
# cd ./docker/nginx/;pwd /root/docker/nginx # # ls docker-compose.yml # # docker-compose up -d Starting nginx_nginx_1 #
これで起動したはずです。docker-compose.ymlを利用すれば、docker run
コマンドのようにいちいち長いコマンドを打たなくてもいいですし、ファイルにも設定が残ります。また、nginx以外にも同じファイルにサービスを書けば複数のdockerコンテナを起動することが可能です。
試しにMySQLとnginxを同じdocker-compose.ymlに記述して起動してみます。
まずは、MySQLのdockerの公式イメージをdocker pull
コマンドで持ってきます。
# docker pull mysql
docker-compose.ymlにMySQLを起動する記述を追加します。
# cd ./docker/nginx/;pwd /root/docker/nginx # # cat docker-compose.yml version: '2' services: nginx : image: nginx ports: - "8080:80" volumes: - /var/www/html:/usr/share/nginx/html:ro restart: always mysql : image: mysql ports: - "3306:3306" environment: - MYSQL_ROOT_PASSWORD=test #
docker-compose
コマンドで起動させます。
# docker-compose up -d Creating nginx_nginx_1 Creating nginx_mysql_1 #
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 130c49cf16da mysql "docker-entrypoint..." About a minute ago Up About a minute 0.0.0.0:3306->3306/tcp nginx_mysql_1 87a880588a96 nginx "nginx -g 'daemon ..." About a minute ago Up About a minute 0.0.0.0:8080->80/tcp nginx_nginx_1 #
MySQLとnginxのコンテナ二つを起動することがきました。MySQLコンテナの後にnginxコンテナを起動したい場合は、depends_on:
にどのservice起動後にnginxを起動したいのか書けばOKです。
ただし、MySQLのコンテナが起動しているかだけを見て、MySQLが正常に起動しているかは見てくれないので注意が必要です。あくまでもMySQLのコンテナ
が起動しているかしか見てくれません。
version: '2' services: nginx : image: nginx ports: - "8080:80" depends_on: - mysql <---mysqlコンテナの後にnginxコンテナを起動 volumes: - /var/www/html:/usr/share/nginx/html:ro restart: always mysql : image: mysql ports: - "3306:3306" environment: - MYSQL_ROOT_PASSWORD=test
尚、この方法だと、MySQLのデータはdockerコンテナが再起動するたびに消えます。データを永続的に使用したい場合は、volumesでホスト側の領域をマウントしてそこの領域をMySQLのデータ領域として使う必要がありますので注意してください。
おわりに
今更ながらdockerをはじめて触って見ましたが、これは確かにソフトウェアエンジニアに人気でるだろうなと感じました。便利ですからね。個人的な感想としては大雑把すぎるでしょうが、高機能なchroot
+daemontools
という印象を受けました。単純に便利なので、これからも積極的に使っていこうと思います。