【利用シーン】仮想サーバーに環境構築をする時

こんにちは。GMOクラウドの縞子です。 以前、クラウドアカデミーに「ALTUS Basic上でDockerを使って開発環境を構築してみました」という記事を投稿しました。今回は、その後より実際的に開発環境として使うために付け加えたDockerの利用手順について紹介したいと思います。

Ⅰ. 実現したいこと
Ⅱ. LAMP + SSHサーバー環境の作成
Ⅱ-Ⅰ. Dockerfileの編集
Ⅱ-Ⅱ. 追加ファイルの内容について
Ⅲ. Dockerイメージのビルド
Ⅳ. Dockerコンテナの起動
Ⅴ. DockerコンテナにSSHで接続
Ⅵ. Apache + PHP状態確認
Ⅶ. MySQLの接続確認
Ⅷ. 最後に…
Ⅸ. 参考情報

Ⅰ. 実現したいこと

前回の手順をベースに、1~5までの手順を確認します。6についてはプライベート リポジトリを構築して実現したいと考えていますが、まだその準備が整っていないため今回は割愛します。

Ⅱ. LAMP + SSHサーバー環境の作成

作成する環境は次の通りです。

  • CentOS 6.6
  • Apache 2.2 (ssl対応無し)
  • MySQL 5.6 (community版)
  • PHP 5.6
  • OpenSSH

Dockerコンテナを起動した際、Apache、MySQLおよびsshdなどのサービスを自動起動させたいと思います。
Dockerfileへのsshdのインストール・設定方法は、Docker公式サイトや、Docker HubにアップされているさまざまなDockerfileに例がありますので、これらを参考にします。
また、1つのサービスを起動させる際には、Dockerfileの中でCMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"] のようにCMDまたはENTRYPOINTなどのコマンドを使用しますが、複数サービスを起動させる場合には少し工夫が必要となります。
Dockerの公式サイトに、その工夫の一つとしてsupervisorを利用する手順が紹介されていましたので、こちらを参考にして設定を記述してみます。

Ⅱ-Ⅰ. Dockerfileの編集

DockerエンジンをインストールしたホストOS上に/var/opt/docker/repository/lamp_sshというディレクトリを作成し、そのディレクトリ内に必要な設定を記述したDockerfileを作成しました。

 $sudo -s
 #mkdir –p /var/opt/docker/repository/lamp_ssh
 #cd /var/opt/docker/repository/lamp_ssh
 #vi Dockerfike

※ここではエディターとしてviを使用しましたが、viに馴染みの無い方はその他のエディターを(emacsなど)を使用するか、ローカルPC上で編集したDockerfileをホストOSに転送してください。

作成したDockerfileの内容は次の通りです。

●Dockerfile

 FROM centos:centos6
 MAINTAINER GMO Cloud

 ### Install Apache, MySQL, PHP, openssh, sudo, git and supervisor ---①
 RUN yum clean all ¥
  && yum -y update ¥
  && yum install -y http://repo.mysql.com/mysql-community-release-el6-4.noarch.rpm ¥
  && yum install -y http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
 RUN yum install -y httpd ¥
   mysql-community-server ¥
   mysql-community-client ¥
   openssh-server ¥
   sudo ¥
   python-pip ¥
   git
 RUN yum --enablerepo=remi-php56 install -y ¥
   php ¥
   php-mysqlnd ¥
   php-cli ¥
   php-mbstring ¥
   php-mcrypt ¥
   php-pdo ¥
   php-xml
 RUN yum clean all
 RUN pip install --upgrade supervisor supervisor-stdout

 ### supervisord setting ---②
 ADD supervisord.conf /etc/supervisor/supervisord.conf     

 ### sshd setting ---③
 RUN sed -i -e "s|^#PermitRootLogin .*$|PermitRootLogin yes|" /etc/ssh/sshd_config \
  && sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
 RUN ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa ¥
  && ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa ¥
  && chmod -R 700 /etc/ssh

 ### MySQL setting ---④
 RUN mv /etc/my.cnf /etc/my.cnf.org
 ADD my.cnf /etc/my.cnf
 RUN chmod 640 /etc/my.cnf
 RUN /etc/init.d/mysqld start ¥
  && sleep 3 ¥
  && mysqladmin -u root password 'mysqlpass' ¥
  && (echo 'grant all privileges on *.* to testuser@"localhost" identified by "testuser123" with grant option;' | mysql -u root -pmysqlpass) ¥
  && (echo 'grant all privileges on *.* to testuser@"%" identified by "testuser123" with grant option;' | mysql -u root -pmysqlpass) ¥
  && /etc/init.d/mysqld stop
 RUN /usr/bin/mysql_install_db

 ### PHP setting ---⑤
 RUN sed -i -e "s|^;expose_php =.*$|expose_php = Off|" /etc/php.ini ¥
  && sed -i -e "s|^;date.timezone =.*$|date.timezone = Asia/Tokyo|" /etc/php.ini ¥
  && sed -i -e "s|^;mbstring.language =.*$|mbstring.language = Japanese|" /etc/php.ini ¥
  && sed -i -e "s|^;mbstring.encoding_translation =.*$|mbstring.encoding_translation = On|" /etc/php.ini ¥
  && sed -i -e "s|^;mbstring.detect_order =.*$|mbstring.detect_order = auto|" /etc/php.ini ¥
  && sed -i -e "s|^;mbstring.substitute_character =.*$|mbstring.substitute_character = none|" /etc/php.ini

 ### Change the root's password and add a new user ---⑥
 RUN echo "root:password123" | chpasswd ¥
  && useradd testuser ¥
  && echo "testuser:testuser123" | chpasswd

 ### Make a virtual host ---⑦
 COPY develop.conf /etc/httpd/conf.d/
 RUN mkdir -p /home/webroot/develop
 COPY index.php /home/webroot/develop/
 RUN chown -R testuser:apache /home/webroot

 ### Expose httpd, mysqld and sshd ports. ---⑧
 EXPOSE 80 3306 22

 ### Start multiple processes from supervisor ---⑨
 CMD ["/usr/bin/supervisord", "--configuration=/etc/supervisor/supervisord.conf"]

