default eye-catch image.

ルーティング

この記事は自分の勉強のために書いています。 ソースはLaravel5.7の公式ドキュメントです。 新しいことは何もないので通常はそちらを参照してください。 [clink implicit=\"false\" url=\"https://readouble.com/laravel/5.7/ja/routing.html\" imgurl=\"http://laravel.jp/assets/img/header.jpg\" title=\"Laravel 5.7 ルーティング\" excerpt=\"基本的なルーティング\"] [arst_toc tag=\"h4\"] 基本的なルーティング routes.phpの書き方 HTTP動詞に対応させたroutes.phpの書き方。RESTfulAPIを書く場合は必要なんだと思う。 anyを使うと全ての動詞に対応する。matchを使うと対応する動詞を選べる。 No 動詞 文法 1 GET Route::get($url,$callback); 2 POST Route::post($url,$callback); 3 PUT Route::put($url,$callback); 4 PATCH Route::patch($url,$callback); 5 DELETE Route::delete($url,$callback); 6 OPTIONS Route::options($url,$callback); 7 全て Route::any($url,$callback); 8 選んだ動詞 Route::match($array_of_verb,$url,$callback); リダイレクトルート 単純にリダイレクトをかける場合は、わざわざコントローラを通さなくて良い。 (コントローラを通してた...)。 通常302で、301もルーティングだけで対応可能。 No HTTP Status Code 文法 1 302 Route::redirect(\'here\',\'there\'); or Route::redirect(\'here\',\'there\',302); 2 302 Route::redirect(\'here\',\'there\',301); or Route::permanentRedirect(\'hear\',\'there\'); Viewルート ルートから直接ビューを返す場合はコントローラを介さなくてもよい。 No文法 1Route::view($url,$view_name); 2Route::view($url,$view_name,$array_of_parameters); ex, Route::view($url,$view,[\'param1\'=>100,\'param2\'=>200]); CSRF保護 webルートに定義したPOST,PUT,DELETEへのルートへ送信するフォームは 一緒にCSRFトークンを送る必要がある(CSRFは別にまとめる予定)。 ルートパラメータ URLの動作に必要なパラメタをクエリ文字列ではなくURLに含める書き方。 必須パラメータとしておけば省略は不可となり存在チェックを省略できる。 必須パラメータ Curly bracketsでパラメタ名を囲んで定義する。 受けるクロージャはそのパラメタ名をもつ引数を使用する。 Route::get(\'application/{application_id}\', function($application_id) { return $application_id; }); 任意パラメータ Curly brackets内のパラメタ名を\"?\"で終わらすと任意パラメータになる。 受けるクロージャでは必ずデフォルト引数を設定する。 Route::get(\'user/{name?}\',function($name = null) { return $name; }); 正規表現制約 ルートパラメタのフォーマットを正規表現で制約できる(そんなことできるんだ...)。 書き方は以下の通り。URLとクロージャは触らない。 Route::get(\'user/{name}\', function($name) { return $name; })->where(\'name\',\'[A-Za-z]+\'); グローバル制約 RouteServiceProviderのbootメソッドに全てのルートパラメタを制約するルールを書ける。 例えば以下のように書いておくと、全てのルートの\"id\"という名前のクエリパラメタが数値に制約される。 /** * */ public function boot() { Route::pattern(\'id\',\'[0-9]+\'); parent::boot(); } /** * routes.php */ Route::get(\'user/{id}\',function($id) { return $id; // $idは数値に制約 }); 名前付きルート 定義したルートに名前を付けておくことで、そのルートのURLを名前から引くことができる。 名前付きルート 例えばuser/{id}に対するルートにmypageという名前を付けるには以下。 Route::get(\'user/{id}\',function($id) { return $id; })->name(\'mypage\'); 名前付きルートへのURL取得 このルートへのURLはroute()により取得できる。 ルートが必須/任意パラメータを必要とする場合は第2引数で値を与える。 redirect()->route(\'mypage\',[\'id\'=>100]); ルートグループ 複数のルートで共通の属性(=ミドルウェアと名前空間)をまとめて書ける。 グループはネストすることができる。ミドルウェアと名前空間は別途記載。 ミドルウェアによるグループ化 複数のルートで共通のミドルウェアを外出しする書き方は以下。 (もちろん個別に書くこともできる) Route::middleware([\'first\',\'second\'])->group(function() { Route::get(\'/\',function(){ // firstミドルウェア、secondミドルウェアを順番に使用 }); Route::get(\'/hoge/{id}\',function($id){ // firstミドルウェア、secondミドルウェアを順番に使用 }); }); 名前空間によるグループ化 複数のルートで同じPHP名前空間を使用する書き方は以下。 こうすることで、各コントローラのファイルの先頭に名前空間を書かなくてもよくなる。 Route::namespace(\'Namespace1\')->group(function() { // AppHttpControllersNamespace1 名前空間下のコントローラ }); })/ <?php namespace App/Http/Controllers/Namespace1; // <- これが不要になる サブドメインによるグループ化 複数のルートが同じサブドメイン配下にあるような配置にする書き方は以下。(こんなことできるのか!)。 Route::domain(\'{subdomainname}.myapp.test\')->group(function() { Route::get(\'user/{id}\',function($id) { // subdomainname.myapp.test/user/100 }); }); ルートプレフィックスによるグループ化 複数のルートが同じ文字列からスタートするように配置する書き方は以下。 Route::prefix(\'sameprefix\')->group(function() { Route::get(\'user/{id}\',function($id) { // /sameprefix/user/100 }); Route::get(\'group/{id}\',function($id) { // /sameprefix/group/200 }); }); ルート名プレフィックスによるグループ化 複数のルートのルート名が同じ文字列からスタートするように配置する書き方は以下。 Route::name(\'sameprefix\')->group(function() { Route::get(\'user/{id}\',function($id) { // \'sameprefix.user\' というルート名 })->name(\'user\'); Route::get(\'group/{id}\',function($id) { // \'sameprefix.group\' というルート名 }); }); モデル結合ルート ルートで与えた情報(多くの場合でモデルID)をコントローラに渡して コントローラの中でモデルインスタンスを引くという使い方がほとんどなので、 ルートに含めたモデルIDからモデルインスタンスを解決してコントローラでそれを使うことができる。 当然、クロージャを直接書いても同じ。 暗黙のモデル結合ルート どうやってルートパラメータとモデルインスタンスを紐づけるかというと、 なんと、PHPのタイプヒントを使って紐づける。 以下、$userがAppUserクラスであるとタイプヒントされている。 ルートパラメータにuserがあるから、クロージャの中ではAppUserのインスタンスを $userを使って引いたオブジェクトを使用できる。 わざわざ$userを使ってAppUser::find($user)と書いたりエラーケースを書くのを省略できる。 AppUser::find($user)が見つからなかったらルートは404を返す。すごいー。 Route::get(\'users/{user}\',function(AppUser $user) { // AppUser $user を使用できる。 }); キー名がカスタマイズされたモデル結合ルート モデルの主キーがidではないときimplicitにidからModelを引くことが出来ない。 モデル側でgetRouteKeyName()をオーバーライドして主キーを返せば良い。 ルートパラメータを新しい主キーであるものとしてインスタンスを探してくれる。 Route::get(\'users/{user}\',function(AppUser $user) { // AppUser.userid が $user であるインスタンスを使用できる。 }); /** * モデルの中 * */ public function getRouteKeyName() { return \'userid\'; } 明示的なモデル結合ルート ルート名とタイプヒントを使ってimplicitにモデル結合する方法とは別に、 RouteServiceProviderクラスのboot()メソッドの中でexplicitにモデル結合を定義できる。 タイプヒントがなくても良いというのならexplicitに書く意味もあると思うのだけど、 タイプヒントが必要なのであれば、implicitな記法に対して冗長な気がするんだけども...。 /** * RouteServiceProvider * */ public function boot() { parent::boot(); Route::model(\'user\',AppUser::class); } /** * routes.php * */ Route::get(\'user/{user}\',function(AppUser $user) { }); 依存解決ロジックのカスタマイズ 「ルートパラメータをモデルID、タイプヒントをモデルクラスとして、モデルIDを主キー(または別のキー) を使って検索する」という単純なロジックとは異なるロジックを定義する方法が用意されている。 例えばモデルを主キーとは関係ないフィールドで検索したいときは以下みたいに書く。 /** * RouteServiceProvider * */ public function boot() { parent::boot(); Route::bind(\'user\', function($value) { return AppUser::where(\'name\',$value)->first() ?? abort(404); }); } モデル側でresoluveRoutingBind()をオーバーライドすることでも実現可能。 /** * モデル * */ public function resolveRoutingBind($value) { return $this->where(\'name\',$value)->first() ?? abort(404); } その他 フォールバックルート フォールバックルートを書いておくと、routes.phpに書いたどのルートにも当たらなかったときに使われる。 通常404になるところを受ける。書く場合は最後に配置しないといけない。 Route::fallback(function(){ // do something when 404. });

default eye-catch image.

FileMakerServer16/17に非公式SSL/TLS証明書をインストールする

はじめに オンプレミスでFileMakerServerを配置するのではなく、AWS,Azure,さくらクラウドなどに配置することが増えているためか、FileMakerServerにSSL/TLS証明書をインストールしたいという要望が増えていそうです。 FileMaker社はFMS15,16用に利用可能なSSL/TLS証明書を公開していますが[1]、どれもアメリカ本国の業者であるだけでなく、いわゆる格安証明書がリストされておらず、たかだかイントラ用のアプリのために高額なお布施を積まないといけない状況にあります。 FileMaker社はFMS17用に利用可能なSSL/TLS証明書に関する記述を改めましたが[2]、いずれにせよ、適合するか否かは実験してみる必要があります。 適合しない証明書をインストールすると、「通信は暗号化されているか証明書を検証できない」というおかしな状況が出来上がります[3]。もともとClosedな傾向が強いFileMakerですが、この状況がどういう理由で発生しているのか確認する術がなく、発生してしまった場合に解決が非常に困難です。 日本の格安SSL/TLS証明書をFMS15,16,17にインストールすることができましたので、 本記事ではその事実を紹介します。 まず結論 以下の証明書をFMS15,16,17にインストールできました。 「鍵マーク」は緑色となります。 さくらインターネットのRapidSSL(DV証明書) 1,620円/年 中間CA証明書必須 クロスルート証明書必須 AWS EC2上 WindowsServer2012 R2 (JPN) または Azure上のWindowsServer2012 R2(JPN) IISでファイル認証 OS、プラットフォーム、Webサーバはオプションです。他でもOKなはずです。 格安証明書で有名なSSLストアはRapidSSLのファイル認証をやめてしまったので、 RapidSSLをファイル認証で取得できるのはここだけかもしれません。 SSLストアのFujiSSL、ComodoSSL(PositiveSSL)はいずれも入りませんでした。 中間CA証明書、クロスルート証明書がないと、証明書自体のインストールは出来ますが、鍵が「オレンジ色」になります。FMSは中間CA証明書、クロスルート証明書を見ています。 なお、FMSには中間証明書を指定するUIが一つしかありませんので、FileMaker社が指定する方法で中間CA証明書、クロスルート証明書を結合する必要があります。 以下の通り結合し1つのファイルとしておきます。 -----BEGIN CERTIFICATE----- Root certificate -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- Intermediate certificate 2 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- Intermediate certificate 1 -----END CERTIFICATE-----

default eye-catch image.

非マルチサイトでユーザ情報を共有する

概要 ネットワーク機能経由のマルチサイトでなく、サブディレクトリ型マルチサイトでもなく、 単純にサブディレクトリに複数のWordPressインスタンスを並列するケースで、 複数のWordPressインスタンスから一つのユーザ情報を共有する方法について書く。 wp_users,wp_usermetaの共有 このあたりを参照すると書いてある。要は、インスタンスの数だけ作られるwp_users、wp_usermetaを使わず、一つを共有すれば良い。そのためにはwp-config.phpを修正すれば良い。ただしWordPressの互換性的な都合を理解しておく必要がある。 カスタム User テーブルとカスタム Usermeta テーブル CUSTOM_USER_TABLE および CUSTOM_USER_META_TABLE を使用すると、通常 WordPress が利用する user および usermeta テーブルを使用せず、代わりに指定されたテーブル名を使用してユーザー情報を格納します。 define( \'CUSTOM_USER_TABLE\', $table_prefix.\'my_users\' ); define( \'CUSTOM_USER_META_TABLE\', $table_prefix.\'my_usermeta\' ); WordPressは互換性確保のためwp_usersの拡張を推奨しておらず、wp_usermetaに拡張情報を持たせることになっている。拡張情報をwp_usersのカラムとして持たないことで、拡張が必要になったときに初めてwp_usermetaにレコードが作られる。つまり、wp_usermetaはインスタンス毎の拡張情報であるということ。 そのため、CUSTOM_USER_TABLE、CUSTOM_USER_META_TABLEを指定したとしても、共有しようとしたwp_users、wp_usermetaとは別にインスタンス毎にwp_users,wp_usermetaテーブルが作られる。 インスタンスのインストール時にID=1番のレコードが作られる。インスタンスの最初の管理者はこのレコードである。wp_usersのID=1はSuperAdmin的な特別なアカウントで、各インスタンスのwp_users,wp_usermetaが使われる。 共有しようとするwp_usersには、インストールしたインスタンス用のwp_usermetaが無いので「権限なし」となる。そこで、まず、各インスタンスに作られてしまったID=1でログインし、次に共有するwp_usersテーブルのアカウントにインスタンス毎の権限を付与することで解決する。 面倒だけど、確かにアカウントの互換性は保たれるな。

default eye-catch image.

FileMakerServer15の通信を無料でSSL化する方法

FileMakerServer15からデータベースの公開に関してセキュリティが考えられるようになった(本気になった感じ)。Windows VPSにFileMakerServerを配置することでお手軽クラウドが完成するので、割と重要なアップデートだと思う。 Rapid SSLは無理 CSRを作成し、証明書に署名してもらって、秘密鍵と一緒にサーバにインストールする流れはWebサーバと同じだが、RapidSSLなどドメイン認証式(かつファイル認証式)の証明書を作成する場合、FMSは80番で待っている訳ではないから「DocumentRootにファイルを配置してクロールしてもらう」という手続きを進められない。 じゃあ、簡易httpdを立てたらどうか。 RapidSSLのサイトには以下のような記述がある。 RapidSSL、PositiveSSLをお申込みの方へ ホームページが未完成、ホームページに運営者情報が掲載されていない場合、会員制など、ログインが必要なホームページの場合、審査を通過しないケースが増えております。 仮のWebサーバを立てて80番を開けてファイルを配置しても、そもそも怪しい署名リクエストはリジェクトされちゃうらしい!とりあえず、1日経っても来なかった。 一般的なフローではないのだから、仕方ないんじゃないかな。と納得する。そして無料SSLに触手を伸ばす。 Linuxであれば、Certbotを使って90日間の証明書を発行すれば良いが、2017年3月現在、WindowsServerで動作するCertbotが存在せず、Certbotは利用できなさそうである。Windows Serverにvagrant/virtualboxを立てて80番をそこに通すというやり方を思いついたが、それは相当に面倒くさい。 Zero SSL 世の中には便利なサービスがあるものだ。Certbot認証局側をやってくれるサービスが存在する。Zero SSLだ。手順はここのサイトが詳しかった。 サービスのWizardに従ってCSRとコモンネーム(ドメイン)を入力すると、サーバの80の指定URLにファイルを置いてくれ、と言われる。Wizardに従ってNextボタンを押下し続ければ、画面に署名済み証明書と中間証明書が表示される。 FMS15側で1)証明書、2)プライベートキー、3)中間証明書を入れてくれ、と言われるが、2)のプライベートキーはFMS15で生成したものをいれる。ZeroSSLで生成されるプライベートキーは利用しない。1),2),3)を安全な場所に保管しておくこと。 肝心のポート番号だが、80を閉じても繋がるようになった。しかし、443以外のwell knownでないFileMaker専用ポートは依然として使われるようだ。SSLをトンネルとして使うという訳ではなさそうだ。

