takaya030の備忘録

PHP、Laravel、Docker などの話がメインです

Windows の docker-machine で Google Cloud Platform に Docker ホストマシンを立てる

Google App Engine で課金設定をした際、2ヶ月有効の 300 USドルのクーポンがついてきたので、試しに GCP に Docker のホストマシンを立ててみました。

検証環境

Docker Toolbox 1.10.3 と同じ構成です。

  • VirtualBox 5.0.16
  • docker 1.10.3
  • docker-machine 0.6.0

Google Cloud SDK のインストール

下記のリンクから Windows 用の Goolge Cloud SDK をインストールします。
Google Cloud SDK - Cloud SDK - Google Cloud Platform

gcloud にログイン

Google Cloud SDK をインストールするとスタートメニューかデスクトップに "Google Cloud SDK Shell" のショートカットが作られるので、それをダブルクリックしてシェルを起動し、以下のコマンドを入力してログインします。

$ gcloud auth login

Docker ホストマシンの作成

$ docker-machine create -d google --google-project <project-id> --google-zone asia-east1-a --google-machine-type "g1-small" gcetest
Running pre-create checks...
(gcetest) Check that the project exists
(gcetest) Check if the instance already exists
Creating machine...
(gcetest) Generating SSH Key
(gcetest) Creating host...
(gcetest) Opening firewall ports
(gcetest) Creating instance
(gcetest) Waiting for Instance
(gcetest) Uploading SSH Key
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with ubuntu(systemd)...
Installing Docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: C:\Git\bin\docker-machine.exe env gcetest

インスタンスの確認

$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
dev       -        virtualbox   Stopped                                       Unknown
gcetest   -        google       Running   tcp://104.199.xxx.xxx:2376          v1.10.3

環境変数の設定

msysgit のシェルの場合

$ eval "$(docker-machine env --shell powereshell gcetest)"

ホストマシンへログイン

