TECH
中津川 篤司

ついに公開されたAPIをPHPから利用する(バックアップ情報を取得する)

CloudGarageのインスタンス操作などを自動化できるAPIがついに公開されました。これでインスタンスの立ち上げや停止を自動化できるようになります。 そこで今回はPHPを使ってAPI操作を行う方法を解説します。処理内容としては、インスタンスに設定されたバックアップ情報を取得します。 必要なソフトウェア、ライブラリ 今回必要なソフトウェア、ライブラリは以下の通りです。 PHP APIキーを取得する 続いてCloudGarageの管理画面にてAPIキーを取得します。管理画面の右上にあるメニューをクリックして、アカウント情報確認/変更を選択します。 一度パスワードを入力する必要があります。 そして一番下にあるAPI Key管理にてAPI Keyを発行します。私はすでに発行済みなので再発行になっていますが、最初はAPIキーがないはずです。Client ID(クライアントID)とClient Secret(クライアントシークレット)の二つで認証します。重要なキーなので漏洩したりしないよう注意してください。 設定ファイルを読み込む まず設定ファイルとなるJSONファイルを取得します。これは上記クライアントIDとクライアントシークレットが保存されたファイルです。 $config = json_decode(file_get_contents('../config.json'), true); トークンを取得する 次にAPIを利用するためのトークンを取得します。これはクライアントIDとクライアントシークレットを用いて、POST /tokens にアクセスします。file_get_contents関数を使ってPOST処理を行います。 $baseUrl = "https://api.cloudgarage.jp"; $token = getToken($baseUrl, $config); // トークンを取得する function getToken($baseUrl, $config) { $url = "$baseUrl/tokens"; $options = array ( 'http' => array ( 'method' => 'POST', 'header' => 'Content-type: application/json', 'content' => json_encode( array( 'client_id' => $config['clientId'], 'client_secret' => $config['clientSecret'] ) ) ) ); $contents = file_get_contents($url, false, stream_context_create($options)); return json_decode($contents, true)['token']['id']; } インスタンス一覧を取得する トークンを取得したら、それを使ってAPIにアクセスできます。まず、既存のインスタンス一覧を取得します。これは GET /servers にリクエストします。 function getInstances($baseUrl, $token) { $url = "$baseUrl/servers"; return get($url, $token, 'servers'); } function get($url, $token, $key) { $options = array ( 'http' => array ( 'header' => implode("\r\n", array( 'Content-type: application/json', "X-Auth-Token: $token" )) ) ); $contents = file_get_contents($url, false, stream_context_create($options)); return json_decode($contents, true)[$key]; } GET処理はこの後でも使うので関数化しておきます。 自動バックアップ情報を取得する インスタンスIDが分かったら、そのインスタンスの自動バックアップ情報を取得します。これは GET /servers/{id}/autoBackup で取得できます。 function getAutoBackupInfo($baseUrl, $token, $id) { $url = "$baseUrl/servers/$id/autoBackup"; return get($url, $token, 'autoBackup'); } 結果を出力すると次のようになります。 array(6) { ["resourceId"]=> string(36) "948...4fc" ["cycle"]=> string(1) "W" ["dayOfCycle"]=> string(6) "MONDAY" ["time"]=> string(8) "01:00:00" ["saveCount"]=> int(1) ["nextExecDatetime"]=> string(23) "2018/12/24 01:00:00.000" } PHPは豊富な関数が用意されているので、それらを組み合わせるだけで簡単に利用できます。特にWeb APIを扱う上でfile_get_contents関数は強力です。ぜひ使いこなしてください! APIリファレンスはCloudGarage API リファレンスにありますので、ぜひご覧ください。

TECH
中津川 篤司

ついに公開されたAPIをSwfitから利用する(SSH公開鍵を取得する)