default eye-catch image.

Laravel Mutator Accessor

たぶん Delphi/C# が起源だと思うんだが、データに紐づく規則や処理をモデルに寄せるパターン(Microsoft:The Repository Pattern)と同等の機能がPHP FrameworkであるLaravelのORM(Eloquent)にあり、流石に超便利だったのでメモっておく。 setter側をMutator、getter側をAccessorという。Mutator, Accessorを簡単にまとめると以下のような感じ。 Eloquentインスタンスに対して値をセットする際に必ずあるメソッド(Mutator)を経由する機能 Eloquentインスタンスから値をゲットする際に必ずあるメソッド(Accessor)を経由する機能 本家のドキュメントは以下のように続く。 Accessors and mutators allow you to format Eloquent attribute values when you retrieve or set them on model instances. For example, you may want to use the Laravel encrypter to encrypt a value while it is stored in the database, and then automatically decrypt the attribute when you access it on an Eloquent model. データに紐づくルールや処理をモデルに寄せることでコントローラの肥大化を防ぐ機能の一つだが、コントローラとモデルの間の取り決めを規約によって定めることで、コントローラからもモデルからも扱いやすくなる。 例えば、usersテーブルにfirst_nameという名前のフィールドがあったとする。 フィールドには小文字で入力し、使うときは必ず先頭1文字を大文字として使う、というルールがある場合Userモデル側を以下のような規約に従って書く。 <?php namespace App; use IlluminateDatabaseEloquentModel; class User extends Model { /* * Get the user\'s first name. * * @param string $value * @return string */ public function getFirstNameAttribute($value) { return ucfirst($value); } /* * Set the user\'s first name. * * @param string $value * @return void */ public function setFirstNameAttribute($value) { $this->attributes[\'first_name\'] = strtolower($value); } } コントローラからfirst_nameフィールドの値を取るコードは以下の通りだが、必ずAccessorを経由し値が返る。フィールドの値が何であれ先頭は必ず大文字になる。ブラウザ等に表示する際に加工する必要がない。 <?php $user = AppUser::find(1); $firstname = $user->first_name; ブラウザ等からデータが入って来たとき、それをusers.first_nameフィールドに格納する処理を書く際、必ずMutatorを経由する。 「小文字にする」という処理を一切意識しないで良い。 <?php $user = AppUser::find(1); $user->first_name = \'Sally\'; コントローラより上は涼しい顔をして重い処理の記述を省略できる。データに紐づくルールが重ければ重いほどモデルに寄せる効果が大きくなる。 例えば、データを暗号化して格納するケースにおいては、暗号化/復号処理をModelに隠蔽しControllerより上からは透過的に平文として扱うなど。 Eloquentは流石に雄弁だ。

