読者です 読者をやめる 読者になる 読者になる

takaya030の備忘録

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

Docker 版 Rails5 で Hello world

Docker で構築した Ruby on Rails5 の環境で "Hello world!" を表示してみる

コントローラ作成

Docker ホストOS 上で下記コマンドで作成

$ docker-compose run --rm web rails generate controller hello
      create  app/controllers/hello_controller.rb
      invoke  erb
      create    app/views/hello
      invoke  test_unit
      create    test/controllers/hello_controller_test.rb
      invoke  helper
      create    app/helpers/hello_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/hello.coffee
      invoke    scss
      create      app/assets/stylesheets/hello.scss

index のアクション作成

app/controllers/hello_controller.rb

class HelloController < ApplicationController
	def index
		render :text => "Hello, world!"
	end
end

ルーティング

config/routes.rb

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

  resources :hello do
	  root 'hello#index'
  end
end

動作確認

web ブラウザで http://192.168.99.100:3000/hello を開いて "Hello, world!" と表示されれば成功です

Docker で Rails5 + MySQL の開発環境を構築する

前回 Docker で Ruby on Rails5 のサーバーを単体で起動させましたが、今回は MySQL 連携させてみました。

設定ファイルおよび操作手順について

こちらのサイトに記載されている手順とほぼ同じです。
qiita.com


以下、内容を変更した設定ファイルです。

Dockerfile

#
# ruby 2.3 + rails 5.0.0.1
#
# 2016-10-10
#

FROM ruby:2.3
MAINTAINER takaya030

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp

Gemfile

source "https://rubygems.org"
gem 'rails', '5.0.0.1'

docker-compose.yml

version: '2'
services:
  db:
    image: mysql:5.6
    container_name: rr5_db
    environment:
      MYSQL_ROOT_PASSWORD: root
  web:
    build: .
    image: rr5_web
    container_name: rr5_web
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

Docker で Ruby on Rails5 の開発環境を構築する

Docker で Ruby on Rails5 の開発環境のベースイメージを作成したときの手順メモ

設定ファイルおよび操作手順について

こちらのサイトに記載されている手順で rails5 もセットアップできました。
qiita.com


以下、内容を変更した設定ファイルです。

Dockerfile

#
# ruby 2.3 + rails 5.0.0.1
#
# 2016-10-05
#

FROM ruby:2.3
MAINTAINER takaya030

ENV APP_ROOT /usr/src/myapp

WORKDIR $APP_ROOT

