Septeni Engineer's Blog

セプテーニエンジニアが綴る技術ブログ

EC2にDockerをインストールしてNginxコンテナを作る

セプテーニ・オリジナルの池田です。

弊社でDockerが使用されることになり、最近Dockerについて調べました。

f:id:taketor:20151119154325p:plain:w500

今回Dockerfileを使わずに、DockerをインストールしてからNginx動かし、
Dockerのコンテナ、イメージ、基礎的なコマンドなどを説明したいと思います。

目次

OS
Amazon Linux AMI release 2015.09

Dockerのインストール

まずDokcerの環境を作ります。

◼︎ Dockerをインストール

[ec2-user ~]$ sudo yum install -y docker

◼︎ Dockerを起動

[ec2-user ~]$ sudo service docker start
Starting cgconfig service:                                 [  OK  ]
Starting docker:    

◼︎ ec2-userをdockerグループに追加

[ec2-user ~]$ sudo usermod -a -G docker ec2-user
[ec2-user ~]$ cat /etc/group |grep docker
docker:x:497:ec2-user

グループに追加されていることを確認したら、一度ログアウトして再度ログインしてください。
dockerグループに所属していれば、sudoなしで ec2-userから Dockerコマンドが使えます。

[ec2-user ~]$ docker info
Containers: 0
Images: 0
Storage Driver: devicemapper
 Pool Name: docker-202:1-263567-pool
 Pool Blocksize: 65.54 kB
 Backing Filesystem: extfs
 Data file: /dev/loop0
 Metadata file: /dev/loop1
 Data Space Used: 305.7 MB
 Data Space Total: 107.4 GB
 Metadata Space Used: 729.1 kB
 Metadata Space Total: 2.147 GB
 Library Version: 1.02.93-RHEL7 (2015-01-28)
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 4.1.10-17.31.amzn1.x86_64
Operating System: Amazon Linux AMI 2015.09

(docker info :dockerのシステム全体を表示する)

権限がない場合は以下のような出力になります。

[ec2-user ~]$ docker info
Get http:///var/run/docker.sock/v1.19/info: dial unix /var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?


さて環境ができたので早速Dockerを試して行きましょう。

公開レジストリからCentOS7のイメージを取得

f:id:taketor:20151120100035p:plain:w500

コンテナはイメージから生成されて、複数のバージョンのイメージがリポジトリに格納できます。
自分で作成したリポジトリは「Docker Hub」というインターネット上の公開レジストリへ登録することができ、「Docker Hub」に登録されているリポジトリは誰でもダウンロードできます。

コンテナ   イメージという型をもとに作られる実体(オブジェクト指向におけるインスタンス)
イメージ   コンテナという実体を作成するための型(オブジェクト指向におけるクラス)
リポジトリ  複数のバージョンのイメージが格納されている


Docker用語について以下のリンクわかりやすく掲載されています。
Qoosky - Docker チートシート

それでは「Docker Hub」からCentOS7のコンテナイメージがあるリポジトリを取得します。

◼︎ リポジトリー検索
「Docker Hub」から「enakai00」というリポジトリを検索します。

[ec2-user ~]$ docker search enakai00
NAME                  DESCRIPTION                               STARS     OFFICIAL   AUTOMATED
enakai00/web                                                    0                    
enakai00/app                                                    0                    
enakai00/dbs                                                    0                    
enakai00/fedora       Sample fedora repository for dockerbon.   0                    
enakai00/centos       Sample CentOS repository for dockerbon.   0                    
enakai00/test-httpd                                             0                    
enakai00/httpd                                                  0                    
enakai00/ostools                                                0    

(docker search <文字列>:Docker Hubから<文字列>を含むイメージを検索)
「enakai00/centos」 がリポジトリ名になり、リポジトリ名は先頭部分が「<ユーザー名>/」で
始まるようになっています。

◼︎ リポジトリの取得
docker pullコマンドを使ってリポジトリを取得します。

[ec2-user ~]$ docker pull -a enakai00/centos

(docker pull -a <リポジトリ名>レジストリにあるリポジトリをローカル環境に持ってくる)

ダウンロードしたリポジトリの内容を確認します。

[ec2-user ~]$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
enakai00/centos     centos6             a005304e4e74        5 months ago        203.1 MB
enakai00/centos     centos7             7322fbe74aa5        5 months ago        172.2 MB
enakai00/centos     latest              7322fbe74aa5        5 months ago        172.2 MB

(docker images:保存したイメージを確認する)
enakai00/centosリポジトリにcentos6とcentos7のタグをもったイメージを確認できました。
このイメージからコンテナを起動させることができます。

コンテナ作成

◼︎ イメージからコンテナ作成
先ほど取り込んだイメージからcentos7のコンテナを作成します。

f:id:taketor:20151120102600p:plain:w500

[ec2-user ~]$ docker run -it --name centos01 enakai00/centos:centos7 /bin/bash
[root@0b7ddb71a57f /]# 

(docker run -it --name <コンテナ名> <レポジトリ名>:<タグ名> /bin/bash: <コンテナ>を作成しコマンドプロントができる状態で起動させる)

このコマンドはコンテナを起動させ、コンテナに端末デバイスを持たせることでコマンドプロントができる状態にしています。


Dockerコンテナは起動時にttyが生成されないので、docker runコマンドの後に
オプション -i (--interactive)-t (--tty) をつけて起動することで、
コンテナに擬似TTY端末を割りあてて対話的にbashが使えるようにしています。

コンテナ内に入ってOSのバージョンを確認しましょう。