$ docker-machine ssh gcetest
Welcome to Ubuntu 15.10 (GNU/Linux 4.2.0-18-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud


*** System restart required ***
Last login: Mon Mar 21 12:56:22 2016 from xxx.xxx.xxx.xxx

Windows の Docker 環境を Docker Toolbox を使わずバージョンアップする

以前 Windows 上に構築した Docker 環境Docker Toolbox (Docker インストーラ) を使わずに最新バージョンアップしたときの手順メモ。

バージョンアップ前の Docker 環境

  • VirtualBox 4.3.28
  • docker 1.8.1
  • docker-machine 0.4.1

最新の Docker 環境

2016年3月19日現在の最新バージョンです。

  • VirtualBox 5.0.16
  • docker 1.10.3
  • docker-machine 0.6.0

イメージ、コンテナのバックアップ

docker-machine v0.4.1 で作成したホストマシンは v0.6.0 では動作しないため、新しい環境でも使用したいイメージやコンテナはあらかじめバックアップしておきます。
イメージのエクスポート

$ docker save centos > centos.image.tar

コンテナのエクスポート

$ docker export busybox_1 > busybox_1.container.tar

VirtualBox のバージョンアップ

以下のサイトから最新の WindowsVirtualBox をダウンロードしてインストールします。
上書きインストールで問題ありません。

docker-machine v0.5.2 のインストール

docker-machine v0.5.2 の各種仮想マシンドライバが必要になるため、v0.6.0 の前にインストールします。

$ curl -L https://github.com/docker/machine/releases/download/v0.5.2/docker-machine_windows-amd64.zip > machine.zip
$ unzip machine.zip
$ rm machine.zip
$ mv -f docker-machine* /bin

Dokcer 関連コマンドのバージョンアップ

msysgit のシェル上で以下のコマンドを入力します。

$ curl -L https://get.docker.com/builds/Windows/x86_64/docker-1.10.3.exe > /bin/docker
$ curl -L https://github.com/docker/machine/releases/download/v0.6.0/docker-machine-Windows-x86_64.exe > /bin/docker-machine

動作確認

$ docker -v
Docker version 1.10.3, build 20f81dd

$ docker-machine -v
docker-machine version 0.6.0, build e27fb87

ホストマシンの作成

docker-machine v0.6.0 でホストマシンを作成します。

$ docker-machine create --driver virtualbox --virtualbox-memory 2048 --virtualbox-disk-size 40000 dev2

ホストマシンの確認

$ docker-macine ls
NAME   ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKR    ERRORS
dev    -        virtualbox   Stopped                                       Unknwn
dev2   *        virtualbox   Running   tcp://192.168.99.100:2376           v1.10.3

docker-machine ssh でログイン

$ docker-machine ssh dev2
                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 1.10.3, build master : 625117e - Thu Mar 10 22:09:02 UTC 2016
Docker version 1.10.3, build 20f81dd

イメージ、コンテナのインポート

新しく作成したホストマシンにイメージ、コンテナをインポートします。
イメージのインポート

$ docker load < centos.image.tar

コンテナのインポート

$ cat busybox_1.container.tar | docker import - busybox_1:latest

Google App Engine for PHP で cURL を使う

Google App Engine for PHP (以下、GAE)で cURL を使えるように設定したときのメモ

GAE で cURL を有効化する設定

2016年3月現在、GAE はデフォルト状態で cURL を使用することはできません。
下記の通り app.yamlphp.ini を変更することで通常の cURL とサブセット版である cURL_lite が使用可能となります。

cURL_lite
  • php.ini に以下の設定を追加
google_app_engine.enable_curl_lite = "1"
  • app.yaml の runtime を php55 に変更
runtime: php55

cURL_lite はいくつかの機能が未実装なため、ローカルサーバーでは正常に動作していても、デプロイした先でエラーが発生することがあります。
自分の場合、以下のようなエラーが発生しました。

exception 'google\appengine\runtime\CurlLiteOptionNotSupportedException' with message 'Option 10065 is not supported by this curl implementation.' in /base/data/home/runtimes/php/sdk/google/appengine/runtime/CurlLite.php:487
cURL
  • php.ini に以下の設定を追加
extension = "curl.so"

cURL_lite の設定 (google_app_engine.enable_curl_lite) が残っていると正常動作しないので 削除します。

  • app.yaml の runtime を php55 に変更
runtime: php55
  • GAE の課金設定を有効にする

Google App Engine の設定画面で課金を有効にします。
課金を有効にしても無料枠内の使用であれば課金されることはありません。

cURL の設定を使用することで cURL が使用可能となりました。

Docker で Google App Engine for PHP の開発環境を作る

前回 Docker 上の CentOS に Python 2.7 をインストールしましたが、そのイメージをつかって GAE for PHP の開発環境を作ってみます。
ポイントは以下の二点です。

  • PHP の Memcache や Memcached 拡張がインストールされていると SDK のアプリがローカルで動作しないため、PHP はソースビルドでインストールする。
  • SDKツール類を Python 2.7 で動作させるようにスクリプトを変更する。

Dockerfile

#
# 2016/01/30
#   CentOS 6.7 + epel,remi,rpmforge
#	Python 2.7.11
#	PHP 5.5.31
#   GAE SDK 1.9.31

FROM takaya030/python27
MAINTAINER takaya030

# libraries
RUN yum install -y libxml2-devel libxslt-devel libcurl-devel libpng-devel libicu-devel && \
    yum clean all

RUN yum install --enablerepo=epel -y libmcrypt libmcrypt-devel && \
    yum clean all

# php 5.5
RUN curl -Lso php-5.5.31.tar.gz http://jp2.php.net/get/php-5.5.31.tar.gz/from/this/mirror && \
	tar xvzf php-5.5.31.tar.gz && \
	cd php-5.5.31 && \
	./configure --prefix=/usr/local/php-5.5.31/ \
    --enable-bcmath \
    --enable-calendar \
    --enable-ftp \
    --enable-mbstring \
    --enable-opcache \
    --enable-phar \
    --enable-soap \
    --enable-sockets \
    --enable-zip \
    --disable-fileinfo \
    --disable-flatfile \
    --disable-posix \
    --with-curl \
    --with-gd \
    --with-openssl \
    --without-sqlite3 \
    --without-pdo-sqlite \
    --without-imap \
    --without-kerberos \
    --without-imap-ssl \
    --without-interbase \
    --without-ldap \
    --without-mssql \
    --without-oci8 \
    --without-pgsql \
    --without-pear \
    --with-pdo-mysql=mysqlnd \
    --with-mysqli=mysqlnd \
    --with-mysql=mysqlnd \
	--with-config-file-path=/etc && \
	make && make install && \
	cp ./php.ini-production /etc/php.ini && \
	cd .. && \
	rm -r php-5.5.31 php-5.5.31.tar.gz

# modify /etc/php.ini
RUN sed -i -e "s/;date.timezone *=.*$/date.timezone = Asia\/Tokyo/" /etc/php.ini

# symbolic links
RUN ln -s /usr/local/php-5.5.31/bin/php /usr/local/bin/php && \
	ln -s /usr/local/php-5.5.31/bin/php-cgi /usr/local/bin/php-cgi && \
	ln -s /usr/local/php-5.5.31/bin/php-config /usr/local/bin/php-config && \
	ln -s /usr/local/php-5.5.31/bin/phpize /usr/local/bin/phpize

# Google App Engine SDK
RUN curl -O  https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.31.zip && \
	unzip google_appengine_1.9.31.zip -d /usr/local/ && \
	rm google_appengine_1.9.31.zip

# modify gae scripts
RUN sed -i -e "s/\/usr\/bin\/env *python/\/usr\/bin\/env python2.7/" /usr/local/google_appengine/*.py

# composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# phpunit
RUN curl -L https://phar.phpunit.de/phpunit-old.phar > /usr/local/bin/phpunit && \
	chmod +x /usr/local/bin/phpunit

# git
RUN yum install -y curl-devel expat-devel gettext-devel  openssl-devel zlib-devel perl-ExtUtils-MakeMaker && \
    yum clean all && \
	curl -O https://www.kernel.org/pub/software/scm/git/git-1.9.5.tar.gz && \
	tar xvzf git-1.9.5.tar.gz && \
	cd git-1.9.5 && \
	make configure && \
	./configure --prefix=/usr/local && \
	make all && \
	make install && \
	cd .. && \
	rm -r git-1.9.5 git-1.9.5.tar.gz

EXPOSE 22 8080 8000

CMD ["/usr/sbin/sshd","-D"]

イメージのビルド

docker@dev:~$ docker build -t takaya030/gaeweb

イメージの確認

docker@dev:~$ docker images
REPOSITORY                            TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
takaya030/gaeweb                      latest              1a012686df3d        28 hours ago        1.004 GB
takaya030/python27                    latest              b63358cbd426        28 hours ago        693.3 MB
centos                                6                   a005304e4e74        7 months ago        203.1 MB
busybox                               latest              8c2e06607696        9 months ago        2.433 MB

動作確認

コンテナの起動

docker@dev:~$ docker run -d -p 2022:22 -p 8080:8080 -p 8000:8000 --name gaeweb -h gaeweb takaya030/gaeweb

コンテナへのログイン

$ ssh -p 2022 gae@192.168.99.100

ホームディレクトリに helloworld ディレクトリを作成して、そこに下記の 2 ファイルを作る
helloworld.php

<?php
    phpinfo();

app.yaml

application: helloworld
version: 1
runtime: php55
api_version: 1

handlers:
- url: /.*
  script: helloworld.php

開発用サーバーの起動

[gae@gaeweb ~]$ /usr/local/google_appengine/dev_appserver.py --php_executable_path=/usr/local/bin/php-cgi --host=0.0.0.0 --admin_host=0.0.0.0 helloworld/

Web ブラウザで http://192.168.99.100:8080 にアクセスして以下のように表示されれば成功です。

変更履歴

  • (2016/02/05) Dockerfile の記述変更
  • (2016/02/05) Dockerfile に git のインストールを追加

Docker で CentOS 6 + Python 2.7 の環境を作る

CentOS6 にはデフォルトで Python 2.6 がインストールされていますが、Python 2.7 が必要になったためインストールしたときのメモ。
一部の OS コマンドが Python 2.6 で書かれており、上書きインストールするとそれらのコマンドが使えなくなる恐れがあるため、ソースからビルドして別ディレクトリ (/opt/local) にインストールする。

Dockerfile

#
# 2016/01/23
#   CentOS 6.7 + epel,remi,rpmforge
#	Python 2.7
#

FROM centos:6
MAINTAINER takaya030

# update yum
RUN yum update -y && \
    yum clean all

# epel repo
RUN yum install -y epel-release && \
    yum clean all
RUN sed -i -e "s/enabled *= *1/enabled=0/g" /etc/yum.repos.d/epel.repo

# remi repo
RUN yum install -y http://rpms.famillecollet.com/enterprise/remi-release-6.rpm && \
    yum clean all
RUN sed -i -e "s/enabled *= *1/enabled=0/g" /etc/yum.repos.d/remi.repo

# rpmforge repo
RUN yum install -y http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm && \
    yum clean all
RUN sed -i -e "s/enabled *= *1/enabled=0/g" /etc/yum.repos.d/rpmforge.repo

# gcc, make, sshd, scp, sudo, unzip, tar, which
RUN yum install -y gcc make openssh-server openssh-clients sudo tar unzip which && \
    yum clean all

# libraries
RUN yum install -y bzip2-devel zlib-devel openssl-devel sqlite-devel ncurses-devel readline-devel tk-devel && \
    yum clean all

# python
RUN curl -O https://www.python.org/ftp/python/2.7.11/Python-2.7.11.tgz && \
	tar xvzf Python-2.7.11.tgz && \
	cd Python-2.7.11 && \
	./configure --prefix=/opt/local && \
	make && make altinstall && \
	cd .. && \
	rm -r Python-2.7.11 Python-2.7.11.tgz

# pip, easy_install
RUN curl -kL https://bootstrap.pypa.io/get-pip.py | /opt/local/bin/python2.7 && \
	/opt/local/bin/pip2.7 install distribute

# initialize for ssh
RUN sed -i '/pam_loginuid\.so/s/required/optional/' /etc/pam.d/sshd
RUN /sbin/service sshd start
RUN /sbin/service sshd stop

# create login user
RUN useradd -d /home/gae -m -s /bin/bash gae
RUN echo gae:****gae | chpasswd
RUN echo 'gae ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

# timezone
RUN cp -p /usr/share/zoneinfo/Japan /etc/localtime

# symbolic links
RUN ln -s /opt/local/bin/python2.7 /usr/bin/python2.7

EXPOSE 22

CMD ["/usr/sbin/sshd","-D"]

イメージのビルド

docker@dev:~$ docker build -t takaya030/python27

イメージの確認

docker@dev:~$ docker images
REPOSITORY                            TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
takaya030/python27                    latest              a8bce34c067e        3 days ago          693.3 MB
centos                                6                   a005304e4e74        7 months ago        203.1 MB
busybox                               latest              8c2e06607696        9 months ago        2.433 MB

動作確認

コンテナの起動

docker@dev:~$ docker run -d -p 2022:22 --name python27 takaya030/python27

コンテナへのログイン

$ ssh -p 2022 gae@192.168.99.100

python のバージョン確認

[gae@e17d37b01407 ~]$ python -V
Python 2.6.6
[gae@e17d37b01407 ~]$ /opt/local/bin/python2.7 -V
Python 2.7.11

Google Apps Script では XMLHttpRequest が使えない

Google Apps Script から他サイトに対して HTTP GET リクエストするため XMLHttpRequest を使おうとしたら、下記エラーが発生しました。

ReferenceError: "XMLHttpRequest" is not defined.

Google Apps Script では代わりに UrlFetchApp.fetch を使うようです。
以下のようなコードで無事 GET リクエストが実行できました。

function httpGet(theUrl) {
  var resp = UrlFetchApp.fetch(theUrl);
  var data = JSON.parse(resp.getContentText());
  return data;
}

Docker Hub の MySQL 5.6 公式イメージの設定を変更する

Docker Hub の MySQL 5.6 公式イメージの設定変更したときのメモ。
変更項目

  • timezone を Japan に変更
  • sql_mode の STRICT_TRANS_TABLES を無効化

デフォルトの my.cnf の内容

公式イメージをそのまま起動したときの /etc/mysql/my.cnf

#
# The MySQL Community Server configuration file.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

[client]
port		= 3306
socket		= /var/run/mysqld/mysqld.sock

[mysqld_safe]
pid-file	= /var/run/mysqld/mysqld.pid
socket		= /var/run/mysqld/mysqld.sock
nice		= 0

[mysqld]
user		= mysql
pid-file	= /var/run/mysqld/mysqld.pid
socket		= /var/run/mysqld/mysqld.sock
port		= 3306
basedir		= /usr
datadir		= /var/lib/mysql
tmpdir		= /tmp
lc-messages-dir	= /usr/share/mysql
explicit_defaults_for_timestamp

# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
#bind-address	= 127.0.0.1

#log-error	= /var/log/mysql/error.log

# Recommended in standard MySQL setup
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

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

# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#
!includedir /etc/mysql/conf.d/

timezone の変更

my.cnf を見ると timezone を指定している部分はありません。
その場合、OS の timezone と同じになるので、今回は Dockerfile で OS 側の timezone を Japan に変更することにします。

sql_mode の変更

my.cnf の最後で /etc/mysql/conf.d/ にある cnf ファイルをインクルードするようになっているので、試しに以下のような cnf ファイルを追加してみましたが STRICT_TRANS_TABLES は有効のままでした。

/etc/mysql/conf.d/ext_my.cnf

[mysqld]

sql_mode=NO_ENGINE_SUBSTITUTION

my.cnf の sql_mode の項目を直接書き換えることで対応しました。

mysql の Dockerfile

以下が変更項目に対応した Dockerfile になります。

FROM mysql:5.6
MAINTAINER takaya030

# timezone
RUN cp -p /usr/share/zoneinfo/Japan /etc/localtime

# modify my.cnf
RUN sed -i -e "s/^sql_mode=.*$/sql_mode=NO_ENGINE_SUBSTITUTION/" /etc/mysql/my.cnf