※ファイルの内容についての補足※

① 必要な各種パッケージをインストールします。
まずはApache、MySQL、sudo(rootアカウントに昇格するためのパッケージ)、PHP、gitおよびpython-pipをyumコマンドでインストールします。
Supervisorもyumのepelリポジトリからインストールできるのですが、その場合supervisorからMySQLを起動するときに使うpidproxy というツールがインストールされないため、pip(pythonのパッケージ管理用パッケージ)からsupervisorをインストールします。

② あらかじめ用意したsupervisord.confをコンテナ内にコピーします。

③ sshdの設定を行います。ここではrootアカウントのパスワードによるログオンを許可し、ログオンの前後でログオン ユーザーのuidをプロセスの属性に記録するように指定しています。 また、SSHサーバーの鍵をRSAとDSAの2つの認証方式で生成しています。

④ MySQLの初期設定を行っています。あらかじめ用意したMySQLの設定ファイル(my.cnf)をコンテナ内にコピーし、デフォルトで用意されていたmy.cnfと差し替えます。
続いてMySQLのrootアカウントのパスワードを変更し、testuserアカウントをMySQLに追加します。testuserアカウントにはローカルからの接続と、リモートからの接続の両方を許可します。

⑤ PHPの設定を行います。ここでは日本語利用のための設定を行っています。

⑥ OSのrootアカウントのパスワードを変更します。また、testuserアカウントを追加し、このユーザーのパスワードを設定します。

⑦ ApacheのデフォルトWebルート ディレクトリ(/var/www/html)以外のディレクトリ(/home/webroot/develop)に開発ソースコードを置きたいため、このディレクトリをWebルート ディレクトリとするバーチャル ホスト設定を追加します。
⑧ Apache、MySQLおよびsshdに接続するために、TCPの各ポート(80、3306および22番)を通信待ち受け状態にします。

⑨ Dockerコンテナをバックグラウンドで実行した際にsupervisorを自動起動させます。なお、SupervisorはApache、MySQLおよびsshdを起動します。

Ⅱ-Ⅱ. 追加ファイルの内容について

作成したDockerfile内では、次の4つのファイルをコンテナ内にコピーするよう指示しています。コピーする各ファイルは、Dockerfileと同じ場所(/var/opt/docker/repository/lamp_ssh/)に保存しておきます。

●コンテナ内にコピーするファイル

  • supervisord.conf ・・・ supervisorの設定ファイル
  • my.cnf ・・・ MySQLの設定ファイル
  • develop.conf ・・・ Apacheのバーチャル ホスト設定ファイル
  • index.php ・・・ Apache+PHPの動作確認用PHPファイル

それぞれのファイル次の内容で作成しました。

■supervisord.conf

 [supervisord]
 nodaemon=true

 [program:sshd]
 command=/usr/sbin/sshd -D

 [program:httpd]
 command=/usr/sbin/apachectl -D FOREGROUND

 [program:mysql]
 command=/usr/bin/pidproxy /var/run/mysqld/mysqld.pid /usr/bin/mysqld_safe
 autostart=true
 autorestart=true

※supervisord.confでは、プロセスの起動コマンドを記述します。最初の2行ではsupervisord自身をフォアグラウンドで起動するように設定しています。この設定が無い場合、Dockerコンテナ内でsupervisorが指定した各プロセスを起動できなくなりますので必ず記述します。

■my.cnf

 [mysqld]
 datadir=/var/lib/mysql
 socket=/var/lib/mysql/mysql.sock

 # Disabling symbolic-links is recommended to prevent assorted security risks
 symbolic-links=0

 # Recommended in standard MySQL setup
 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

 default-storage-engine=innodb
 explicit_defaults_for_timestamp=true

 # UTF8 settings
 character_set_server = utf8
 collation-server=utf8_general_ci
 skip-character-set-client-handshake

 [mysqld_safe]
 log-error=/var/log/mysqld.log
 pid-file=/var/run/mysqld/mysqld.pid

 [mysql]
 default-character-set=utf8

 [client]
 default-character-set=utf8