CloudGarageのインスタンス操作などを自動化できるAPIがついに公開されました。これでインスタンスの立ち上げや停止を自動化できるようになります。 そこで今回はSwiftを使ってAPI操作を行う方法を解説します。処理内容としては、コントロールパネルで設定した公開鍵を取得します。 必要なソフトウェア、ライブラリ 今回必要なソフトウェア、ライブラリは以下の通りです。 Xcode Ruby(CocoaPods用) cocoapods-keys CocoaPods HydraAsync SwiftyJSON APIキーを取得する まずはCloudGarageの管理画面にてAPIキーを取得します。管理画面の右上にあるメニューをクリックして、アカウント情報確認/変更を選択します。 一度パスワードを入力する必要があります。 そして一番下にあるAPI Key管理にてAPI Keyを発行します。私はすでに発行済みなので再発行になっていますが、最初はAPIキーがないはずです。Client ID(クライアントID)とClient Secret(クライアントシークレット)の二つで認証します。重要なキーなので漏洩したりしないよう注意してください。 Xcodeで新しいプロジェクトを作成する 最初にXcodeでiOSプロジェクトを作成します。作成したら、一旦終了します。 Gemfileを作成する クライアントIDなどを隠すため、 cocoapods-keys をインストールします。以下の内容で Gemfile を作成します。 source 'https://rubygems.org' gem 'cocoapods-keys' そしてbundlerを実行します。 $ bundle Podfileを作成する 次にCocoaPodsで必要なライブラリをインストールします。 Podfile の内容は次の通りです。 {YOUR_PROJECT} は自分のプロジェクト名に置き換えてください。インストールするのはSwiftでasync/awaitを利用するHydraAsync、そしてJSONを扱いやすくするSwiftyJSONです。cocoapods-keysの設定も行っています。 # Uncomment the next line to define a global platform for your project # platform :ios, '9.0' target '{YOUR_PROJECT}' do # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! pod 'HydraAsync' pod 'SwiftyJSON' # Pods for ncmbPush target '{YOUR_PROJECT}Tests' do inherit! :search_paths # Pods for testing end target '{YOUR_PROJECT}UITests' do inherit! :search_paths # Pods for testing end end plugin 'cocoapods-keys', { :project => "{YOUR_PROJECT}", :keys => [ "clientId", "clientSecret" ]} これをインストールした状態で pod install を実行すると、clientIdとclientSecretの入力が求められます。先ほどCloudGarageのコントロールパネルで取得したものをそれぞれ指定してください。 $ pod install CocoaPods-Keys has detected a keys mismatch for your setup. What is the key for clientId > ylk...t1P Saved clientId to cloudgarage. What is the key for clientSecret > iIG...oUo Saved clientSecret to cloudgarage. Analyzing dependencies Fetching podspec for `Keys` from `Pods/CocoaPodsKeys` Downloading dependencies Using HydraAsync (1.2.1) Using Keys (1.0.1) Using SwiftyJSON (4.2.0) Generating Pods project Integrating client project Sending stats Pod installation complete! There are 3 dependencies from the Podfile and 3 total pods installed. Xcodeでの作業 .xcworkspace という拡張子のファイルが生成されているので、それを開きます。Xcodeで、新しいヘッダーファイルを作成します。名前は任意ですが BridgeHeader.h などとします。 内容は次の通りです。 CloudgarageKeys.h というファイル名はそれぞれ変わりますが、PodsプロジェクトのDevelopment Pods/Keysの中にあるヘッダーファイルが対象です。 #ifndef BridgeHeader_h #define BridgeHeader_h #import "Keys/CloudgarageKeys.h" #endif /* BridgeHeader_h */ そして作成したXcodeプロジェクトのBuild SettingsにあるObjective-C Bridging Headerにて作成した BridgeHeader.h ファイルを指定します。例えば cloudgarage/BridgeHeader.h といった具合です。 Swiftによる開発 では準備ができましたので実際にコードを書いてみます。まず全体像です。HydraAsyncを使って非同期処理をasync/await化しています。 let baseUrl = "https://api.cloudgarage.jp" async({ _ -> Int in // トークンを取得 let token:String = try await(self.getToken(baseUrl: baseUrl)) // 公開鍵一覧を取得 let keyPairs = try await(self.getKeyPairs(baseUrl: baseUrl, token: token)) as! JSON // 公開鍵の詳細情報を取得 let keyPair = try await(self.getKeyPair(baseUrl: baseUrl, token: token, id: keyPairs[0]["id"].int ?? 0)) // デバッグ出力 print(keyPair) return 0 }).then({stats in print(stats) }) .catch {error in print("Error") print(error) } トークンの取得 まずトークンの取得です。CloudgarageKeysを使ってキーを取得しています。そしてPOSTリクエストを行った後、token.idがあるのかを確認してトークンを返します。 func getToken(baseUrl: String) -> Promise<String> { return Promise<String>(in: .background, {resolve, reject, _ -> Void in let keys = CloudgarageKeys.init() let url = "\(baseUrl)/tokens" let request = NSMutableURLRequest(url: URL(string: url)!) request.httpMethod = "POST" request.addValue("application/json", forHTTPHeaderField: "Content-Type") let params:[String:Any] = [ "client_id": keys.clientId, "client_secret": keys.clientSecret ] request.httpBody = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted) do { let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in if error != nil { reject(error ?? NSError(domain: "Request error", code: 1)) } else { let json = try? JSON(data: data!) if let token = json?["token"]["id"].string { resolve(token) } return reject(NSError(domain: "Parse error", code: 1)) } } task.resume() } catch let error as NSError { reject(error) } }) } 公開鍵の一覧を取得 続いて公開鍵の一覧を取得します。get処理を関数化し、一覧を取得する処理自体短くしています。トークンを取得していますので、それを X-Auth-Token ヘッダーに適用して実行します。 func getKeyPairs(baseUrl: String, token: String) -> Promise<Any> { return Promise<Any>(in: .background, {resolve, reject, _ -> Void in let url = "\(baseUrl)/keypairs" self.get(url: url, token: token) .then {json in if json["keypairs"].array != nil { return resolve(json["keypairs"]) } else { return reject(NSError(domain: "Parse error on getKeyPairs \(json)", code: 1)) } } .catch{error in return reject(error) } }) } // GET処理を関数化 func get(url: String, token: String) -> Promise<JSON> { return Promise<JSON>(in: .background, {resolve, reject, _ -> Void in let request = NSMutableURLRequest(url: URL(string: url)!) request.httpMethod = "GET" request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.addValue(token, forHTTPHeaderField: "X-Auth-Token") let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in if error != nil { reject(error ?? NSError(domain: "Request error", code: 1)) } else { let json = try? JSON(data: data!) return resolve(json!) } } task.resume() }) } 公開鍵の詳細を取得 取得した公開鍵のID(数値)を使って公開鍵詳細を取得します。ここは先ほどのget処理を使って行います。 func getKeyPair(baseUrl: String, token: String, id: Int) -> Promise<Any> { return Promise<Any>(in: .background, {resolve, reject, _ -> Void in let url = "\(baseUrl)/keypairs/\(id)" self.get(url: url, token: token) .then {json in if json["keypair"].dictionary != nil { resolve(json["keypair"]) } else { return reject(NSError(domain: "Parse error on getKeyPair \(json)", code: 1)) } } .catch{error in reject(error) } }) } 結果として以下のような公開鍵情報が得られます。 { "keypair_created_time" : "2018\/09\/03 13:44:29.684", "publicKey" : "ssh-rsa AAA...F+w== nakatsugawa@macpro.local", "name" : "macpro", "id" : 1217 } SwiftはiOSやmacOSアプリの開発はもちろん、サーバサイドでも利用できる言語となっています。静的型付けながら、スクリプト言語のような書き方ができるのが特徴です。ぜひiOSアプリからCloudGarage Public APIを呼び出してみてください! APIリファレンスはCloudGarage API リファレンスにありますので、ぜひご覧ください。