RUN apt-get update && \
    apt-get install -y nodejs \
                       mysql-client \
                       postgresql-client \
                       sqlite3 \
                       --no-install-recommends && \
    rm -rf /var/lib/apt/lists/*

COPY Gemfile $APP_ROOT
COPY Gemfile.lock $APP_ROOT

RUN \
  echo 'gem: --no-document' >> ~/.gemrc && \
  cp ~/.gemrc /etc/gemrc && \
  chmod uog+r /etc/gemrc && \
  bundle config --global build.nokogiri --use-system-libraries && \
  bundle config --global jobs 4 && \
  bundle install && \
  rm -rf ~/.gem

# bundle install でカレントディレクトリに rails5 をインストールした後、
# 以下をコメントアウトして再度 docker build を実行する

#COPY . $APP_ROOT
#
#EXPOSE  3000
#CMD ["rails", "server", "-b", "0.0.0.0"]

Gemfile

source "https://rubygems.org"
gem 'rails', '5.0.0.1'

Docker で nginx + php-fpm + Laravel5.3 の開発環境を作る

DockerLaravel 5.3 の開発環境を構築した際の手順メモ

検証環境

以下の環境で検証しました
VirtualBoxDocker はインストール済みの前提で話を進めます

Windows10 Home Edition
VirtualBox 5.0.16
docker 1.10.3
docker-machine 0.6.0
docker-compose 1.6.2

準備作業

Windowsのエディタで php のコードを編集した結果を直ちに反映させるため、Windows のフォルダを VirtualBox にマウントし、そこに Laravel をインストールします
マウント手順は下記の記事を参照してください
takaya030.hatenablog.com

C:\workspace をマウントした後、C:\workspace\laravel53 フォルダを作成します

Docker イメージの作成のための各種ファイル

ファイル構成

l53
│  docker-compose.yml
│
├─nginx
│      Dockerfile
│      server.conf
│
└─php7
        bashrc
        Dockerfile
        index.php
        mysupervisord.conf

各ファイルの内容

l53/docker-compose.yml
nginx: 
  build: ./nginx
  ports: 
    - "80:80"
    - "9000:9000"
  links: 
    - php7

php7: 
  build: ./php7
  hostname: laraweb
  ports: 
    - "2022:22"
  volumes: 
    - /workspace/laravel53:/webapp
l53/nginx/Dockerfile
FROM nginx:latest
MAINTAINER takaya030

ADD server.conf /etc/nginx/conf.d/server.conf
l53/nginx/server.conf
server {
    listen 80 default;
    server_name _;
    root /webapp/public;
    index index.php index.html index.htm;
    charset utf-8;

    access_log off;
    error_log off;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ ^/index.php$ {
        fastcgi_pass l53_php7_1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

server {
    listen 9000 default;
    server_name _;
    root /var/www/html;
    index index.php index.html index.htm;
    charset utf-8;

    access_log off;
    error_log off;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ ^/index.php$ {
        fastcgi_pass l53_php7_1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}
l53/php7/bashrc
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# git prompt
if [ -f $HOME/.git-completion.bash ]; then
	source $HOME/.git-completion.bash
fi
if [ -f $HOME/.git-prompt.sh ]; then
	source $HOME/.git-prompt.sh
	export PS1='\[\033]0;$TITLEPREFIX:${PWD//[^[:ascii:]]/?}\007\]\n\[\033[32m\]\u@\h\[\033[35m\]: \[\033[33m\]\w\[\033[36m\]`__git_ps1`\[\033[0m\]\n$ '
fi

# User specific aliases and functions
alias ls='ls -F --color=auto'
alias ll='ls -la --color=auto'
alias la='ls -a --color=auto'
alias sl='ls -F --color=auto'
alias glog='git log --oneline --decorate --graph --branches --tags --remotes'
l53/php7/Dockerfile
#
# php7-fpm
#
# 2016-09-18
#   PHP 7.0.11

FROM php:7-fpm
MAINTAINER takaya030

# php
RUN apt-get update \
  && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng12-dev libmcrypt-dev \
  && docker-php-ext-install pdo_mysql mysqli mbstring gd iconv mcrypt \
  && apt-get clean

# sshd, scp, sudo, unzip, tar
RUN apt-get install -y openssh-server openssh-client sudo tar unzip supervisor && \
    apt-get clean

# gcc (for building git)
RUN apt-get install -y build-essential libssl-dev gettext curl expat openssl zlibc libcurl4-openssl-dev \
	&& apt-get clean

# git
RUN curl -O https://www.kernel.org/pub/software/scm/git/git-2.9.3.tar.gz && \
	tar xvzf git-2.9.3.tar.gz && \
	cd git-2.9.3 && \
	make configure && \
	./configure --prefix=/usr/local --with-curl --with-expat && \
	make all && \
	make install && \
	cd .. && \
	rm -r git-2.9.3 git-2.9.3.tar.gz

# for git prompt
RUN curl -L https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash > /etc/skel/.git-completion.bash && \
	curl -L https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh > /etc/skel/.git-prompt.sh 
ADD ./bashrc /etc/skel/.bashrc

# 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.phar > /usr/local/bin/phpunit && \
	chmod +x /usr/local/bin/phpunit

# node, npm, gulp
RUN apt-get install -y nodejs npm && \
	npm cache clean && \
	npm install n -g && \
	n stable && \
	apt-get purge -y nodejs npm && \
	apt-get clean && \
	/usr/local/bin/npm install --global gulp-cli

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

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

# timezone
RUN cp -p /usr/share/zoneinfo/Japan /etc/localtime && \
	echo "date.timezone = Asia/Tokyo" > /usr/local/etc/php/conf.d/myphp.ini

# supervisor
COPY ./mysupervisord.conf /etc/supervisor/conf.d/

COPY index.php /var/www/html/

EXPOSE 22 9000

CMD ["/usr/bin/supervisord"]
l53/php7/index.php
<?php
	phpinfo();
l53/php7/mysupervisord.conf
[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor            ; ('AUTO' child log dir, default $TEMP)
nodaemon=true               ; (start in foreground if true;default false)

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

[program:php-fpm]
command=/usr/local/sbin/php-fpm

Docker イメージの作成

Docker ホストに上記のファイルを配置した後、以下のコマンドでイメージを作成します

$ cd l53
$ docker-compose build

コンテナの起動

$ cd l53
$ docker-compose up -d

ssh でログイン

$ ssh -p 2022 laravel@192.168.99.100

※パスワードは "****laravel"

Laravel 5.3 のインストール

ssh でログインしたコンテナ上で以下のコマンドを実行する

$ cd /webapp
$ composer create-project "laravel/laravel" --prefer-dist .

動作確認

WEBブラウザで http://192.168.99.100 にアクセスすると Laravel の welcome ページが表示されます
f:id:takaya030:20160920230537p:plain

また http://192.168.99.100:9000 にアクセスすると phpinfo が表示されます
f:id:takaya030:20160920230600p:plain

更新履歴

  • (2016-09-27) l53/php7/Dockerfilenode, npm, gulp のインストールを追加

oriceon/oauth-5-laravel を使った Google API の OAuth 認証

前回手動で Google API の Access Token と Refresh Token を取得したので、それを使って oriceon/oauth-5-laravel で OAuth 認証を検証したときのメモ

検証環境

$ php --version
PHP 5.5.19 (cli) (built: Nov 12 2014 12:35:44)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies

$ php artisan --version
Laravel Framework version 5.2.45

oriceon/oauth-5-laravel のインストール

composer.json に下記を追加

    "require": {
	"oriceon/oauth-5-laravel": "dev-master"
    },

composer update を実行

$ composer update

OAuth クライアント ID、Refresh Token の取得

前回の記事を参考に予め取得する
Google API の Access Token を手動で取得する - takaya030の備忘録

サンプルコード

.env に下記を追加

# oauth
GOOGLE_CLIENT_ID=Your-Clinet-Id
GOOGLE_CLIENT_SECRET=Your-Clinet-Secret
GOOGLE_ACCESS_TOKEN=Your-Access-Token
GOOGLE_REFRESH_TOKEN=Your-Refresh-Token

config/oauth-5-laravel.php

<?php

return [

	/*
	|--------------------------------------------------------------------------
	| oAuth Config
	|--------------------------------------------------------------------------
	*/

	/**
	 * Storage
	 */
	'storage' => '\\OAuth\\Common\\Storage\\Session',

	/**
	 * Consumers
	 */
	'consumers' => [

		'Google' => [
			'client_id'     => env('GOOGLE_CLIENT_ID'),
			'client_secret' => env('GOOGLE_CLIENT_SECRET'),
			'scope'         => ['https://mail.google.com/'],
		],

	]

];

