Edited at

Dockerを体験してみるハンズオン Part1

More than 3 years have passed since last update.

前回はdockerを使う動機ということを書いたのですが今回は実際に動かしてみるハンズオン的なものです。

ここで使用しているソースコードはこちらに格納してあります。

https://github.com/NewGyu/docker-demo

readme.mdにもある程度のことを書いてあるので参考にしてください。


前提


解説すること


  • dockerコマンドの簡単な説明

  • およびその概念


解説しないこと


用意するもの


  • AWSのt2.microインスタンスを起動できるAWSアカウントと少々のお金

  • EC2インスタンスにssh接続できるスキル

  • 少々のLinuxコマンドの知識

※Vagrantなどで自分のローカルにLinuxサーバーを立てても構いません


まずは動かしてみよう


1. dockerが動くEC2インスタンスをつくる



  • ECS-Optimized Amazon Linux AMIからt2.microにEC2インスタンスを作成(リッチな人はもっと良いインスタンスでも構いません)

  • セキュリティグループでは80番ポートを開けておいてください


2. デモアプリのコンテナを動かす

$ docker run -it -p 80:80 newgyu/docker-sample:1.0.0


Unable to find image 'newgyu/docker-sample:1.0.0' locally
1.0.0: Pulling from newgyu/docker-sample
e2a4fb18da48: Pulling fs layer
58016a5acc80: Pulling fs layer
3f8d2e13b904: Pulling fs layer
f82bfe122da5: Pulling fs layer
0ae98a5db0c5: Pulling fs layer
2b61a94751a3: Pull complete
:

Digest: sha256:3137e6df67b07bd3f19ec08bdec7c9049a50a07900a45d1f2febfe9b256822a3
Status: Downloaded newer image for newgyu/docker-sample:1.0.0
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.111. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.111. Set the 'ServerName' directive globally to suppress this message
[Sun Oct 25 14:54:49.402642 2015] [mpm_event:notice] [pid 9:tid 140328118753152] AH00489: Apache/2.4.17 (Unix) configured -- resuming normal operations
[Sun Oct 25 14:54:49.412396 2015] [core:notice] [pid 9:tid 140328118753152] AH00094: Command line: 'httpd -D FOREGROUND'

さて、これで、

の2つが確認できると思います。(Tomcatの起動に10秒くらいかかるので せっかちにアクセスするとService Unavailableがでるかもしれません)

コンソールの方を見てみると、

111.238.90.15 - - [25/Oct/2015:15:28:35 +0000] "GET /index.jsp HTTP/1.1" 200 125

111.238.90.15 - - [25/Oct/2015:15:28:40 +0000] "GET /hello HTTP/1.1" 200 103

こんな感じのアクセスログが出ているかと思います。

終了は普通のフォアグラウンドで動いているプロセスを止めるのと同じで、Ctrl+Cです。

これでdockerのコンテナを動かすことが出来ました。パチパチ。


さて、解説


アプリケーションの構成


もう一度動かして確認


今度はバックグラウンドで動かす

$ docker run -d -p 80:80 newgyu/docker-sample:1.0.0

先ほど-itだったところを-dに変えて実行します。

docker runのオプションの意味はこんな感じです。

オプション
意味

i
ターミナルからコマンドの入力ができます

t
標準出力に実行したコマンドの結果が出力されます。普通は-itとセットで使います。

d
バックグラウンドでデーモンの用に動きます

See: https://docs.docker.com/reference/commandline/run/

さて、今度は先ほどのようなtomcatとapacheの起動ログは出ずにすぐに制御が返ってきましたね。


プロセスを確認する

$ ps -ef | grep -E "(httpd|tomcat)"

root 14352 2235 0 15:56 ? 00:00:00 /bin/sh -c /usr/local/bin/httpd-foreground
root 14367 14352 0 15:56 ? 00:00:00 httpd -DFOREGROUND
root 14396 14352 17 15:56 ? 00:00:37 /usr/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
bin 14405 14367 0 15:56 ? 00:00:00 httpd -DFOREGROUND
bin 14406 14367 0 15:56 ? 00:00:00 httpd -DFOREGROUND
bin 14407 14367 0 15:56 ? 00:00:00 httpd -DFOREGROUND
ec2-user 19434 13661 0 15:59 pts/0 00:00:00 grep --color=auto -E (httpd|tomcat)

ホストマシンにはインストールした覚えのないhttpdやjavaのプロセスが動いていますね。

このようにdocker runで動かしたコンテナは普通のプロセスとして動作します。

今度はdocker psというコマンドを使ってみましょう。

]$ docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
84eb0313086b newgyu/docker-sample:1.0.0 "/bin/sh -c /usr/loc 5 minutes ago Up 5 minutes 0.0.0.0:80->80/tcp, 8080/tcp stupefied_goodall

CONTAINER ID=84eb0313086bこれが先ほどdocker runで起動したコンテナのIDです。このIDはdockerの世界におけるプロセス番号みたいなものでコンテナを起動するたびに変わるものです。

このようにしてdockerのコンテナの動作状況を確認することが出来ます。


ポートを確認する

$ netstat -tan

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 :::80 :::* LISTEN
tcp 0 0 :::22 :::* LISTEN

80番ポートが開いていますね。dockerは仮想マシンのようなものでホストのポートを勝手に開けたりしないのですがなぜでしょう?

ヒントは先ほどdocker psした時のPORTS=0.0.0.0:80->80/tcp, 8080/tcpというところにあります。そしてdocker runした時の-p 80:80です。

オプション
意味

p
ホストのポートとコンテナのポートをマッピングします。 -p ホストのポート:コンテナのポート

このようにホストのポートからコンテナのポートにフォワードすることが出来ます。iptablesみたいですね。

$ sudo iptables -L -4

Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere ip-172-17-8-239.ap-northeast-1.compute.internal tcp dpt:http

dockerが裏でiptablesにルールを追加しているのです。

See: https://docs.docker.com/userguide/dockerlinks/#connect-using-network-port-mapping


コンテナのIPアドレス

コンテナには仮想マシンのNATモードの様にIPアドレスがふられます。

docker inspectで確認できます。

$ docker inspect -f "{{.NetworkSettings.IPAddress}}" 84eb031

172.17.8.239

※84eb031はコンテナIDです。フル桁指定しなくても一意になるところまで省略可能です。

このIPはdockerホスト内だけで有効なIPなので外部から直接コンテナにアクセスすることは出来ません。そのため、上記のような-pでポートのマッピングを行います。

また、コンテナを起動するたびにdockerが自動で割り振りをします。


docker inspect

単に次のようにしてみましょう。

$ docker inspect コンテナId

長いJSONが出ましたね。 -fで指定しているのはjqコマンドの評価式と同じようなものです。

正しくはGo言語のテンプレート式のようです。 ごめんなさいこのへんはあまり詳しくないんでこちらを参考にしてください。

See: https://docs.docker.com/reference/commandline/inspect/


もっと色々書こうと思っていたのですが、疲れたのでまた今度続きを書きたいと思います。

寝ます。

Part2はコチラ