Dockerを使い始めてみたので、覚え書き的に書いていきます。
おかしいところなどあればご指摘下さいm(_ _)m
今回のゴール
・Dockerの基本機能の把握+理解
・ローカル環境でnginxが動作するDockerコンテナを構築する。
Dockerとは
DockerはImmutable Infrastructureという概念を採用しており、どの環境にデプロイしても冪等性を担保したインフラを実現する技術である。
つまり、
・デプロイしたら動かなかった
・デプロイ先によってバージョンが異なる
といった問題が生じない
Dockerはコンテナと呼ばれるアプリケーションのパッケージを作成することでき、Dockerfileに設定を記述することで独自のコンテナを作成することができる。
もちろん予め用意されたイメージを利用することも可能で、dockerhubというサイト上に存在するイメージをpullしてきて利用ができる。
Dockerfile内に利用したいイメージを記述することで既存のイメージに設定の追加した独自のイメージを作成することも可能。
DockerはLinuxでしか利用できないためMacで利用するにはboot2docker経由でDockerを利用する必要がある。
http://boot2docker.io/
Virtualboxのインストール
boot2dockerはvirtualbox上で走るcoreosの仮想マシンなのでまずはVirtualboxをインストールする
https://www.virtualbox.org/wiki/Downloads
Dockerのインストール
brewでDocker/boot2dockerをインストール
brew install docker boot2docker
インストールされたことを確認
boot2docker version
docker -v
まずはdockerを動かすための仮想マシンであるboot2dockerを初期化→起動
boot2docker init
boot2docker up
upした時点でDOCKER_HOSTという環境変数を設定するように出力されるので、それに従って~/.zshrcや~/.bash_profileなどに適宜設定する。
CentOSイメージを取得
DockerHub上には多数の公式イメージも存在している
https://registry.hub.docker.com/
今回はそこからCentOSの公式イメージをインストールする。
docker pull centos
docker pullはイメージを取得してくるコマンド
docker images
docker imagesでcentosが表示され、pullされていることを確認する
早速動かしてみる
早速インストールしてきたイメージを動かしてみる。
↓のサンプルはcentosイメージに"hello docker"を出力させる例
docker run centos echo "hello docker"
また、以下のように標準入力を開く事も可能である
% docker run -i -t centos /bin/bash
bash-4.2# echo "hello docker"
hello docker
bash-4.2# exit
exit
イメージを保存する
さらに、イメージに対して変更を加えた場合(例えば、標準入力内でyum installなどを行った際など)、その変更適用済みのイメージを他の部分でも使いたい場面などがある。
Dockerにはcommitという変更を適用した状態をセーブする機能が存在し、commitすればその後、そのコミットした状態からイメージを操作することができる。
↓の例ではecho "hello world"
を実行し、docker ps -a
で実行済みのプロセスも含め表示させている。
% docker run centos echo "hello world"
hello world
Reo-no-MacBook-Pro% docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43fa67c118f5 centos:centos7 echo 'hello world' 24 hours ago Exited (0) 3 seconds ago mad_lumiere
するとそれぞれにCONTAINER_IDというユニークなIDが発行されるので、そのIDをcommitしていく
% docker commit 43fa67c118f5 centos:helloworld
de44ab74e61aa20156013946717c3f13937802b63e88378d5c8cac4b55ea9ae6
↑の例では43fa67c118f5というcontainer_idに対してcentos:helloworldというイメージを作成している
イメージの名前は「:」で区切られているが、手前がイメージ名、後ろがタグとなっている。
実際にイメージが作成出来ているかを確認するために、イメージの一覧を出力するdocker images
を実行する
% docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos helloworld de44ab74e61a 24 hours ago 236.4 MB
実際にtagがhelloworldとなっているdockerイメージが生成されているのを確認できた。
Dockerイメージを作成する
Dockerfileを作成
これまでは既存のdockerイメージを利用していたが、実際に自分でイメージをビルドして使ってみる。
Dockerのイメージをビルドする際はDockerfileというファイルを作成し、その中に環境を記述してあげれば、思い通りのイメージを作成できる。
以下の例ではnginxをインストールし、実行する命令を記述している。
FROM centos
MAINTAINER reoy
RUN yum update -y
ADD nginx.repo /etc/yum.repos.d/
RUN yum install -y nginx
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]
Dockerfileの説明としては
FROM
は作成するイメージのもととなるイメージ。ここではcentosの環境を利用したいのでFROMにcentosを指定している。
MAINTAINER
は作成者
RUN
はビルド時に実行される命令を設定することができるコマンド
ADD
はファイルをローカルからイメージの中にコピーするコマンド
EXPOSE
はイメージがコンテナとして実行された際に開放するポートを指定するコマンド
ENTRYPOINT
はCMD
というコマンドと似ているが両方共にビルド時ではなくdocker runのタイミングで実行されるコマンド。それぞれの違いは主にシェルを通してコマンドを実行しているかどうかである。
また、上記の例のnginx.repoは
http://wiki.nginx.org/Install
↑のサイトを参考に作成している
ビルドしてみる
ここまでで作成したDockerfileを基に実際にビルドしてみる
docker build -t centos/nginx:test .
↑ではビルドを実行しており、-tオプションをつけることでタグをつけている。つまり例ではcentos/nginxという名前のイメージを作成し、そのイメージにtestというタグをつけている。
末尾の「.」はカレントディレクトリを指しており、絶対パスでDockerfileのあるディレクトリを指定する事も可能。
docker images
を実行して、先ほど作成したイメージが作成されていることを確認
% docker images
centos/nginx test 775fd7e82bf1 37 hours ago 321.8 MB
RUNしてみる
それでは先ほど作成したイメージを実行してみる
% docker run -d -p 80:80 centos/nginx:test
6a9d9f667462d7d216f76f2a41753c0362221c4f85dc47e2f99b304bbc93e519
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6a9d9f667462 centos/nginx:test /usr/sbin/nginx -g ' 38 hours ago Up 13 hours 0.0.0.0:80->80/tcp lonely_ritchie
docker run
コマンドに-p
オプションを付けることでホストOSとdockerコンテナのポートを紐付ける事が可能となる。この場合はホストの80番ポートとコンテナ内の80番ポートの紐付けを行っている。
docker ps
で実際にnginxが実行されてことを確認できた。
それではcurl
をローカルホストに投げてみる
curl http://localhost:80
curl: (7) Failed connect to localhost:80; Connection refused
refuseされたがこれは当然の事である。
先ほど-p
オプションをつけてポートを80番に設定しているがそれは「仮想マシン(boot2docker)の80番ポートとdockerの80番ポート」を紐付けたに過ぎないため、OSX上のポートとは紐付いていない。
そこでVirtualboxのポートフォワーディング機能(GUI)を利用してOSXの8080番ポートと仮想マシンの80番ポートを紐付ける必要がある。
もちろん以下のVBoxManageコマンドを利用すればコマンドラインからVirtualBoxの仮想マシンのポートフォワーディングを実行できる。
VBoxManage controlvm "boot2docker-vm" natpf1 "nginx,tcp,127.0.0.1,8080,,80"
ポートフォワーディングを実行したうえでもう一度curlを実行し、値が返ってくることを確認
% curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
もちろんブラウザからもlocalhost:8080にアクセスで確認可能
次回予告
AWS Elastic Beanstalkを使って実際にrailsアプリをデプロイするところまでやってみようと思いますー。