※MySQLの設定ファイルをあらかじめ用意し、コンテナ内のデフォルトで用意されたmy.cnfと差し替えます。今回は必要最小限の設定のみを記述していますので、環境に応じて設定を追加・編集します。

■develop.conf

 <VirtualHost *:80>
  ServerAdmin testuser@xxx.yyy.zzz (※任意のメールアドレスを指定)
  ServerName xxx.yyy.zzz (※Dockerコンテナ上で動作するサーバーのDNS名を指定)
  DocumentRoot /home/webroot/develop
  <Directory /home/webroot/develop>
   AllowOverride all
   Options -MultiViews
  </Directory>
 </VirtualHost>

■index.php

 <?php
  phpinfo();

※develop.confで設定した/home/webroot/develop配下に、このindex.phpファイルを置きます。もし設定が適切になされていれば、WebブラウザからDockerコンテナのTCP 80番ポートにアクセスした際、このindex.phpファイルが読み込まれてPHPの設定が表示されるはずです。

Ⅲ. Dockerイメージのビルド

Dockerfileをビルドして、Dockerイメージをビルドします。

 #docker build -t gmocloud/lamp_ssh /var/opt/docker/repository/lamp_ssh/.

ビルドが開始され、最後に「Successfully built」のメッセージが表示されたら成功です。

Ⅳ. Dockerコンテナの起動

ではいよいよDockerコンテナを起動します。

 #docker run -d -p 10022:22 -p 13306:3306 -p 10080:80 --name lamp_ssh gmocloud/lamp_ssh

前回も補足しましたが、-p オプションでポートをバインディングしています。たとえばDockerコンテナ内のTCP 22番ポートをホストOSのTCP 10022番ポートにバインディングしています。また、--nameオプションでコンテナの名前を指定しています。

Ⅴ. DockerコンテナにSSHで接続

設定が適切にできていれば、コンテナにSSHで接続できるはずです。 ローカルPCからTeratermなどの端末エミュレーターを利用してコンテナに接続してみます。

●接続設定
ホスト: DockerホストOSのDNS名またはIPアドレス
接続先ポート: TCP 10022
ユーザー名: testuser
パスワード:testuser123

無事ログオンできました!

ちなみに上記の接続設定を使用してeclipseやNetBeansなどのIDEにてリモート接続設定を行いますと、通常にWebルート ディレクトリ(/home/webroot/develop)上のファイル編集が可能となります。

Ⅵ. Apache + PHP状態確認

次に、ApacheとPHPが正常に動作しているか確認します(前回も同じ確認をしましたね)。 正常に動作していれば、WebブラウザからコンテナのWebサイトにアクセスした際にindex.phpのファイルがロードされるはずです。 コンテナ内のWebサイトは次のURLでアクセスできます。 http://(DockerホストOSのDNS名またはIPアドレス):10080

Ⅶ. MySQLの接続確認

最後にMySQLへリモートから接続できるかを確認します。 DockerホストOSとは別のLinuxサーバーからコンテナのMySQLサーバーにリモート接続してみます。なお、接続元LinuxサーバーにはMySQLのクライアント(mysql-community-client)をあらかじめインストールしておきます。

以下のコマンドを、接続元Linuxサーバー上で実行します。

 $ mysql -h {DockerホストOSのDNS名またはIPアドレス} -P 13306 -u testuser –p
 Enter password:{Dockerfile内で指定したパスワード: testuser123を入力}

接続が成功しましたら、次のように" mysql>" プロンプトが表示されます。

接続できましたね!

Ⅷ. 最後に…

今回作成したDockerfileを含む各種設定ファイルは基本的な設定のみを記述しており、実際の運用環境やセキュリティについて十分な考慮、検討した設定にはなっていません。あくまでも参考情報としてご参照ください。 また、Dockerの大きなメリットであるポータル化(作成したDockerイメージを別の環境で実行する手順)については、プライベート リポジトリを用意して試したいと考えていますので、その方法を確認できましたら、またクラウドアカデミーで紹介したいと思います。

Ⅸ. 参考情報

Using Supervisor with Docker
Dockerizing an SSH daemon service
Supervisor - pidproxy Program
jdeathe / centos-ssh
elcolio / centos-sshd
kawanamiyuu / Docker-centos-supervisord
各種ミドルウェアをSupervisorで管理する
DockerでMySQLを自動起動する
Dockerでsshdがバックグラウンドで起動しない場合の対策

※ご利用中のクラウドサービスによっては、利用できない場合があります。

この記事を書いた人 GMOクラウド 縞子 GMOクラウド株式会社 企画開発部 開発グループ所属。2014 年に同社へ入社し、主に SaaS開発に携わる。これまで使用して来た言語は C/C++、PHP、Java、JavaScript。猫派ですが、肉球のある生物はみんな好きです。 GMOクラウド 縞子の記事一覧
本コラム5、GMOクラウド株式会社の特設サイトに掲載されている「GMOクラウドアカデミー ~あなたの興味が知識に変わる」より転載したものです。GMOクラウドアカデミーは、クラウド・ホスティングの「悩み」「問題」「課題」の解決を目的に、現場の声を集約した「生きた」コンテンツを提供します。