TECH
中津川 篤司

ついに公開されたAPIをGoから利用する(契約情報を取得する)

CloudGarageのインスタンス操作などを自動化できるAPIがついに公開されました。これでインスタンスの立ち上げや停止を自動化できるようになります。 そこで今回はGoを使ってAPI操作を行う方法を解説します。契約情報を取得します。 必要なソフトウェア、ライブラリ 今回必要なソフトウェア、ライブラリは以下の通りです。 Go APIキーを取得する 続いてCloudGarageの管理画面にてAPIキーを取得します。管理画面の右上にあるメニューをクリックして、アカウント情報確認/変更を選択します。 一度パスワードを入力する必要があります。 そして一番下にあるAPI Key管理にてAPI Keyを発行します。私はすでに発行済みなので再発行になっていますが、最初はAPIキーがないはずです。Client ID(クライアントID)とClient Secret(クライアントシークレット)の二つで認証します。重要なキーなので漏洩したりしないよう注意してください。 設定ファイルを読み込む APIキーを記述したファイル(config.json)を読み込みます。GoではJSONを扱う際に、まずその構造に合わせて構造体を作っておく必要があります。この場合、Config という構造体になります。 type Config struct { ClientId string `json:"client_id"` ClientSecret string `json:"client_secret"` } そしてファイルを読み込みます。 // APIキーの取得 config, err := loadConfig() if err != nil { log.Fatal(err) } // 読み込む関数 func loadConfig() (Config, error) { // APIキーの取得 bytes, err := ioutil.ReadFile("./config.json") if err != nil { log.Fatal(err) } var config Config err = json.Unmarshal(bytes, &config) return config, err } トークンを取得する まずAPIを利用するためのトークンを取得する必要があります。コードは次のようになります。 POST /tokens リクエストして、その結果として得られるJSONの token.id の値がトークンになります。 今回の構造体は以下のようになります。 type Token struct { Value TokenValue `json:"token"` } type TokenValue struct { Id string `json:"id"` Expires string `json:"expires"` ClientId string `json:"client_id"` } そしてトークンを取得するコードです。 // トークンの取得 token, err := getToken(baseUrl, config) // トークンを取得する関数 func getToken(baseUrl string, config Config) (string, error) { url := baseUrl + "/tokens" params, err := json.Marshal(config) res, err := http.Post(url, "application/json", bytes.NewBuffer(params)) body, err := ioutil.ReadAll(res.Body) var token Token if err := json.Unmarshal(body, &token); err != nil { log.Fatal(err) } defer res.Body.Close() return token.Value.Id, err } CloudGarageのAPIでは {token: { id: ... }} といった具合にレスポンスのJSONがデータモデルのキーでラップされています。そのため Token と TokenValue のように一段階ネストした構造になっています。 契約情報の一覧を取得する トークンを取得したら、そのトークンを使って契約情報の一覧を取得します。こちらもまず構造体を定義します。 type ContractsJson struct { Value []Contract `json:"contracts"` } type Contract struct { Id int `json:"contract_id"` Status string `json:"contract_status"` ProductName string `json:"product_name"` UsedServerCount int `json:"used_server_count"` ContractDateFrom string `json:"contract_date_from"` ContractDateTo string `json:"contract_date_to"` Price int `json:"price"` PriceInit int `json:"price_init"` ResourceInfo ResourceInfo `json:"resource_info"` } そして契約情報の一覧を取得します。getはこの後の契約情報詳細を取得する際にも使います。GETリクエストを行って、その結果をバイト文字列で返します。 // 契約情報の一覧を取得 contracts, err := getContracts(baseUrl, token) func getContracts(baseUrl string, token string) ([]Contract, error) { url := baseUrl + "/contracts" body, err := get(url, token) var contractsJson ContractsJson if err := json.Unmarshal(body, &contractsJson); err != nil { log.Fatal(err) } return contractsJson.Value, err } // GETリクエストを行う処理 func get(url string, token string) ([]byte, error){ req, _ := http.NewRequest("GET", url, nil) req.Header.Set("Content-Type", "application/json") req.Header.Set("X-Auth-Token", token) client := new(http.Client) res, err := client.Do(req) body, err := ioutil.ReadAll(res.Body) defer res.Body.Close() return body, err } 契約情報詳細を取得する 契約情報IDを取得したら、さらに詳細を取得します。これは GET /contracts/{id} となっています。 構造体としては契約情報自体は変わらないので、そのモデルキーになる構造体だけ定義します。さらにCPUやメモリ、ストレージとしたリソース情報を入れる構造体も定義します。 type ContractJson struct { Value Contract `json:"contract"` } type ResourceInfo struct { CpuMax int `json:"cpu_max"` MemoryMax int `json:"memory_max"` DiskMax int `json:"disk_max"` CpuUsed int `json:"cpu_used"` MemoryUsed int `json:"memory_used"` DiskUsed int `json:"disk_used"` } そして契約情報の詳細を得るためのコードです。 // 契約情報の詳細を取得 contract, err := getContract(baseUrl, token, contracts[0].Id) log.Println(contract) func getContract(baseUrl string, token string, id int) (Contract, error){ url := baseUrl + "/contracts/" + strconv.Itoa(id) body, err := get(url, token) log.Println(string(body)) var contractJson ContractJson if err := json.Unmarshal(body, &contractJson); err != nil { log.Fatal(err) } return contractJson.Value, err } 結果として、次のような出力が得られます。 {114581 契約中 C4 1 2018/09/03 2959 0 {2 4 100 1 2 50}} Goの場合、構造体を作るのが若干の手間かも知れません。しかしCloudGarage APIのようにRESTfulの原則に則っていれば構造体の使い回しも効きます。Goのコードは見やすく書けますのでぜひ使ってみてください。 APIリファレンスはCloudGarage API リファレンスにありますので、ぜひご覧ください。