app/Http/Controllers/GmailController.php

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

use OAuth\OAuth2\Token\StdOAuth2Token;

class GmailController extends Controller
{
	public function loginOAuth(Request $request)
	{
		// get data from request
		$access_token = env("GOOGLE_ACCESS_TOKEN");
		$refresh_token = env("GOOGLE_REFRESH_TOKEN");

		// get google service
		$googleService = \OAuth::consumer('Google');

		if( !is_null($access_token) && !is_null($refresh_token) )
		{
			$dummy_token = new StdOAuth2Token( $access_token, $refresh_token );
			$token = $googleService->refreshAccessToken($dummy_token);

			$params = [
				'maxResults' => '3',
				'q' => 'is:inbox',
			];

			// Send a request with it
			$result = json_decode($googleService->request('https://www.googleapis.com/gmail/v1/users/me/messages?'.http_build_query($params),'GET'), true);

			dd($result);
		}
		else
		{
			dd('No Access Token or Refresh Token.');
		}
	}

}

app/Http/routes.php

<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

Route::get('gmail', 'GmailController@loginOAuth' );

autoload 更新

$ php artisan optimize

動作確認

テストサーバー起動

$ php artisan serve

WEBブラウザで http://localhost:8000/gmail を開いて下の画像のように表示されれば成功です
f:id:takaya030:20160904174005p:plain

Google API の Access Token を手動で取得する

はじめに

Google App Engine (GAE) を運用する場合通常サービスアカウントを使用しますが、サービスアカウントから個人の Gmail などにアクセスする際には別途 OAuth 認証を行って Access Token、Refresh Token を取得する必要があるため、その手順のメモ