[root@0b7ddb71a57f /]# cat /etc/centos-release
CentOS Linux release 7.1.1503 (Core) 

CentOS7.1のルートディレクトリが確認できました。

このように動かしてみるとコンテナ内部でCentOS7.1が実際に動いているように見えますが、実際にゲストOSが動いているわけではありません。 この環境ではec2インスタンスのNameSpace(Linuxカーネルで実装されている機能)を使ってコンテナが動いているのです。 コンテナの中身はプロセスとイメージを起動させてできたスナップショット(ディスクイメージ)になります。

コンテナの実態はこちらのリンクに詳しく記載されています。
dockerについてのメモ - Qiita

コンテナ内にアプリケーションを入れる

CentOS7のコンテナにNginxを入れてwebアプリケーションを作成してみます。

◼︎ Nginx をインストール
Nginxをインストールするためにyumリポジトリを登録して、Nginxをインストールします。

[root@0b7ddb71a57f /]# rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
[root@0b7ddb71a57f /]# yum install nginx -y 

レポジトリを作成する

◼︎ ホストからコンテナのレポジトリを作成

f:id:taketor:20151120104219p:plain:w500

コンテナにNginxがインストールされたら、Ctrl + P Qを押して 一旦ホスト側のEC2のコマンドプロントに戻り、コンテナを確認します。

[ec2-user ~]$
[ec2-user ~]$ docker ps -a
CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS              PORTS               NAMES
0b7ddb71a57f        enakai00/centos:centos7   "/bin/bash"         About an hour ago   Up About an hour                        centos01 

(docker ps -a:コンテナ一覧を表示 -aオプションを付けないと、起動しているコンテナだけ表示)

コンテナが起動しているとリポジトリ作成時にファイルの内容の不整合が発生する可能性があるので、コンテナを停止させます。

[ec2-user ~]$ docker stop centos01
centos01

(docker stop:起動しているコンテナを停止させる)

停止状態のコンテナに対してdocker commitを使用すると、コンテナに接続していたスナップショット(ディスクイメージ)を複製し、保存することができます。

[ec2-user ~]$ docker commit centos01 hoge/nginx:ver1.0
328d5139932bf439d6a31f48a4a03bd4c99fa72b7b6ec4f14d21e9745f12d03a

(docker commit <コンテナ名> <リポジトリ名>:<タグ名>:コンテナを保存先の「リポジトリ:タグ名」で保存する)

hoge/nginxリポジトリを作成して タグ名ver1.0をつけて保存しています。 出力された文字列は、作成したコンテナイメージのイメージIDと呼ばれイメージを判別する識別子となります。

リポジトリを確認するためにdocker imagesコマンドを使ってみましょう。

[ec2-user@i ~]$ docker images hoge/nginx 
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hoge/nginx          ver1.0              328d5139932b        4 minutes ago       288.3 MB

イメージが保存されていますね。
(docker imagesコマンドはリポジトリー名を指定することで該当のリポジトリーの情報だけを表示してくれます。)

コンテナ内部でwebサーバーの立ち上げ

先ほど保存したNginxコンテナイメージを利用して、webサーバを立ち上げてみます。
GIPを持たせていないのでポートフォワードをしてホストからアクセスできるか確認します。

◼︎ Nginxのリポジトリからコンテナを作成

[ec2-user ~]$ docker run --privileged -d -p 8000:80 --name web01 hoge/nginx:ver1.0  /sbin/init
ca8d886c9c3a6e942b79b86535d2d3e6f5e6d6f244e7e16fc59d9185ff9107ee
[ec2-user ~]$ docker exec -it web01 /bin/bash
[root@ca8d886c9c3a /]# 

CentOS 7ではinitデーモンがsystemdなので、今回はコンテナをsystemdで起動させて、
起動しているコンテナにdocker execでログインします。

◼︎ Nginxを起動させる
Nginxのルートディレクトリにファイルをおき、Nginxを起動させます。

[root@ca8d886c9c3a /]# echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
[root@ca8d886c9c3a /]# systemctl enable nginx.service
ln -s '/usr/lib/systemd/system/nginx.service' '/etc/systemd/system/multi-user.target.wants/nginx.service'
[root@ca8d886c9c3a /]# 
[root@ca8d886c9c3a /]# systemctl start nginx.service


◼︎ Nginxの動作確認
Ctrl + P Qを押して ホスト側のEC2のコマンドプロントに戻り、Nginxが正常に動いているか確認をします。

[ec2-user ~]$ curl -s http://localhost:8000/ | head
<h1>Hello, Docker!</h1>

ポートフォワードのアクセス先でNginxが動いていますね。

またホストからdocker cpコマンドを使うことでNginxのアクセスログがホストから確認できます。

[ec2-user ~]$ docker cp web01:/var/log/nginx/access.log /tmp/
[ec2-user ~]$ cat /tmp/access.log
192.168.X.X - - [19/Nov/2015:05:54:37 +0000] "GET / HTTP/1.1" 200 24 "-" "curl/7.40.0" "-"

(docker cp:コンテナとローカルのファイルシステム間のファイル、フォルダをコピーする)

以上DockerをインストールしてNginxコンテナを作成してみました。

今回実際にDockerに触れてみることで、Dockerのコンテナ、イメージなどの用語や コンテナのライフサイクルなど勉強になりました。

参考サイト

◼︎ Docker Docs
https://docs.docker.com/

◼︎ Docker チートシート
https://www.qoosky.net/references/206/

◼︎ CentOS 7のDockerコンテナ内でsystemdを使ってサービスを起動する
http://qiita.com/yunano/items/9637ee21a71eba197345