TECH
中津川 篤司

ついに公開されたAPIをPythonから利用する(インスタンス一覧を取得&インスタンスを停止)

CloudGarageのインスタンス操作などを自動化できるAPIがついに公開されました。これでインスタンスの立ち上げや停止を自動化できるようになります。 そこで今回はPythonを使ってAPI操作を行う方法を解説します。インスタンスを一覧で取得した後、インスタンスを停止させる操作を行います。 必要なソフトウェア、ライブラリ 今回必要なソフトウェア、ライブラリは以下の通りです。 Python request APIキーを取得する まずはCloudGarageの管理画面にてAPIキーを取得します。管理画面の右上にあるメニューをクリックして、アカウント情報確認/変更を選択します。 一度パスワードを入力する必要があります。 そして一番下にあるAPI Key管理にてAPI Keyを発行します。私はすでに発行済みなので再発行になっていますが、最初はAPIキーがないはずです。Client ID(クライアントID)とClient Secret(クライアントシークレット)の二つで認証します。重要なキーなので漏洩したりしないよう注意してください。 トークンを取得する 次にAPIを利用するためのトークンを取得する必要があります。コードは次のようになります。 POST /tokens リクエストして、その結果として得られるJSONの token.id の値がトークンになります。 import requests import json config = json.load(open('./config.json', 'r')) def getToken(base_url, config): response = requests.post(f"{base_url}/tokens", data=json.dumps({ 'client_id': config['clientId'], 'client_secret': config['clientSecret'], }), headers={ 'Content-Type': 'application/json' } ) return response.json()['token']['id'] base_url = 'https://api.cloudgarage.jp' token = getToken(base_url, config) インスタンス一覧を取得する トークンを取得したら、それを使ってAPIにアクセスできます。次にインスタンス一覧を取得します。これは GET /servers になります。取得したJSONの servers 以下に配列で返ってきます。 def getInstances(base_url, token): response = requests.get(f"{base_url}/servers", headers={ 'X-Auth-Token': token, 'Content-Type': 'application/json' } ) return response.json()['servers'] servers = getInstances(base_url, token) インスタンスを停止する 最後にインスタンスを停止させます。今回はインスタンス一覧の最初のインスタンスを止めてみます。これは POST /servers/operate になります。operateとして今回はSTOP(停止)を指定します。他にもSTART(起動)、RESTART(再起動)、RESTART_HARD(強制再起動)があります。 def stopInstance(base_url, token, id): response = requests.post(f"{base_url}/servers/operate", data=json.dumps({ 'operate': 'STOP', 'servers': [ id ] }), headers={ 'X-Auth-Token': token, 'Content-Type': 'application/json' } ) return response.json() response = stopInstance(base_url, token, servers[0]['id']) 処理が成功した時のレスポンスです。resultに success が入ってきます。 { "operation_results": [ { "result": "success", "resource_id": "ebe...26a" } ] } 失敗時です。すでにインスタンスが停止しているとエラーになります。 { "operation_results": [ { "result": "instance is invalid state for operate : STOP", "resource_id": "ebe...26a" } ] } まとめ Pythonの場合はHTTPリクエストを標準ライブラリだけでも行えますが、requestライブラリがある方がより簡単です。HTTPリクエストを行うのはとても簡単なので、Pythonを通じてAPIをコールするコードを書くのは容易でしょう。 APIリファレンスはCloudGarage API リファレンスにありますので、ぜひご覧ください。