default eye-catch image.

Laravel5 Form Request Validationによるコントローラの軽量化

フォームのビジネスロジック(検証や保存)をコントローラに書くと、どうでも良いコードでコントローラが重くなってくる。フォームが複数ある場合、だいたい似たり寄ったりのコードが量産されていく。本エントリでは、Laravel5 の Form Request Validation によってコントローラからバリデーションロジックを完全分離する方法について記述する。 Form Request Validation - バリデーションの分離 流れは以下の通り。 AppHttpRequestsRequestクラスを派生し、ContactRequestクラスを作成する。 コントローラメソッドにて、AppHttpRequestsRequestクラスのインスタンスではなく ContractRequestクラスのインスタンスを受けるようにする。 コントローラメソッドに入ったときには既にContactRequestクラスによるバリデーションが完了していて、データが正しい前提で処理できる。 ContactRequestクラス、ContactRequestTraitクラスの例を以下に示す。 <?php namespace AppHttpRequests; class ContactRequest extends Request { use ConfirmRequestTrait; /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ \'name\' => \'required\', \'email\' => \'required|email\', \'subject\' => \'required\', \'content\' => \'required\', ]; } /** * Set custom messages for validator errors. * * @return array */ public function messages() { return [ // ]; } /** * Set custom attributes for validator errors. * * @return array */ public function attributes() { return [ \'name\' => \'お名前\', \'email\' => \'メールアドレス\', \'subject\' => \'件名\', \'content\' => \'内容\', ]; } } <?php namespace AppHttpRequests; use IlluminateContractsValidationValidator; trait ConfirmRequestTrait { /** * Set custom messages for validator errors. * * @param IlluminateContractsValidationFactory $factory * * @return IlluminateContractsValidationValidator */ public function validator($factory) { // 値検証前の処理 if (method_exists($this, \'beforeValidate\')) { $this->beforeValidate(); } $validator = $factory->make( $this->all(), $rules, $this->messages(), $this->attributes() ); $validator->after(function ($validator) { $failed = $validator->failed(); // 値検証後の処理 if (method_exists($this, \'afterValidate\')) { $this->afterValidate($validator); } }); return $validator; } /** * Format the errors from the given Validator instance. * * @param IlluminateContractsValidationValidator $validator * * @return array */ protected function formatErrors(Validator $validator) { $errors = parent::formatErrors($validator); return $errors; } } Form Request Validation - コントローラ側 ポイントは、storeメソッドの引数に ContactRequestヒントが渡されていること。sotreメソッドに入る前にContactRequestによりバリデーションが実行され、バリデーションに成功した時に限り、sotre()メソッドに入る。バリデーションが失敗すると、その前のアドレスにリダイレクトされる。コントローラから一切のバリデーションロジックを排除できた。 <?php namespace App¥Http¥Controllers; use App¥Http¥Requests¥ContactRequest; use App¥Repositories¥ContactRepository; class ContactController extends Controller { /** /* @var ContactRepository */ protected $repository; /** /* @constructor /* param ContactRepository $repository */ public function __construct(ContactRepository $repository) { $this->repository = $repository; } /* * */ public function index() { ... } /** * @var ContactRequest $request * */ public function store(ContactRequest $request) { } }

default eye-catch image.

VPC内にElastic Beanstalk + RDS の環境を構築して Laravel アプリをデプロイする [Laravel5アプリデプロイ編]

今後も何度か同じことを調べそうなので忘備録としてまとめておく。手順をstep by stepで記述するが、それぞれ分量が多いので以下の通り章立てを行ってエントリを分割する。 VPC構築編 VPCの作成 VPC、NetworkACL、SecurityGroupの確認、タグ付け VPCのDNSホスト名を有効にする サブネットの作成、タグ付け インターネットゲートウェイの作成、タグ付け、VPCにアタッチ パブリックサブネット用RoutingTableの作成 パブリックサブネット用RoutingTableにインターネットゲートウェイの関連付け 作成したサブネットをパブリックサブネット用RoutingTableに繋ぎかえる RDS構築編 MySQLの設定変更(DBパラメータグループの作成) DBサブネットグループを作成 RDS用セキュリティグループの作成 RDSインスタンスの作成 エンドポイントの確認、疎通確認 Elastic Beanstalk構築編 環境の構築 .ebextensionsによるカスタマイズ Laravel5アプリデプロイ編(本エントリ) gitリポジトリからclone .envの編集 アプリで使うDBのダンプファイルをRDSにコピー Laravelインストーラの準備 Laravel本体のインストール ビルトインサーバでの疎通確認 Elastic Beanstalkへのデプロイ gitリポジトリからclone 通常 Laravel5 にはデフォルトの .gitignore が作られており、Laravel本体は.gitignoreに登録されている。まず、アプリをcloneし、そのあとでLaravel本体をインストールする。 どこか、Laravel5の要件を満たすところでgitリポジトリからcloneする。 $ pwd /home/ikuty/www/ $ git clone ssh://servername/var/git/project.git project .envの編集 アプリケーションの設定を変更する。/config 内に各種設定ファイルが配置されているが、laravelでは.envを変更することで /config内のenv()関数に展開される仕組みになっている。だから、/config 内の各種ファイルを直接変更する必要はない。/config 内も git の構成管理に含めても良い。 cloneした先でenvを編集する。.env_example をリネームすると楽。 APP_KEY= *** 次項で示すようにキーを生成する DB_HOST : RDS編で設定したRDSエンドポイントを指定する DB_DATABASE, USERNAME, PASSWORD : RDS編で設定した各種設定を指定する APP_ENV=local APP_DEBUG=true APP_KEY=**** APP_URL=http://hoge.com/ DB_CONNECTION=mysql DB_HOST=rds-endpoint DB_PORT=3306 DB_DATABASE=hogedb DB_USERNAME=hoge DB_PASSWORD=fuga CACHE_DRIVER=file SESSION_DRIVER=file QUEUE_DRIVER=sync キーを生成する。以下のコマンドで .env の APP_KEY が差し替わる。 $ php artisan key:generate アプリで使うDBのダンプファイルをRDSにコピー 本来は Migration を使うべきだが...。Migration を利用しないでDBを作ってしまった場合は泥臭くやる...;;まず、ダンプ。 $ mysqldump -u hoge -p appdb > appdb.sql RDS側にDBを作成し権限を付与しておく。 $ mysql -h [rds-endpoint] -u hoge -p $ > CREATE DATABSE appdb; $ > GRANT ALL ON appdb.* to hoge@localhost; $ > FLUSH PRIVILEGES; $ > SHOW DATABSES; $ > ... RDS上のDBにダンプしたsqlを流し込む。 $ mysql -h [rds-endpoint] -u hoge -p -D appdb < appdb.sql Laravelインストーラの準備 composerを利用する。パスを通す。本エントリ作成時の最新は version1.3.3。 $ composer global require \"laravel/installer=~1.1\" $ echo \'export PATH=~/.composer/vendor/laravel/installer:$PATH\' >> ~/.bash_profile $ source .bash_profile $ laravel Laravel Installer version 1.3.3 Laravel本体のインストール composerが準備できたらcomposer installでLaravel本体をインストールする。 $ cd project $ composer install ビルトインサーバでの疎通確認 この状態でビルトインサーバを立ち上げ、疎通確認を行う。 $ cd project php artisan serve --host hoge.com Laravel development server started on http://hoge.com:8000/ Elastic Beanstalkへのデプロイ Elastic Beanstalk構築編にて、環境の準備が出来ているものとする。 eb deploy コマンドにより、カレントディレクトリ以下のファイルをデプロイする。また、.ebextension に DocumentRoot を設定する。カレントディレクトリと DocumentRoot の組み合わせを正しく設定する必要がある。 まず、DocumentRootを設定するため、.ebextensionディレクトリを作成し、設定ファイルを作成する。 $ pwd /home/ikuty/www/ $ mkdir .ebextensions $ cd .ebextensions $ vi 01_documentroot.config 01.documentroot_config は以下の通り。YAMLとして記述する必要がある。空白とタブの扱いがシビアなので、タブが入らないように注意する。ファイルの先頭の\"01\" は、ファイルが解釈される順番を表す。.ebextensions 内に、01,02,... のように設定を複数配置できる。 option_settings: - namespace: aws:elasticbeanstalk:container:php:phpini option_name: document_root value: /project/public DocumentRoot を /project/public と設定した場合に正しい構成になるように、カレントディレクトリを移動し、eb deployを実行する。~/www に移動して、/project 以下をデプロイすれば良い。 $ cd ~/www/ $ eb deploy Creating application version archive \"app-160630_130423\". Uploading: [##################################################] 100% Done... INFO: Environment update is starting. INFO: Deploying new version to instance(s). INFO: New application version was deployed to running EC2 instances. INFO: Environment update completed successfully. 設定が正しければ2分弱で完了する。

default eye-catch image.

VPC内にElastic Beanstalk + RDS の環境を構築して Laravel アプリをデプロイする [ElasticBeanstalk構築編]

今後も何度か同じことを調べそうなので忘備録としてまとめておく。手順をstep by stepで記述するが、それぞれ分量が多いので以下の通り章立てを行ってエントリを分割する。 VPC構築編 VPCの作成 VPC、NetworkACL、SecurityGroupの確認、タグ付け VPCのDNSホスト名を有効にする サブネットの作成、タグ付け インターネットゲートウェイの作成、タグ付け、VPCにアタッチ パブリックサブネット用RoutingTableの作成 パブリックサブネット用RoutingTableにインターネットゲートウェイの関連付け 作成したサブネットをパブリックサブネット用RoutingTableに繋ぎかえる RDS構築編 MySQLの設定変更(DBパラメータグループの作成) DBサブネットグループを作成 RDS用セキュリティグループの作成 RDSインスタンスの作成 エンドポイントの確認、疎通確認 Elastic Beanstalk構築編(本エントリ) 環境の構築 .ebextensionsによるカスタマイズ Laravel5アプリデプロイ編 gitリポジトリからclone .envの編集 アプリで使うDBのダンプファイルをRDSにコピー Laravelインストーラの準備 Laravel本体のインストール ビルトインサーバでの疎通確認 Elastic Beanstalkへのデプロイ 環境の構築 Elastic Beanstalk の各インスタンスを収める「環境」を作成する。この「環境」の中に、これまで作ってきたVPCの要素を追加する。 $ eb create hoge-production --sample # アプリケーションのデプロイは後で行う。今はSampleアプリケーションをデプロイ --cname com-sample-production --instance_type t2.micro --region ap-northeast-1 --tier webserver --vpc.ec2subnets subnet-b71eeac1 #VPCに作成したパブリックサブネット --vpc.elbsubnets subnet-b71eeac1 #VPCに作成したパブリックサブネット(同じにする) --vpc.id vpc-cc2b11a9 --vpc.securitygroups sg-23fe8447 #デフォルトセキュリティグループ --vpc.publicip --vpc.elbpublic 3分から5分程度時間を要する。 作成した環境のURLを開く $eb open http://com-sample-production.ap-northeast-1.elasticbeanstalk.com/ .ebextensionsによるカスタマイズ Laravel5アプリケーションをデプロイするにあたって、環境をカスタマイズする。(qiitaを参考にした) $ pwd /home/ikuty/www $ mkdir .ebextensions $ cd .ebextensions # timezoneを変更する vi 01_settimezone.config 各ファイルは以下の通り。なお、各ファイルは yaml形式であり、空白とタブの扱いがシビア。タブでインデントすると簡単に謎のエラーに悩まされる。空文字はタブではなく半角スペース。 01_settimezone.config command: 01-set_timezone: command: cp /usr/share/zoneinfo/Japan /etc/localtime

default eye-catch image.

VPC内にElastic Beanstalk + RDS の環境を構築して Laravel アプリをデプロイする [RDS構築編]

今後も何度か同じことを調べそうなので忘備録としてまとめておく。手順をstep by stepで記述するが、それぞれ分量が多いので以下の通り章立てを行ってエントリを分割する。 VPC構築編 VPCの作成 VPC、NetworkACL、SecurityGroupの確認、タグ付け VPCのDNSホスト名を有効にする サブネットの作成、タグ付け インターネットゲートウェイの作成、タグ付け、VPCにアタッチ パブリックサブネット用RoutingTableの作成 パブリックサブネット用RoutingTableにインターネットゲートウェイの関連付け 作成したサブネットをパブリックサブネット用RoutingTableに繋ぎかえる RDS構築編(本エントリ) MySQLの設定変更(DBパラメータグループの作成) DBサブネットグループを作成 RDS用セキュリティグループの作成 RDSインスタンスの作成 エンドポイントの確認、疎通確認 Elastic Beanstalk構築編 環境の構築 .ebextensionsによるカスタマイズ Laravel5アプリデプロイ編 gitリポジトリからclone .envの編集 アプリで使うDBのダンプファイルをRDSにコピー Laravelインストーラの準備 Laravel本体のインストール ビルトインサーバでの疎通確認 Elastic Beanstalkへのデプロイ MySQLの設定変更 my.cnf等のコンフィグファイルに記述していた内容をRDS風に記述する。RDSでは「DBパラメータ」に設定を記述していく。まず、DBパラメータを作成する。 $ aws rds create-db-parameter-group --db-parameter-group-name mydbparamgroup --db-parameter-group-family mysql5.6 --description \"public rds\" { \"DBParameterGroup\": { \"DBParameterGroupName\": \"mydbparamgroup\", \"DBParameterGroupFamily\": \"mysql5.6\", \"Description\": \"public rds\" } } 文字コード関連の設定 $ aws rds modify-db-parameter-group --db-parameter-group-name --parameters ParameterName=character_set_client,ParameterValue=utf8mb4,ApplyMethod=immediate ParameterName=character_set_connection,ParameterValue=utf8mb4,ApplyMethod=immediate ParameterName=character_set_database,ParameterValue=utf8mb4,ApplyMethod=immediate ParameterName=character_set_results,ParameterValue=utf8mb4,ApplyMethod=immediate ParameterName=character_set_server,ParameterValue=utf8mb4,ApplyMethod=immediate ParameterName=collation_connection,ParameterValue=utf8mb4_general_ci,ApplyMethod=immediate ParameterName=collation_server,ParameterValue=utf8mb4_general_ci,ApplyMethod=immediate ParameterName=skip-character-set-client-handshake,ParameterValue=0,ApplyMethod=pending-reboot init_connectパラメータの設定。デフォルトの設定をファイルに落とし、ファイルを変更する。 $ aws rds modify-db-parameter-group --generate-cli-skeleton > init_connect.json # 変更後 $ cat init_connect.json { \"DBParameterGroupName\": \"\", \"Parameters\": [ { \"ParameterName\": \"\", \"ParameterValue\": \"\", \"Description\": \"\", \"Source\": \"\", \"ApplyType\": \"\", \"DataType\": \"\", \"AllowedValues\": \"\", \"IsModifiable\": true, \"MinimumEngineVersion\": \"\", \"ApplyMethod\": \"\" } ] } # 出力された設定ファイルを変更する $ vi init_connect.json # 変更内容は以下の通り $ cat init_connect.json { \"DBParameterGroupName\": \"mydbparamgroup\", \"Parameters\": [ { \"ParameterName\": \"init_connect\", \"ParameterValue\": \"SET SESSION time_zone = CASE WHEN POSITION(\'rds\' IN CURRENT_USER()) = 1 THEN \'UTC\' ELSE \'Asia/Tokyo\' END;\", \"Description\": \"\", \"Source\": \"\", \"ApplyType\": \"\", \"DataType\": \"\", \"AllowedValues\": \"\", \"IsModifiable\": true, \"MinimumEngineVersion\": \"\", \"ApplyMethod\": \"immediate\" } ] } # 設定ファイルを読み込む $ aws rds modify-db-parameter-group --cli-input-json file://init_connect.json { \"DBParameterGroupName\": \"mydbparamgroup\" } DBサブネットグループを作成 DB構築編にてAvailabilityZoneが異なるDB用サブネットを2個作成した。それぞれID/tagは\"subnet-131feb65\"/\"subnet public db1\"、\"subnet-d6d2d38f\"/\"subnet public db2\"であった。 DB サブネットグループmydbsubnetgroupを作成する。 aws rds create-db-subnet-group --db-subnet-group-name mydbsubnetgroup --db-subnet-group-description \"DB SubnetGroup for RDS Instance\" --subnet-ids subnet-131feb65 subnet-d6d2d38f { \"DBSubnetGroup\": { \"Subnets\": [ { \"SubnetStatus\": \"Active\", \"SubnetIdentifier\": \"subnet-131feb65\", \"SubnetAvailabilityZone\": { \"Name\": \"ap-northeast-1a\" } }, { \"SubnetStatus\": \"Active\", \"SubnetIdentifier\": \"subnet-d6d2d38f\", \"SubnetAvailabilityZone\": { \"Name\": \"ap-northeast-1c\" } } ], \"DBSubnetGroupName\": \"mydbsubnetgroup\", \"VpcId\": \"vpc-cc2b11a9\", \"DBSubnetGroupDescription\": \"DB SubnetGroup for RDS Instance\", \"SubnetGroupStatus\": \"Complete\" } } RDS用セキュリティグループの作成 RDS用セキュリティグループ myrds を作成する。 $ aws ec2 create-security-group --group-name myrds --description \"RDS security group\" --vpc-id vpc-cc2b11a9 { \"GroupId\": \"sg-b50742d1\" } #タグ付け $ aws ec2 create-tags --resources sg-b50742d1 --tags Key=Name,Value=\"sg rds\" RDS MySQLにVPCから接続するために、RDS用セキュリティグループに3306からのInbound許可設定を行う。(作成済のVPCセキュリティグループのIDはsg-73490c17。) $ aws ec2 authorize-security-group-ingress --group-id sg-b50742d1 --protocol tcp --port 3306 --source-group sg-73490c17 [参考] 下記のようにCIDR標記のアドレスを指定するとVPCの外部からも接続可能になる。 $ aws ec2 authorize-security-group-ingress --group-id sg-b50742d1 --protocol tcp --port 3306 --cidr 0.0.0.0/0 RDSインスタンスの作成 DBパラメータグループ、デフォルトセキュリティグループ、RDS用セキュリティグループを指定する。 外部からの接続を許可する場合 -- publicly-accessible を指定する必要がある。 $ aws rds create-db-instance --db-instance-identifier hogedb --allocated-storage 5 --db-instance-class db.t2.micro --engine MySQL --engine-version 5.6.22 --master-username hoge --master-user-password fuga --db-name hogedb --db-parameter-group-name mydbparamgroup --db-subnet-group-name mydbsubnetgroup --vpc-security-group-ids sg-23fe8447 sg-b50742d1 --storage-type standard --availability-zone ap-northeast-1a --no-multi-az --region ap-northeast-1 --publicly-accessible --no-auto-minor-version-upgrade 疎通確認 エンドポイントを確認する。予めjqコマンドを利用可能にしておくこと。 # jqがない場合 $ sudo yum install jq $ aws rds describe-db-instances --db-instance-identifier hogedb | jq \'.DBInstances[].Endpoint\' { \"Address\": \"hogedb.c3w6*******5990.ap-northeast-1.rds.amazonaws.com\", \"Port\": 3306 } PublicIp、PublicDnsName を確認する。 $ aws ec2 describe-network-interfaces --filters \"Name=description,Values=RDSNetworkInterface\" { .. \"Description\": \"RDSNetworkInterface\", \"Association\": { \"PublicIp\": \"54.95.100.249\", \"PublicDnsName\": \"ec2-54-92-100-249.ap-northeast-1.compute.amazonaws.com\", \"IpOwnerId\": \"amazon-rds\" }, .. } mysql コマンドでエンドポイントに接続してみる。 $ mysql -h 54.95.100.249 -P 3306 -u hoge -p -D hogedb Enter password: fuga Welcome to the MySQL monitor. Commands end with ; or g. Your MySQL connection id is 9 Server version: 5.6.22-log MySQL Community Server (GPL) Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. ...

default eye-catch image.

VPC内にElastic Beanstalk + RDS の環境を構築して Laravel アプリをデプロイする [VPC作成編]

今後も何度か同じことを調べそうなので忘備録としてまとめておく。手順をstep by stepで記述するが、それぞれ分量が多いので以下の通り章立てを行ってエントリを分割する。 VPC構築編(本エントリ) VPCの作成 VPC、NetworkACL、SecurityGroupの確認、タグ付け VPCのDNSホスト名を有効にする サブネットの作成、タグ付け インターネットゲートウェイの作成、タグ付け、VPCにアタッチ パブリックサブネット用RoutingTableの作成 パブリックサブネット用RoutingTableにインターネットゲートウェイの関連付け 作成したサブネットをパブリックサブネット用RoutingTableに繋ぎかえる RDS構築編 MySQLの設定変更(DBパラメータグループの作成) DBサブネットグループを作成 RDS用セキュリティグループの作成 RDSインスタンスの作成 エンドポイントの確認、疎通確認 Elastic Beanstalk構築編 環境の構築 .ebextensionsによるカスタマイズ Laravel5アプリデプロイ編 gitリポジトリからclone .envの編集 アプリで使うDBのダンプファイルをRDSにコピー Laravelインストーラの準備 Laravel本体のインストール ビルトインサーバでの疎通確認 Elastic Beanstalkへのデプロイ 前提 aws cli, eb-cli をインストールしておくこと。 $ pwd /home/ikuty $ aws --version aws-cli/1.10.37 Python/2.6.6 Linux/2.6.32-573.22.1.el6.x86_64 botocore/1.4.27 $ eb --version EB CLI 3.7.6 (Python 2.7.9) Administrator AccessポリシーをもつユーザをIAMで作成し、aws-cli から該当ユーザの権限で操作できるようにしておくこと。 $ aws configure AWS Access Key ID [****************] AWS Secret Key [***********************] Default region name [ap-northeast-1] Default output format [json] VPCの環境構築 VPCを作成する。アドレスの範囲をCIDR標記で記述する。ネットワーク部を16bit取る。 vpc-cc2b11a9というIDのVPCが作成されたという報告がjsonで戻る。 $ aws ec2 create-vpc --cidr-block 10.0.0.0/16 { \"Vpc\": { \"VpcId\": \"vpc-cc2b11a9\", \"InstanceTenancy\": \"default\", \"State\": \"pending\", \"DhcpOptionsId\": \"dopt-fec65c9b\", \"CidrBlock\": \"10.0.0.0/16\", \"IsDefault\": false } } vpc-cc2b11a9というVPCにNameタグを付与する。 $ aws ec2 create-tags --resources vpc-cc2b11a9 --tags Key=Name,Value=\"vpc\" VPCとは、クラウド上に閉じたネットワークを構築する機能であり、VPC作成時に、閉じたネットワークを構成する要素が同時に生成される。構成要素は以下の通り。 Routing Table Subnet Network ACL Security group なお、Network ACL、Security group について AWS のドキュメントでは以下の通り説明している。 Amazon VPCのネットワークACL(アクセスコントロールリスト)は、サブネット内外のトラフィックを制御するファイアウォールとして任意のセキュリティを提供します。セキュリティグループの設定と同じようにACLのルールを適応することによって、VPCに追加のセキュリティ層を提供します。EC2はサブネット指定ができませんのでネットワークACLを利用することはできません。 なんのこっちゃ、だが、図を見ると一目瞭然である。NetworkACLを使ってサブネット毎にファイアウォールを定義できる! NetworkACL、SecurityGroupいずれもファイアウォールのように見えるが、以下のような違いがある。 セキュリティグループ ネットワーク ACL インスタンスレベルで動作します(第 1 保護レイヤー) サブネットレベルで動作します(第 2 保護レイヤー) ルールの許可のみがサポートされます ルールの許可と拒否がサポートされます ステートフル: ルールに関係なく、返されたトラフィックが自動的に許可されます ステートレス: 返されたトラフィックがルールによって明示的に許可されます トラフィックを許可するかどうかを決める前に、すべてのルールを評価します トラフィックを許可するかどうかを決めるときに、順番にルールを処理します インスタンスの起動時に誰かがセキュリティグループを指定した場合、または後でセキュリティグループをインスタンスに関連付けた場合にのみ、インスタンスに適用されます。 関連付けられたサブネット内のすべてのインスタンスに自動的に適用されます(バックアップの保護レイヤーなので、セキュリティグループを指定する人物に依存する必要はありません) Routing tableにタグをつける vpc-cc2b11a9というIDを持ったVPCのRouting tableを確認する。rtb-964da5f2というIDを持ったRouting tableを確認できる。 $ aws ec2 describe-route-tables --filters \"Name=vpc-id,Values=vpc-cc2b11a9\" { \"RouteTables\": [ { \"Associations\": [ { \"RouteTableAssociationId\": \"rtbassoc-b2fd42d6\", \"Main\": true, \"RouteTableId\": \"rtb-964da5f2\" } ], \"RouteTableId\": \"rtb-964da5f2\", \"VpcId\": \"vpc-cc2b11a9\", \"PropagatingVgws\": [], \"Tags\": [], \"Routes\": [ { \"GatewayId\": \"local\", \"DestinationCidrBlock\": \"10.0.0.0/16\", \"State\": \"active\", \"Origin\": \"CreateRouteTable\" } ] } ] } $ aws ec2 create-tags --resources rtb-964da5f2 --tags Key=Name,Value=\"rtb main\" NetworkACLにタグをつける $ aws ec2 describe-network-acls --filters \"Name=vpc-id,Values=vpc-cc2b11a9\" { \"NetworkAcls\": [ { \"Associations\": [], \"NetworkAclId\": \"acl-25fb1a41\", \"VpcId\": \"vpc-cc2b11a9\", \"Tags\": [], \"Entries\": [ { \"CidrBlock\": \"0.0.0.0/0\", \"RuleNumber\": 100, \"Protocol\": \"-1\", \"Egress\": true, \"RuleAction\": \"allow\" }, { \"CidrBlock\": \"0.0.0.0/0\", \"RuleNumber\": 32767, \"Protocol\": \"-1\", \"Egress\": true, \"RuleAction\": \"deny\" }, { \"CidrBlock\": \"0.0.0.0/0\", \"RuleNumber\": 100, \"Protocol\": \"-1\", \"Egress\": false, \"RuleAction\": \"allow\" }, { \"CidrBlock\": \"0.0.0.0/0\", \"RuleNumber\": 32767, \"Protocol\": \"-1\", \"Egress\": false, \"RuleAction\": \"deny\" } ], \"IsDefault\": true } ] } $ aws ec2 create-tags --resources acl-25fb1a41 --tags Key=Name,Value=\"acl main\" SecurityGroupにタグをつける SecurityGroupを確認する。ID=sg-23fe8447というSecurityGroupが存在することがわかる。 $ aws ec2 describe-security-groups --filters \"Name=vpc-id,Values=vpc-cc2b11a9\" { \"SecurityGroups\": [ { \"IpPermissionsEgress\": [ { \"IpProtocol\": \"-1\", \"IpRanges\": [ { \"CidrIp\": \"0.0.0.0/0\" } ], \"UserIdGroupPairs\": [], \"PrefixListIds\": [] } ], \"Description\": \"default VPC security group\", \"IpPermissions\": [ { \"IpProtocol\": \"-1\", \"IpRanges\": [], \"UserIdGroupPairs\": [ { \"UserId\": \"281631559249\", \"GroupId\": \"sg-23fe8447\" } ], \"PrefixListIds\": [] } ], \"GroupName\": \"default\", \"VpcId\": \"vpc-cc2b11a9\", \"OwnerId\": \"281631559249\", \"GroupId\": \"sg-23fe8447\" } ] } $ aws ec2 create-tags --resources sg-23fe8447 --tags Key=Name,Value=\"sg main\" VPCのDNSホスト名を有効にする VPC内のRDSに外部から接続できるようにDNSホスト名を有効にする。 #有効にする $ aws ec2 modify-vpc-attribute --vpc-id vpc-cc2b11a9 --enable-dns-hostnames #確認する $ aws ec2 describe-vpc-attribute --vpc-id vpc-cc2b11a9 --attribute enableDnsHostnames { \"VpcId\": \"vpc-cc2b11a9\", \"EnableDnsHostnames\": { \"Value\": true } } サブネットを作成する 最初のVPC作成時に、16ビットをネットワーク部として使う意図で、CIDR標記で/16を設定した。さらに、8ビットをサブネットとして利用するため、CIDR標記で/24を設定する。8ビット分(第3オクテット分)がサブネットとして利用でき、そのうち .0、.1、.2 のサブネットを作成する。第4オクテットがホスト部となるが、8ビット全て利用することはできず、利用できる最大数がそれぞれ\"AvailableIpAddressCount\"に書かれてる。なお、各サブネットにそれぞれIDが振られる。 RDSをMultiAZで運用しない場合でもDBサブネットグループを作成する際に2つのAvailabilityZoneが必要なので異なるAvailabilityZoneに対応するサブネットを作成する。 $ aws ec2 create-subnet --vpc-id vpc-cc2b11a9 --cidr-block 10.0.0.0/24 --availability-zone ap-northeast-1a { \"Subnet\": { \"VpcId\": \"vpc-cc2b11a9\", \"CidrBlock\": \"10.0.0.0/24\", \"State\": \"pending\", \"AvailabilityZone\": \"ap-northeast-1a\", \"SubnetId\": \"subnet-b71eeac1\", \"AvailableIpAddressCount\": 251 } } # ap-northeast-1a AvailabilityZone $ aws ec2 create-subnet --vpc-id vpc-cc2b11a9 --cidr-block 10.0.1.0/24 --availability-zone ap-northeast-1a { \"Subnet\": { \"VpcId\": \"vpc-cc2b11a9\", \"CidrBlock\": \"10.0.1.0/24\", \"State\": \"pending\", \"AvailabilityZone\": \"ap-northeast-1a\", \"SubnetId\": \"subnet-131feb65\", \"AvailableIpAddressCount\": 251 } } # ap-northeast-1c AvailabitliyZone $ aws ec2 create-subnet --vpc-id vpc-cc2b11a9 --cidr-block 10.0.2.0/24 --availability-zone ap-northeast-1c { \"Subnet\": { \"VpcId\": \"vpc-cc2b11a9\", \"CidrBlock\": \"10.0.2.0/24\", \"State\": \"pending\", \"AvailabilityZone\": \"ap-northeast-1c\", \"SubnetId\": \"subnet-d6d2d38f\", \"AvailableIpAddressCount\": 251 } } サブネットにタグを付与する 作成したサブネットには、それぞれ、subnet-b71eeac1、subnet-131feb65、subnet-d6d2d38f というIDが振られている。それぞれにタグを付与する。 $ aws ec2 create-tags --resources subnet-b71eeac1 --tags Key=Name,Value=\"subnet public web\" $ aws ec2 create-tags --resources subnet-131feb65 --tags Key=Name,Value=\"subnet public db1\" $ aws ec2 create-tags --resources subnet-d6d2d38f --tags Key=Name,Value=\"subnet public db2\" インターネットゲートウェイの作成 インターネットゲートウェイを作成し、タグを付与する。 $ aws ec2 create-internet-gateway { \"InternetGateway\": { \"Tags\": [], \"InternetGatewayId\": \"igw-5bb8203e\", \"Attachments\": [] } } $ aws ec2 create-tags --resources igw-5bb8203e --tags Key=Name,Value=\"igw main\" インターネットゲートウェイをVPCにアタッチする。 #アタッチ $ aws ec2 attach-internet-gateway --internet-gateway-id igw-5bb8203e --vpc-id vpc-cc2b11a9 #確認 $ aws ec2 describe-internet-gateways --internet-gateway-id igw-5bb8203e { \"InternetGateways\": [ { \"Tags\": [ { \"Value\": \"igw main\", \"Key\": \"Name\" } ], \"InternetGatewayId\": \"igw-5bb8203e\", \"Attachments\": [ { \"State\": \"available\", \"VpcId\": \"vpc-cc2b11a9\" } ] } ] } パブリックサブネット用のRoutingTableを作成する VPC作成時に\"rtb-964da5f2\"というIDを持つRoutingTableが作成されていることを確認した。\"rtb-964da5f2\"にはVPC作成時に自動生成されたデフォルトサブネットが紐付いている。 今回、オリジナルのサブネット、インターネットゲートウェイを新たに作成するのに合わせて、RoutingTableを新規作成する。 # RoutingTable の作成 $ aws ec2 create-route-table --vpc-id vpc-cc2b11a9 { \"RouteTable\": { \"Associations\": [], \"RouteTableId\": \"rtb-fe5cb49a\", \"VpcId\": \"vpc-cc2b11a9\", \"PropagatingVgws\": [], \"Tags\": [], \"Routes\": [ { \"GatewayId\": \"local\", \"DestinationCidrBlock\": \"10.0.0.0/16\", \"State\": \"active\", \"Origin\": \"CreateRouteTable\" } ] } } # タグ付け $ aws ec2 create-tags --resources rtb-fe5cb49a --tags Key=Name,Value=\"rtb public\" パブリックサブネット用RoutingTableにインターネットゲートウェイを関連付ける $ aws ec2 create-route --route-table-id rtb-fe5cb49a --destination-cidr-block 0.0.0.0/0 --gateway-id igw-5bb8203e { \"Return\": true } 新たに作成したサブネットをパブリックサブネット用RoutingTableに繋ぎかえる $ aws ec2 associate-route-table --route-table-id rtb-fe5cb49a --subnet-id subnet-b71eeac1 { \"AssociationId\": \"rtbassoc-0ce55a68\" } $ aws ec2 associate-route-table --route-table-id rtb-fe5cb49a --subnet-id subnet-131feb65 { \"AssociationId\": \"rtbassoc-c1e45ba5\" } $ aws ec2 associate-route-table --route-table-id rtb-fe5cb49a --subnet-id subnet-d6d2d38f { \"AssociationId\": \"rtbassoc-76c97612\" }