【利用シーン】仮想サーバーに環境構築をする時
こんにちは。GMOクラウド開発グループ所属の縞子です。
すっかり春、というよりもう初夏ですね。飼い猫は少し前まで部屋の暖かい場所で丸くなっていましたが、最近は風通しの良い場所でおなかを見せて昼寝しています。
私も天気のいい日は、日なたでのんびり昼寝していたい・・・。
さて、寝ている訳にはいかないので本題に入ります。
私は開発や検証の際、ALTUS上で仮想サーバー(以下VMとします)を作成し、WebサーバーやDBサーバーなど必要なライブラリやパッケージをインストールして使っています。この環境構築の手間が省けるように、環境の自動作成方法はさまざまありますが、「Dockerにそろそろ触っておかないとなあ」とふと思ったので、Dockerを使って開発環境を構築してみました。
- 連載『Dockerを使って開発環境を構築してみました』のほかの記事はこちら
- 第1回:この記事
- 第2回:ALTUS Basic上でDockerを使って開発環境を構築してみました~その2~
Ⅰ.そもそもDockerって何ですか?
Dockerはアプリをビルド、出荷および実行するためのオープンソースのコンテナ型仮想化ソフトウェアです。PC実機、VMまたはクラウドなどさまざまなプラットフォーム上で、同一の仮想環境を簡単に構築できるという点が大きな特徴です。
コンテナ型仮想化ソフトウェアと何やら小難しい言葉が出てきましたね・・・。コンテナは、ものすごくざっくり言いますと、Linuxカーネルをプロセスごとに隔離する技術を利用した仮想環境です。
仮想環境と言えば、現在一般によく使われているものとしてバーチャル マシン(VM)があります。VMはハイパーバイザの上にゲストOSとして作成され、このゲストOSは独自にOSカーネル、各種バイナリやライブラリを持つ必要があるため、リソースを消費し、起動に時間がかかります。
対してコンテナは、OSカーネル、バイナリおよびライブラリなどはホストOSのものを利用できるため、ごく軽量となり、VMに比べ起動が速くなります。
Dockerについては、下図のようにホストOS上にDockerエンジンを乗せ、その上でコンテナを動かしています。
ちなみにコンテナ技術はUNIX OSに導入されたchrootシステムコールから始まり、FreeBSD Jail、LXC(Linux Containers)などに発展して来ました。Dockerも当初はLXCを利用していましたが、バージョン0.9以降libcontainerというライブラリを使用するようになったそうです
(参考:DOCKER 0.9: INTRODUCING EXECUTION DRIVERS AND LIBCONTAINER)。
Ⅱ.じゃあさっそくALTUS Basic上にDockerをインストールしてみよう!
Dockerを動かすために、ALTUS Basic上にVMを作成します。さまざまなOS上にDockerをインストールする手順がDocker社公式サイトに紹介されていますので、この内CentOS 6.5 (64-bit)の手順を参照して実行してみます。
という訳で、まずはCentOSバージョン6.5以上のVMをALTUS Basicに作らねば・・・
VMの作成方法は、アルとタスかるガイド - [STEP3] 仮想サーバーの作成にて紹介しています。この手順のテンプレート選択箇所で"CentOS 6.4 64bit_20140926"を選択します。
VMを作成できましたら、手元のPCからVMに接続するため、[STEP4] IP アドレスの追加の手順に従ってVMにIPアドレスを付与します。
加えて、PCからSSHポート(22番)およびHTTPポート(80番)を使ってVMに接続できるように、ファイアーウォールにこれらのポートの穴を空けます。
[STEP2] セキュリティグループの作成内の「セキュリティグループの設定」の手順に従って、VMが所属するセキュリティグループの「受信規則」に次の3つの規則を追加します。
●追加例: 接続元PCのグローバルIPアドレスをxxx.xxx.xxx.xxxとします。
(1) SSH接続用設定
CIDR: xxx.xxx.xxx.xxx/32
開始ポート: 22
終了ポート: 22
(2) HTTP接続用設定
CIDR: xxx.xxx.xxx.xxx/32
開始ポート: 80
終了ポート: 80
(3) MySQL接続用設定
CIDR: xxx.xxx.xxx.xxx/32
開始ポート: 3306
終了ポート: 3306
※補足
CIDR終端の"32"は、サブネットマスクのビット数が32ビットであることを示します。IPアドレスxxx.xxx.xxx.xxxに32ビットのサブネットマスクをかけることで、「このIPアドレスだけに限定してポートを空ける」ことを意図しています。
次に、VMにSSH接続します。もしSSH接続手順が不明な場合は、GMOクラウド ALTUS Basicシリーズ ガイド - SSHエミュレータを利用したアクセスにて紹介していますので、こちらを参照の上設定してください。
VMにSSH接続し、rootアカウントでログオンします。
なお、以降のほとんどのコマンドはroot権限を必要としますので、rootアカウントで実行するか、もしくはsudoコマンドでユーザーに一時的に root権限を与えて実行してください。
次のコマンドを実行しCentOSのバージョンを6系の最新版に更新します(併せてインストール済みの各種ライブラリやパッケージも更新します)。
# yum clean all
# yum update
コマンドの実行途中、処理を続行するかどうか確認するため「y/N」の入力が求められますので、その際はyを入力し続行を指示します。入力の手間を省きたい場合は「yum update -y」のように -y オプションを付けますと、入力待ちをスキップでき、処理を自動進行させることができます。
コマンドが完了しましたら次のコマンドを実行し、OSバージョンを確認します。
# cat /etc/redhat-release
CentOS release 6.6 (Final)
CentOS 6系の最新版である、6.6になりましたね。これでDockerをインストールする準備が整いました。
Ⅲ.Dockerをインストールし、Dockerデーモンを起動する
こちらのマニュアルを読むと、DockerのパッケージはExtra Packages for Enterprise Linux (EPEL)リポジトリに登録されているので、このリポジトリをサーバーに追加してねとのこと。
CentOSでは、次のコマンドでEPELリポジトリを追加できます。
# yum install epel-release
EPELリポジトリを追加しましたら、Dockerのパッケージを取得しインストールします。
# yum install docker-io
Dockerパッケージのインストールが完了しましたら、Dockerデーモンを起動します。
# service docker start
Starting cgconfig service: [ OK ]
Starting docker: [ OK ]
また、OSを再起動した時に自動的にDockerデーモンが起動するように設定します。
# chkconfig docker on
Dockerのインストールは以上です。簡単でしたね!
Ⅳ.それではいよいよ開発環境を作ってみよう
仮想環境となるDockerコンテナは、Dockerイメージを読み込んで起動します。
DockerイメージはDockerfileというテキストファイルに書かれた設定をビルドし生成されます。DockerfileはDocker Hubに公開されているものを使用することが可能ですが、自身で編集し作成することも可能です。
今回は環境をカスタマイズしたいので、自分自身でDockerfileを作成することとします。
Ⅳ-Ⅰ.Dockerfileを書いてみた
今回作成する環境は、次の通りです。
- CentOS 6.6
- Apache 2.2 (ssl 対応無し)
- MySQL 5.6 (community版)
- PHP 5.6
これらをインストールしたDockerイメージを生成するために、Dockerfileを作成する必要があります。Dockerfileのサンプルは、Docker社公式サイトやDocker Hubなどにありますので、それらを参考にして書いてみます。
と、その前に、ファイルを保存するディレクトリ(Dockerfileのリポジトリ)をVM内に作成します(このリポジトリのパスは一例です。環境に合わせ、適宜パスは変更してください)。
# cd /var/opt
# mkdir -p docker/repository/lamp_base
# cd docker/repository/lamp_base
ファイル作成時は /var/opt/docker/repository/lamp_base ディレクトリ内で、viやemacsコマンドなどを使用してDockerfileを編集します。VMホスト上でファイルを編集しない場合は、手元のPCのテキストエディターでDockerfileを作成・編集し、ファイル転送ソフトでVM側に転送します。
作成したDockerfileはこちらです。
Dockerfile
FROM centos:centos6
MAINTAINER GMO Cloud
RUN yum clean all && yum -y update
RUN yum install -y http://repo.mysql.com/mysql-community-release-el6-4.noarch.rpm
RUN yum install -y http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
RUN yum clean all
### Apache
RUN yum install -y httpd
RUN chkconfig httpd on
### MySQL Server (community version)
RUN yum install -y mysql-community-server mysql-community-client
RUN chkconfig mysqld on
# Edit mysql setting file
RUN echo "" >> /etc/my.cnf
RUN echo "[mysql]" >> /etc/my.cnf
RUN echo "default-character-set=utf8" >> /etc/my.cnf
RUN echo "" >> /etc/my.cnf
RUN echo "[client]" >> /etc/my.cnf
RUN echo "default-character-set=utf8" >> /etc/my.cnf
### PHP
RUN yum -y --enablerepo=remi-php56 install¥
php¥
php-mysqlnd¥
php-cli¥
php-mbstring¥
php-mcrypt¥
php-pdo¥
php-xml
# Edit php setting file
RUN sed -i -e "s|^;expose_php =.*$|expose_php = Off|" /etc/php.ini
RUN sed -i -e "s|^;date.timezone =.*$|date.timezone = Asia/Tokyo|" /etc/php.ini
RUN sed -i -e "s|^;mbstring.language =.*$|mbstring.language = Japanese|" /etc/php.ini
RUN sed -i -e "s|^;mbstring.encoding_translation =.*$|mbstring.encoding_translation = On|" /etc/php.ini
RUN sed -i -e "s|^;mbstring.detect_order =.*$|mbstring.detect_order = auto|" /etc/php.ini
RUN sed -i -e "s|^;mbstring.substitute_character =.*$|mbstring.substitute_character = none|" /etc/php.ini
# Add index.php file to document root directory
ADD index.php /var/www/html/
EXPOSE 80
EXPOSE 3306
CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"]
このDockerfileの処理の流れは次となります。
- ベースとするCentOS 6のイメージを、公式リポジトリからダウンロード。
- MySQLとPHPのインストールに必要なyumリポジトリのインストール。
- (a) 5行目の http://repo.mysql.com/mysql-community-release-el6-4.noarch.rpm : Community版MySQLのリポジトリ
- (b) 6行目のhttp://rpms.famillecollet.com/enterprise/remi-release-6.rpm : PHP 5.6 をインストールするためのremiリポジトリ
- Apacheをインストールし、OS起動時に自動起動するように設定。
- MySQLサーバーとクライアントをインストールし、MySQLサーバーがOS起動時に自動起動するように設定。またMySQLの設定ファイルを編集。
- PHPをインストールし、PHPの設定ファイルを編集。
- あらかじめVM内に用意したindex.php を、コンテナ内の/var/www/htmlにコピー。
- 80番(HTTP)ポートと3306番(MySQLサーバー)ポートを、通信待ち受け状態にする。
- コンテナ起動時にApacheを起動する。
また、各識別の意味については次の通りになります。
FROM ・・・ 生成するDockerイメージのベースイメージ(基にするもの)を指定します。ここではDocker公式リポジトリに登録されている、CentOS6を指定しています。
MAINTAINER ・・・イメージの作成者を指定します。
RUN ・・・ イメージ生成時に実行するコマンドを指定します。このRUNで指定された各コマンドは逐次処理されます。
ADD ・・・ファイルやディレクトリなどを、指定したコンテナ内ディレクトリ配下にコピーします。
EXPOSE ・・・ 指定されたポートで通信を待ち受けることをDockerに指示します。ここではHTTPポート(80番)とMySQL接続ポート(3306番)で通信を待ち受けます。
CMD ・・・ コンテナ起動時の初期処理を指定します。ここではApacheの起動を指定しています。
Dockerfileの記述方法についてのより詳しい情報は、こちらの公式サイトを参照ください。
ファイルの終わり近くに書いた"ADD index.php /var/www/html/"は、PHPが実行可能かテストするため、インストールされたPHPの詳細情報を出力するindex.phpをApacheのドキュメント ルート ディレクトリに置く、という処理を指示したものです。
index.phpはイメージをビルドする前に、Dockerfileと同じディレクトリ内に置いておきます。
作成したindex.phpの内容はこちらです。
index.php
<?php
phpinfo();
Ⅳ-Ⅱ.Dockerファイルをビルドしよう
Dockerfileをビルドして、Dockerイメージを生成します。
# docker build -t gmocloud/lamp_base /var/opt/docker/repository/lamp_base/.
コマンドの最後に「Successfully built」と表示されましたらビルドは成功していますが、念のためイメージがDockerに登録されたかどうか確認します。
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
gmocloud/lamp_base latest {イメージ ID} 10 minutes ago 944.5 MB
ばっちり登録されていますね!
Ⅴ.Dockerコンテナを起動してwebページにアクセスしてみる
作成したgmocloud/lamp_baseを起動すると、このDockerコンテナ内でApacheが起動されているはずです。また、PHPもインストールされているはずですので、Dockerfile内に追記した「index.php」が正常に表示されるはずです。
Dokerコンテナは次のコマンドを実行して起動します。
# docker run -t -i -p 80:80 -p 3306:3306 gmocloud/lamp_base
「-p 80:80」というオプションを指定することで、Dockerコンテナ内のTCP 80番ポートと、VMのTCP 80番ポートがバインディングされます。「-p 3306:3306」も同様に、この指定によりMySQLサーバーに外部から接続するためのTCP 3306番ポートがVMの3306番ポートにバインディングされます。
もし -p オプションを付けない場合は、TCP 5000番ポートでバインディングされます(-p 5000:5000と指定した場合と同じ状態になります)。
80番ポートのバインディングにより、例えば手元のPC上のブラウザからhttp://(VMに付与したグローバルIPアドレス)/ にアクセスしますと、Dockerコンテナ上のApacheにアクセスできることとなります。
ややこしいことを書きましたが、ブラウザでhttp://(VMに付与したグローバルIPアドレス)/ にアクセスした結果、下図のようなPHP情報が表示されましたら期待通りの結果です!
Ⅵ.Dockerコンテナの停止
Dockerコンテナの状態は、次のコマンドで確認できます。
# docker ps –l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
{コンテナ ID} gmocloud/lamp_base:latest "/usr/sbin/apachectl About a minute ago Up About a minute 0.0.0.0:80->80/tcp, 0.0.0.0:3306->3306/tcp {コンテナ名}
※コンテナIDとコンテナ名は、Dockerデーモンが自動的に付与します
STATUS が「Up」となっているため、gmocloud/lamp_baseコンテナが起動中であることが分かります。また、80番と3306番のポートのバインディングがされていることが確認できますね。
このコンテナを停止する場合は、次のコマンドを実行します。
# docker stop <docker ps で確認したコンテナID>
停止した後、もう一度docker ps –l を実行すると、STATUSは「Exited」になります。
Ⅶ.Dockerコンテナとイメージの削除
不要になったDockerコンテナやイメージは削除することができます。次のコマンドを実行すると、停止しているすべてのコンテナを削除することができます。
# docker rm `docker ps -a -q`
さらに生成したDockerイメージを削除する場合は、まず登録されたイメージ一覧を確認します。
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
gmocloud/lamp_base latest {イメージ ID} About an hour ago 944.5 MB
Dockerイメージの削除は、次のコマンドを実行します。
# docker rmi <docker imageで確認したイメージID>
Ⅷ.最後に・・・
とりあえず当初の目的であった、「Dockerを触ってみる」ということは達成できました。
しかし、開発環境として利用するために、コンテナにSSH接続できるようにする、開発アプリケーションのデプロイ手順などを追加するなど、まだまだ課題があります。その課題をクリアできましたら、またクラウドアカデミーで皆さんに公開します!
Dockerfileはサンプルの見よう見まねで書いたものの、よりエレガントな書き方があるはずですので、こちらに記載した内容はあくまでも参考情報として見ていただけますと幸いです。