CloudGarageでサーバセットアップ【その5:WordPressをインストールする】

TECH
中津川 篤司

インスタンスを簡単に立ち上げられるCloudGarageですが、立ち上げただけでは意味がありません。このインスタンスを使って開発を行っていかなければなりません。とは言え、自分の作りたいものはあるのに、セットアップで色々と時間が取られるのは面倒なはずです。 慣れてきたらKUSANAGI/CentOS-7.3-64bitなどのイメージから選択しても良いですが、まずは自分でイチから作業してみると何かトラブルがあってもリカバリーできるようになります。サーバの動きを掴んでおくと、後々役立つことも多いでしょう。 前回はデータベースサーバを立ち上げて、アプリケーションサーバ(nginx + PHP-FPM)と連携できるところまで進めました。今回はPHPアプリケーションの代表例とも言える、WordPressをインストールします。 WordPressはイメージもあります CloudGarageでWordPressを使う方法は3パターンあります。 WordPressホスティングプランを使う インストール済みイメージを使う 自分で構築する WordPressホスティングプランを使う場合、運用代行なども可能です。構成としてはnginx + HHVMとなっています。インストール済みイメージを使う場合、Apache + mod_phpという組み合わせになります。自分で構築する(今回のパターンです)は構成を自由に選べるのが特徴です。 すでにWordPressに慣れていて、特に問題がない場合はインストール済みイメージを使っても良いでしょう。しかし何かトラブルがあったり、細かくカスタマイズしたいと思った時には一度構築を経験しておくと何かと役立つはずです。 WordPressをダウンロード、解凍する まずアプリケーションサーバにSSHでログインします。 ssh -p 22022 (アプリケーションサーバのIPアドレス)そしてnginxのルートディレクトリに移動します。 $ cd /usr/share/nginx/html/ここにWordPressのファイルをダウンロードします。執筆時点での最新バージョンは4.9.8ですが、変わっている可能性があります。日本語 — WordPressにて確認してください。 wget https://ja.wordpress.org/wordpress-4.9.8-ja.tar.gzダウンロードしたら、ファイルを解凍します。 tar xfz wordpress-4.9.8-ja.tar.gz元ファイルは不要なので削除します。 rm wordpress-4.9.8-ja.tar.gz今回はwordpressというディレクトリにインストールしています。ディレクトリは必要に応じて変更してください。また、ディレクトリをnginxのユーザと合わせておきます。 sudo chown -R www-data:www-data wordpressWebブラウザからアクセス 設置が終わったら、Webブラウザからアクセスします。 http://(アプリケーションサーバのIPアドレス)/wordpress になります。 インストール時にデータベース設定が聞かれます。データベースはあらかじめ作成しておきましょう。また、ポート番号を変更している場合には (データベースサーバのIPアドレス):33060 のようにコロンに続けてポート番号を指定します。後は通常のセットアップと変わりません。 問題なく完了したらログインして管理画面に入れるのを確認しましょう。 画像のアップロードもできれば、ファイルの書き込み権限も正しく与えられているのが確認できます。 まとめ ここまででCloudGarageの二つのインスタンス(アプリケーションサーバとデータベースサーバ)を使って、nginx + PHP-FPMの組み合わせでPHPアプリケーションをインストールする流れが完成しました。 より複雑なシステム構築になると、Gitを使ったり、CI(継続的インテグレーション)による自動化なども考えるようになるでしょう。ともあれ、システム構築の基本は変わりませんので、ここまでの流れを覚えておくと様々に応用が効くはずです。