OAuth クライアント ID の取得

  1. 認証を取得したい Google アカウントにログイン
  2. Google Developers Console に移動
  3. API Manager でプロジェクトを作成 or 選択、使用する API を有効にする
  4. API Manager の"認証情報"で、"認証情報を作成" → "OAuth クライアント ID" → "その他" の順で選択して作成
  5. 作成した OAuth クライアント ID を "JSONをダウンロード" してクライアント ID、クライアントシークレット、リダイレクトURIを確認する

Authorization Code 取得

Webブラウザで下記 URL にアクセスする

https://accounts.google.com/o/oauth2/auth?client_id=12345-xxxxx.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://mail.google.com/&response_type=code&approval_prompt=force&access_type=offline

client_id は上で取得したもの
scope は例として Gmail API のものを指定している。他の API を使う場合はに適宜変更すること
ブラウザに認証コードが表示されるのでメモする

Access Token 取得

上で取得した Authorization Code を使って Access Token を取得する (code で指定)

curl -k -d client_id=12345-xxxxx.apps.googleusercontent.com -d client_secret=xxxxx -d redirect_uri=urn:ietf:wg:oauth:2.0:oob -d grant_type=authorization_code -d code=xxxxx https://accounts.google.com/o/oauth2/token

下記JSONがレスポンスで返されるので access_token、refresh_token をメモする

{
  "access_token" : "xxxxx...",
  "token_type" : "Bearer",
  "expires_in" : 3600,
  "refresh_token" : "xxxxx..."
}

oriceon/oauth-5-laravel を使った Pocket API の OAuth 認証

oriceon/oauth-5-laravel で Pocket API の OAuth 認証を検証したときのメモ

検証環境

$ php --version
PHP 5.5.19 (cli) (built: Nov 12 2014 12:35:44)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies

$ php artisan --version
Laravel Framework version 5.2.43

oriceon/oauth-5-laravel のインストール

composer.json に下記を追加

    "require": {
	"oriceon/oauth-5-laravel": "dev-master"
    }

composer update を実行

$ composer update

consumer key の取得

下記リンク先で予め consumer key を取得します
Pocket: Developer API

サンプルコード

.env に下記を追加

# oauth
POCKET_CLIENT_ID=Your-Consumer-Key

config/oauth-5-laravel.php

<?php

return [

	/*
	|--------------------------------------------------------------------------
	| oAuth Config
	|--------------------------------------------------------------------------
	*/

	/**
	 * Storage
	 */
	'storage' => '\\OAuth\\Common\\Storage\\Session',

	/**
	 * Consumers
	 */
	'consumers' => [

		'Pocket' => [
			'client_id'     => env('POCKET_CLIENT_ID'),
			'client_secret' => null,			// Pocket API doesn't have a secret key.
			'scope'         => [],
		],

	]

];

app/Http/Controllers/PocketController.php

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class PocketController extends Controller
{
	public function loginOAuth(Request $request)
	{
		// get pocket service
		$pocketService = \OAuth::consumer('Pocket',url('/loginresult'));

		// get request token
		$reqToken = $pocketService->requestRequestToken();
		$request->session()->put( 'code', $reqToken );

		// get pocketService authorization
		$url = $pocketService->getAuthorizationUri([ 'request_token' => $reqToken ]);

		// return to pocket login url
		return redirect((string)$url);
	}

	public function loginResult(Request $request)
	{
		// get data from request
		$code = $request->session()->get('code');

		// get pocket service
		$pocketService = \OAuth::consumer('Pocket',url('/loginresult'));

		// if code is provided get user data and sign in
		if ( ! is_null($code))
		{
			// This was a callback request from pocket, get the token
			$token = $pocketService->requestAccessToken($code);

			$params = [
				'consumer_key'	=> env('POCKET_CLIENT_ID'),
				'access_token'	=> $token->getAccessToken(),
				'sort' => 'newest',
				'count' => '1',
			];

			// get a post (test)
			$json_result = $pocketService->request('https://getpocket.com/v3/get', 'POST', json_encode($params), [ 'Content-Type' => 'application/json' ]);
			$result = json_decode( $json_result );

			dd($result);
		}
		else
		{
			dd('code is null.');
		}
	}
}

app/Http/routes.php

<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

Route::get('login', 'PocketController@loginOAuth' );
Route::get('loginresult', 'PocketController@loginResult' );

autoload 更新

$ php artisan optimize

動作確認

テストサーバー起動

$ php artisan serve

WEBブラウザで http://localhost:8000/login を開いて下の画像のように表示されれば成功です
f:id:takaya030:20160830232658p:plain