CloudGarageでサーバセットアップ【その4:アプリケーションサーバとデータベースサーバを連携する】

TECH
中津川 篤司

インスタンスを簡単に立ち上げられるCloudGarageですが、立ち上げただけでは意味がありません。このインスタンスを使って開発を行っていかなければなりません。とは言え、自分の作りたいものはあるのに、セットアップで色々と時間が取られるのは面倒なはずです。 慣れてきたらKUSANAGI/CentOS-7.3-64bitなどのイメージから選択しても良いですが、まずは自分でイチから作業してみると何かトラブルがあってもリカバリーできるようになります。サーバの動きを掴んでおくと、後々役立つことも多いでしょう。 前回はnginxとPHP-FPMをインストールするところまでいきました。今回はより本格的に開発できるようにデータベースサーバを立てて、連携できるようにします。 アプリケーションサーバとデータベースサーバ ごくごく小さなWebアプリケーションの場合、一台のサーバ内にすべての機能を追加します。サーバの役割は様々にありますが、ちょっとしたものであれば「HTTP」「アプリケーション」「データベース」という三層に分かれると思います。さらに大きくなると「キャッシュ」や「API」などの役割も出てくるでしょう。 今回の構成では nginx をHTTPサーバとして、PHP-FPMをアプリケーション、MySQLをデータベースとして構築します。前回、nginxとPHP-FPMを一つのインスタンスにインストールしましたので、「HTTP」「アプリケーション」の役割は一つのインスタンスが担っています。データベースは負荷が高くてボトルネックになりやすいので別なインスタンスとしても分離させます。 データベースインスタンスのセットアップ まずデータベースサーバになるインスタンスを立てます。CloudGarageではあらかじめリソースを確保して利用します。例えばCPUを2コアで購入していれば、「HTTP」と「アプリケーション」サーバを1コア、データベースを1コアと割り当てられます。 今回はデータベースインスタンスをUbuntu 16.04 LTSで立てています。ポートは全開放しています。 セキュリティ上の設定 ライブラリの更新、ユーザの作成、sudo設定はHTTPサーバで行った時と変わりません。ポートは22022でSSHを利用できるだけとして、他はすべて無効としています。 MySQLサーバのセットアップ MySQLのインストール aptを使ってMySQLをインストールします。 sudo apt-get install mysql-server MySQLの設定を変更 デフォルトのポートは 3306 で、ローカルからしか接続を許可しないようになっています。この設定を変更します。ファイルは /etc/mysql/mysql.conf.d/mysqld.cnf になります。変更点は以下の2行です。 [mysqld] port=33060 # 元は3306 # bind-address = 127.0.0.1 # コメントアウトする これでMySQLを再起動します。 service mysql restart データベース接続用ポートを公開する 次にHTTPサーバからデータベースに接続できるようにポートを公開するのですが、単純にufwを使うとインターネット全体に渡って公開されてしまいます。それはセキュリティ上好ましくないので、ローカルネットワークからしか接続できないようにします。 CloudGarageでは自分の契約したインスタンス同士がローカルネットワークで接続されており、 192.168.0.* (*は任意の数字)でアクセスできます。そこで、このアドレス範囲においてデータベースに接続できるようにします。 sudo ufw allow from 192.168.0.1/24 to any port 33060 これで完了です。設定が終わると次のようになっているはずです。 sudo ufw status numbered Status: active To Action From -- ------ ---- [ 1] 22022/tcp ALLOW IN Anywhere [ 3] 33060 ALLOW IN 192.168.0.0/24 データベースのユーザを作成する MySQLをインストールする際に root のパスワードを設定しているはずです。それを使ってMySQLに接続します。ポート番号が変わっているので注意してください。 mysql -uroot -p -P 33060 接続したらデータベースを作成します。今回は mydb として作成します。 CREATE DATABASE mydb DEFAULT CHARACTER SET utf8; そして作成したDBに対して操作権限を持つユーザを作成します。 GRANT ALL PRIVILEGES ON mydb.* TO app@'(HTTPサーバのIPアドレス)' IDENTIFIED BY '(パスワード)'; これでHTTPサーバからアクセスできるユーザが作成できました。 PHPから接続する ではHTTPサーバからPHPで接続してみましょう。まず必要なライブラリをインストールします。 sudo apt-get install php7.0-mysql -y これでMySQLiがインストールされます。最後にPHP-FPMを再起動します。 sudo service php7.0-fpm restart コードを書く 例えば以下のようなコードを書きます( /usr/share/nginx/html/mysql.php などとします)。接続先情報はそれぞれ書き換えてください。 <?php $mysqli = new mysqli('(DBのIPアドレス):(DBのポート番号)', '(ユーザ名)', '(パスワード)', '(データベース名)'); if ($mysqli->connect_error) { echo $mysqli->connect_error; exit(); } else { echo "MySQL接続成功"; $mysqli->set_charset("utf8"); } ?> もしファイルが書き込めない場合には /usr/share/nginx/html/ のアクセス権限を変えてください。 chmod -R 777 /usr/share/nginx/html/ そしてWebブラウザからアクセスします。MySQL接続成功、と出れば接続が無事行われています。 Linux + Apache + PHP + MySQLはLAMP環境と呼ばれて人気の技術スタックでしたが、今はApacheに変わってnginxを使うことが増えています。とは言えPHPとMySQLの組み合わせは今なおWeb開発のデファクトとも言えるくらい有名な組み合わせです。皆さんもぜひPHPとMySQLを組み合わせてWeb開発をはじめてみてください!

CloudGarageでサーバセットアップ【その3:nginxとPHP-FPMを連携させる】

TECH
中津川 篤司

インスタンスを簡単に立ち上げられるCloudGarageですが、立ち上げただけでは意味がありません。このインスタンスを使って開発を行っていかなければなりません。とは言え、自分の作りたいものはあるのに、セットアップで色々と時間が取られるのは面倒なはずです。 慣れてきたらKUSANAGI/CentOS-7.3-64bitなどのイメージから選択しても良いですが、まずは自分でイチから作業してみると何かトラブルがあってもリカバリーできるようになります。サーバの動きを掴んでおくと、後々役立つことも多いでしょう。 前回はHTTPサーバを立ち上げるところまでいきましたので、今回はPHPを使えるようにします。 nginxとPHPの組み合わせについて PHPを手軽に使おうと思うとApache + mod_phpという組み合わせが一番簡単でしょう。しかし最近ではHTTPサーバとしてより高速なnginxとPHP-FPMを組み合わせるケースが増えています。FPMとはFastCGI Process Managerの略です。FastCGIは実行プロセスを常時立ち上げておくことで実行速度を高速化する技術です。PHP-FPMを用いることで、nginx上でも高速なPHP実行環境が手に入ります。 PHP-FPMをインストールする インストールはaptで行えます。 sudo sudo apt-get install -y php php-fpm そして起動します。 sudo service php7.0-fpm start これでPHP側の準備は完了です。設定ファイルである /etc/php/7.0/fpm/pool.d/www.conf を見ると、次のように書かれています。 user = www-data listen = /run/php/php7.0-fpm.sock この二つの情報を覚えておきます。 nginxの設定 nginxの設定ファイルを編集します。ファイルは /etc/nginx/conf.d/default.conf です。 〜.php というアクセスがあると location ~ [^/]\.php(/|$) { 以下の設定が適用されます。ファイル名を取得して $document_root$fastcgi_script_name というPHPファイルを実行します。 $document_root は root で定義されている /usr/share/nginx/html/ です。 server { listen 80; # 省略 # root を移動(全体に関係するので) root /usr/share/nginx/html/; location / { # / へのアクセスを index.php へのアクセスとしたい場合は追加 if (!-e $request_filename) { rewrite ^/(.+)# /index.php?q=$1 last; break; } index index.php index.html index.htm; } # PHP FPMの設定 location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+\.php)(/.+)$; if (!-f $document_root$fastcgi_script_name) { return 404; } fastcgi_pass unix:/run/php/php7.0-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; } # 省略 } さらにPHPが www-data というユーザで実行されていますので、nginxも合わせておきます。これは /etc/nginx/nginx.conf です。 # 変更前 user nginx; # 変更後 user www-data; /usr/share/nginx/html/ も www-data 向けにします。 sudo chown -R www-data:www-data /usr/share/nginx/html/ 実行してみる では /usr/share/nginx/html/index.php というファイルを作成して、以下の内容を記述します。 <?php phpinfo(); ?> これでサーバにアクセスしてみます。URLは https://ドメイン名/index.php になります。 PHP Infoが表示されればPHPは正しく動作しています。後はWordPressをはじめとして好きなPHPソフトウェアをインストールしたり、Webアプリケーションの開発が行えるでしょう。 PHPはWeb開発で最も人気のあるプログラミング言語でしょう。実際に使っている方も多いはずです。CloudGarageを使って素早くPHP開発環境を整えてみてください! 次回は別インスタンスでデータベースを立ち上げてPHPから接続してみます。

CloudGarageでサーバセットアップ【その2:ドメインの割り当てとSSL/TLS対応】

TECH
中津川 篤司

インスタンスを簡単に立ち上げられるCloudGarageですが、立ち上げただけでは意味がありません。このインスタンスを使って開発を行っていかなければなりません。とは言え、自分の作りたいものはあるのに、セットアップで色々と時間が取られるのは面倒なはずです。 慣れてきたらKUSANAGI/CentOS-7.3-64bitなどのイメージから選択しても良いですが、まずは自分でイチから作業してみると何かトラブルがあってもリカバリーできるようになります。サーバの動きを掴んでおくと、後々役立つことも多いでしょう。 前回のインスタンス設定に続いて、今回はHTTPサーバを立ち上げるところまで進めます。 使うもの 今回利用するソフトウェア、サービスは以下の通りです。 nginx HTTPサーバです Let's Encript 無料のSSL/TLSサービスです nginxの立ち上げ nginxはaptでインストールできます。 sudo apt-get install nginx 恐らくこれで立ち上がっているはずですが、もし立ち上がっていなかったら以下のコマンドを入力します。 sudo service nginx start HTTPサーバが立ち上がっていれば、 http://222.222.222.222 (IPアドレスは自分のものと置き換えてください)でnginxのデフォルトページが表示されるはずです。 ドメインの割り当て ドメイン業者は色々あるのですが、今回は個人的にドメインを持っていたValue Domainのものを使っています。レコードは二つ追加しています。 a @ 222.222.222.222 a * 222.222.222.222 上は http://example.com/ でアクセスできるようにする設定、下は http://www.example.com/ や http://aaa.example.com/ でもアクセスできるようにする設定です(example.comはあなたのドメインに置き換えてください)。 設定が終わってからDNSに反映されるまではしばらくかかります。 http://(ドメイン名) でアクセスできるようなってから次のステップに進んでください。 SSL/TLS証明書の取得 まずLet's Encriptのライブラリをインストールします。 sudo apt-get install letsencrypt 一旦nginxを終了します。 sudo service nginx stop Let's Encryptを実行します。 sudo letsencrypt certonly --standalone -d (あなたのドメイン名) これでメールアドレスを入力したり、規約に同意すると証明書が取得できます。 nginxの設定を変更 nginxの設定ファイルを編集します。 sudo vi /etc/nginx/conf.d/default.conf 追加するのはポート番号とSSL証明書のパスです。(ドメイン名)はあなたのドメイン名と置き換えてください。 listen 80; # 以下を追加(ここから) listen 443 ssl; ssl_certificate /etc/letsencrypt/live/(ドメイン名)/cert.pem; ssl_certificate_key /etc/letsencrypt/live/(ドメイン名)/privkey.pem; # 以下を追加(ここまで) server_name localhost; 確認する ではnginxを起動しましょう。 sudo service nginx start これで http://(ドメイン名) と https://(ドメイン名) でアクセスできれば成功です。 HTTPSはかつては高価で、個人サイトではなかなか持てるものではありませんでした。しかし低価格が進み、さらにLet's Encryptのように無料でSSLが使えるサービスが登場したことによって、誰でも手軽に使えるようになりました。さらに現在ではGoogle Chromeでアクセスした時にHTTPサイトは安全ではないと表示されるなど、SSL/TLS化が当たり前になっています。 ぜひ皆さんのサイトもセキュアにしてください。次回はnginxとPHPを組み合わせたいと思います。

ページトップへ