- 投稿日:2020-02-18T23:25:53+09:00
SEしてるけど実はあんまりコード書いたことないんだよねって人に捧ぐ、Rails on Dockerハンズオン vol.8 - Sign up -
はじめに
第8回目です。前回、Userモデルを作り上げユーザー詳細ページを作成するところまでいきました。
今回は、ユーザーをUIから登録すべくSign upページを作っていきたいと思います。いままではRailsコンソールからモデルを操作してユーザーを作成していましたが、今回からはMVCを連携させてユーザーを作成させるようにします。
Sign upページの作成
今回はSign upページでユーザーの
name
、password
を入力してもらい、登録完了後そのユーザーのユーザー詳細ページに遷移させます。
まずは、このアプリを実現するために必要なファイルや設定を作成していきます。今回、Sign upページにアクセスするためのRouting、Action、Viewと、実際にUserをDBに登録するRouting、Actionが必要になります。
Scaffoldを思い出してみてください。
あの時、新規にユーザーを作成するには/users/new
のページにアクセスしており、new
アクションがありました。
そこで登録ボタンを押すと、/users
のURLにPOSTメソッドでリクエストが飛びcreate
アクションがDBにユーザーを保存していました。では、これらの設定を元にRouting、Action、Viewをコーディングしていきましょう!
Routing
まず、
users#new
、users#create
へのルーティングを作成します。
しかし、Sign upページと呼んでいるのですから/users/new
のようなURLでは少しカッコつきません。
今回は/sign_up
にGETリクエストしたときにusers#new
にルーティングされるように定義していきましょう。
users#create
へのルーティングも/sign_up
にPOSTリクエストしたときに定義します。config/routes.rbRails.application.routes.draw do root 'static_pages#home' get '/sign_up', to: 'users#new', as: :sign_up post '/sign_up', to: 'users#create', as: :create_user resources :users, only: [:show] end追加した行は以下の通り。
get '/sign_up', to: 'users#new', as: :sign_up post '/sign_up', to: 'users#create', as: :create_user読んでいきましょう。
これは、resouces
やroot
以外のルーティングの書き方としてとても一般的なものです。
static_pages#home
を作った時もこんな感じのルーティングが自動生成されたことを覚えていますか?書き方は以下の通りです。
[method] '[path]', to: '[controller_name]#[action_name]', as: '[route_name]'このコーディングで
「path
にmethod
でリクエストされた場合、controller_name
コントローラーのaction_name
アクションにルーティングする。アプリのコードとしてroute_name
_pathと表現された場合は、このルーティングを表すことと定義する。」
ということをRailsアプリケーションに定義立てています。
route_name
はシンボル(:sign_up
のように:
を頭につけてる文字)で書いてます。シンボルは複数あっては困るものなどに使用するそうです(「Rubyのシンボルと文字列の違い | UX MILK)。
ルートの名前も重複しては困りますので、シンボルを使っています。ルーティングの設定はこれで完了です。次はコントローラーに新しくアクションを用意しましょう。
Action
次にUserコントローラーに
new
アクションを追加します。app/controllers/users_controller.rbclass UsersController < ApplicationController def show @user = User.find(params[:id]) end # newアクションを追加する def new @user = User.new end # createアクションをとりあえず追加しておく def create end end
new
アクションでは、インスタンス変数@user
にUser.new
を代入しています。
これはView側でUserモデルを扱ってフォームを作っていくために空のモデルが必要なのです。
詳しくはView側で説明しますので、ひとまずそのままコピペでお願いします。
create
アクションはとりあえず定義だけしておきます。処理はのちのち。View
ではでは、Viewファイルを作っていきます。
new
アクションでrenderされるViewなのでnew.html.erb
ファイルを作成します。# touch app/views/users/new.html.erbapp/views/users/new.html.erb<div class="container"> <h1 class="my-5">Sign up</h1> <%= form_with model: @user, url: create_user_path, local: true do |form| %> <div class="form-group"> <%= form.label :name %> <%= form.text_field :name, class: "form-control" %> </div> <div class="form-group"> <%= form.label :email %> <%= form.text_field :email, class: "form-control" %> </div> <div class="form-group"> <%= form.label :password %> <%= form.password_field :password, class: "form-control" %> </div> <div class="form-group mt-5"> <%= form.submit "Sign up!", class: "form-control btn btn-primary" %> </div> <% end %> </div>構文自体はそこまで難しくないですね。
http://localhost:3000/sign_up
にアクセスしてみましょう。
なかなかぽいページになったんじゃないでしょうか?
password_confirmation
は使わないことにしました。「登録フォームにおけるパスワード確認用の入力欄は必要か | UX MILK」の記事を参考にしまして。
いくつかrubyコードが埋め込まれているので説明していきますね。form_with
こういうのをビューヘルパー(View helper)っていいます。
『form_with』ヘルパーはform
タグを生成してくれるヘルパーです。
model
をオプションに指定することでそのモデルオブジェクトのためのフォームを作ってくれるようになります。上のコードのようにブロック形式でform
変数を使うことで、例えばform.input_field :name
とするだけで@user
のname
属性に関するinputフィールドを作ってくれるようになるので、これは超便利です。
url
オプションはフォームの送信先を定義します。create_user_path
はroutes.rb
でusers#create
へのルーティングにつけた名前ですね。
このようにコーディングすることでcreate
アクションにフォームを送信できるようになります。また、
local: true
オプションも付けています。form_with
ヘルパーではデフォルトでAjax通信でフォームをポストします。つまり、画面遷移なしでフォームをリクエストするんです。これはこれで便利な場面もあって今時な感じなんですが、今回はユーザーの新規作成が成功したらそのユーザーのマイページに画面遷移させたいので、local: true
オプションでAjax通信をオフにしています。
ちなみに『Ajax』は『エイジャックス』または『アジャックス』と読むそうです。僕は『エイジャックス』って読んでます。今回の
form_with
は実際にクライアントに返却される場合は以下のように変換されて返却されています。<%= form_with model: @user, url: create_user_path, local: true do |form| %> ... <% end %>↓
<form action="/sign_up" accept-charset="UTF-8" method="post"> <input type="hidden" name="authenticity_token" value="xxxxxxxxxx"> ... </form>
authenticity_token
が第3回の時に少し触れた、CSRFトークンですね。XSSを防いでくれるやつです。label
label
はラベルを付けてくれるやつです。ページで『お名前』とか『メールアドレス』と出ているやつのことです。<%= form.label :name %>↓
<label for="user_name">お名前</label>text_field
text_field
はinput type="text"
タグでテキストフィールドを作り出してくれます。
使い方も簡単で、text_field [attribute_name], [options]
なだけです。
今回はBootstrapのform-control
classをオプションで付けてあげています。<%= form.text_field :name, class: "form-control" %>↓
<input class="form-control" type="text" name="user[name]" id="user_name">
name
やid
も勝手に付けてくれているのがいいですよね。
ここでid="user_name"
を付与してくれているので、label
のfor="user_name"
と紐付けができるようになっています。password_field
password
を入力するフォームのところではpassword_field
を使いました。
これはtext_field
と似ていますが、input type="password"
タグのフィールドを作ってくれるやつです。<%= form.password_field :password, class: "form-control" %>↓
<input class="form-control" type="password" name="user[password]" id="user_password">
input type="password"
はパスワード用の入力フィールドを作り出せるので、入力した文字が『●』でマスク化されるようになります。submit
submit
タグはフォーム送信用のボタンを作ってくれるタグです。input type="submit"
を作ってくれるんですね。<%= form.submit "Sign up!", class: "form-control btn btn-primary" %>↓
<input type="submit" name="commit" value="Sign up!" class="form-control btn btn-primary" data-disable-with="Sign up!">HTMLの方にある
data-disable-with
はダブルクリック抑止のためのパラメータですね。RailsのERBを使えばこういった必要だけどついつい忘れてしまいがちなHTMLオプションも自動で付与してくれるので積極的に利用するといいと思います。これ以外にもいろいろなヘルパーが用意されているので、HTMLのあのタグはどうやって書けばいいのか、と思った時は直接HTMLタグを書くのではなく一度Railsでの書き方をググってみるといいでしょう!
これでViewがいい感じに作れました。次は「Sign up!」ボタンを押した時の処理をコーディングしていきます。
Createアクションをコーディング
ここまでで
new.html.erb
のフォームからcreate
アクションにフォームをリクエストできるようになりました。
ここからはcreate
アクションでリクエストされたフォームのデータからDBにUserを登録できるようにします。では、先ほど"とりあえず"作った
create
アクションをコーディングしていきます。app/controllers/users_controller.rbclass UsersController < ApplicationController ... def create @user = User.new(user_params) if @user.save redirect_to @user else render :new end end private def user_params params.require(:user).permit(:name, :email, :password) end endはい。初見だとけっこう複雑に見えるんじゃないかなーと思います。
1行ずつみていきましょう。@user = User.new(user_params)まず、
@user
にUser.new(user_params)
を代入しています。
user_params
とは何でしょう?private def user_params params.require(:user).permit(:name, :email, :password) end
user_params
はここで定義されている関数ですね。
params.require(:user).permit(:name, :email, :password)
の部分は『ストロングパラメーター(Strong parameter)』と呼ばれています。Railsが用意しているこのストロングパラメーターは意図しないデータのPOSTを防いでくれます。params.require([model_name]).permit([attribute_names])これでリクエスト内のパラメーター(
params
)からmodel_name
モデルに紐づくデータのみを抽出し、さらにその中からattribute_names
に指定されているデータのみを抽出して返却します。
それ以外のデータはドロップします。これによってユーザーのいたずらで意図しないデータが作られてしまうことを防ぐということです。
例えばモデルにはこっそりadmin
フラグみたいなものがあって1
のユーザーはなんでもできちゃう権限を持っているとします。いたずらっ子のユーザーがそれに気づいてSign upページにdeveloper toolsとかを使ってadmin=1
のフォームを追加してきたりしたとします。ここでストロングパラメーターを使っていない場合はadmin=1
でユーザーが作成されてしまいアプリが乗っ取られてしまう、みたいなことが起きちゃうんですね。
ストロングパラメーターはそういった意図しないフォームからのリクエストを無視するようになるので、安全なアプリケーションの作成に不可欠なものなのです。今回は
User
モデルのname
、password
以外のデータは無視することを定義しています。また、この関数は
private
より下に書かれています。これはクラス内からのみアクセスできる関数であることを定義しています。さて、ここまでで
@user
にuser_params
で抽出されたデータが初期値として設定されたUser
モデルオブジェクトが代入される、ということになります。if @user.save redirect_to @user else render :new end次は、この
@user
をsave
して条件分岐しています。ModelのCRUDの時にも話がでてきましたがsave
メソッドはバリデーションを通りデータをDBに保存できた場合true
を、バリデーションに引っかかった場合false
を返却します。
その結果を元にtrue
の場合はredirect_to @user
、false
の場合はrender :new
が実行されます。redirect_to @user
redirect_to
メソッドは引数にGET
メソッドでリダイレクトします。
引数には@user
を指定してます。これは、user_path(@user)
と同義です。user_path
はshow
メソッドにつけられている名前です。@user
には今DB保存が成功したUserモデルオブジェクトが入っていますので、今保存したユーザーのユーザー詳細ページに遷移させています。render :new
false
の場合はこちらが実行されます。
render
メソッドは指定したアクションのViewファイルをレンダリングするメソッドです。(いろいろと使い方はありますが、今回はこんな説明で)
通常アクションは自分の名前と同じViewファイルをレンダリングするようになっていますが、render
メソッドを使うことで別のアクションのViewファイルをレンダリングするようにすることもできます。
この場合は、new
アクションのViewファイルがレンダリングされます。さらに@user
には今false
になったUserモデルオブジェクトが入った状態でnew.html.erb
に引き渡されます。
そのため、レンダリングされたとしても今入力してた属性データは再表示されるはずだし、@user.errors
の中にはsave
に失敗した理由も残っているわけです。new.html.erb
側を少し更新すればエラーメッセージを表示することもできます。
new.html.erb
でエラーメッセージを表示できるように更新ということで
new.html.erb
を更新して、save
でエラーが発生した場合はerrors.full_messages
が表示されるようにしてみましょう。app/views/users/new.html.erb... <h1 class="my-5">Sign up</h1> <%# ここから追加 %> <% if @user.errors.any? %> <div class="alert alert-danger"> <ul class="mb-0"> <% @user.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <%# ここまで追加 %> <%= form_with model: @user, url: create_user_path, local: true do |form| %> ...これも少し説明します。
<% if @user.errors.any? %> ... <% end %>まず一番外側を囲っている部分です。
any?
メソッドは対象が"空"でないかどうかを検証して「空でない」場合にtrue
を返します。
今回は@user.errors
に対してany?
メソッドを適用しているので、validationによるエラーがある場合にtrue
になります。<div class="alert alert-danger"> <ul class="mb-0"> <% @user.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div>
@user.errors.any?
がtrue
の場合にはこの部分が表示されることになります。
ul
タグはリストを表示するためのタグですね。li
タグがul
タグのアイテムとして『・』を頭につけた箇条書き形式で表示されるようになっています。
li
タグは以下のコードに囲まれています。<% @user.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %>
@user.errors.full_messages
はバリデーションの回でも使ったので覚えている人が多いと思います。
バリデーションでエラーが起きた時にユーザーにそのまま見せれるようなエラーメッセージが配列で格納されていたやつです。
それをeach
でひとつずつ取り出し、msg
に格納して、@user.errors.full_messages
がなくなるまでブロックの中の処理を繰り返します。
ブロックの中の処理は<li><%= msg %></li>
だけなので、ここで@user.errors.full_messages
のエラーメッセージを一つずつli
タグで囲って表示してあげていますね。
結果として、全てのエラーメッセージが箇条書きの形式で表示されるようになると期待できます。ここまでできたら実際に動作確認をしてみましょう!
動作確認(エラー編)
まずはエラーの場合の動作確認をしてみます。
以前Userモデルのバリデーションを確認したときのように、いくつかのエラーケースでエラーメッセージが表示されるかどうかを確認していきましょう。存在性チェック
Userモデルでは
name
、password
全てが入力必須(presence
)な項目です。
何も入力していなければエラーになるはず。
実際に何も入力せずに「Sign up!」ボタンを選択したページがこちらです。
「お名前」「メールアドレス」「パスワード」について、それぞれエラーが出ていてUserの作成がうまくいかなかったことがわかりますね。文字数チェック
name
と
それ以上の文字数でエラーになるか確認してみましょう。51文字と256文字の文字列は↓をお使いください。
Name aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Email bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@sample.com
文字数制限のエラーが出ていますね。
ちなみに「パスワード」には適当にパスワードを入力して「Sign up!」ボタンを選択したので「パスワード」に関するエラーは出ていないです。「パスワード」はtype="password"
のフィールドを使っているので、エラー時に元の値が反映されないようになっているんですね。フォーマットチェック
ちゃんとエラーになっていますね。重複チェック
最後に
とりあえず
john@sample.com
の
前回までに作ったユーザーなどがいればそれを使っていただいても構いません。> User.create(name: "John Smith", email: "john@sample.com", password: "password")ユーザーを作ったので、同じメールアドレスを大文字とかにしてもエラーになるかを確認してみましょう。
ここまでチェックすれば、バリデーションはちゃんと効いていて、バリデーションエラーが起きた時のエラーハンドリングも正常に動作していることが確認できましたね。
動作確認(正常編)
ではいよいよユーザーを実際にUIから作ってみましょう。
今回は以下のユーザーを作ってみます。
name: Taro Tanaka email: taro@sample.com password: taro1234
ユーザー詳細ページに遷移しましたね!さらに今入力したユーザー情報もちゃんと表示されています!Welcomeメッセージを表示する
ユーザーが作成されて、ユーザー詳細ページにも遷移できたのですが何か物足りないですね。
そうだ、Welcomeメッセージがないんだ。ユーザー詳細ページは、Welcomeページというわけではないので今のまま装飾していけばいいのですが、会員登録した時に限ってでも「ようこそ!」みたいなメッセージがほしいですよね。
こういう一時的にページにメッセージを表示したいときに使えるRailsの機能として
flash
があります。
flash
はControllerで設定してあげます。今回はcreate
アクションでsave
に成功した時に表示されるようにしてみましょう。
create
アクションを通ってshow.html.erb
が表示された場合はWelcomeメッセージが表示されますが、通常show.html.erb
が表示される場合はcreate
アクションは通らずshow
アクションだけを通るので、例えばリロードすればメッセージが消えるという寸法です。app/controllers/users_controller.rb... def create @user = User.new(user_params) if @user.save # 以下の1行を追加する flash[:success] = "サインアップありがとう!" redirect_to user_path(@user) else render :new end end ...Controller側の設定はこんな感じです。
flash
に[:success]
のような形でメッセージのkey
を定義して= 文字列
の形でvalue
を与えます。View側でこれを受け取って、
flash
がある場合だけ表示するように、show.html.erb
も更新しましょう。app/views/users/show.html.erb<div class="container my-5"> <%# ここから追加 %> <% flash.each do |msg_type, msg| %> <div class="alert alert-<%= msg_type %>"><%= msg %></div> <% end %> <%# ここまで追加 %> <%= @user.name %> <br> <%= @user.email %> </div>今回は
flash[:success] = "サインアップありがとう!"
と定義しているので、msg_type
にsuccess
が、msg
にサインアップありがとう!
が格納されます。
alert-<%= msg_type %>
はalert-success
となるわけですね。Bootstrapでalert-success
のCSSが用意されているのでそれを適用するためにflash
のkeyをsuccess
にしていたわけです。
おんなじようにエラー系のメッセージにしたい場合はdanger
にしてあげたりするとViewファイルをいじらなくてもエラーっぽいCSSを適用することができます。では実際に試してみましょう。
次は花子さんを作ってみます。
http://localhost:3000/sign_up
にアクセスして以下のデータで登録してみましょう。Name: Hanako Yamada Email: hanako@sample.com Password: hanako1234この状態でリロードしてみてください。
メッセージが消えましたね。期待通りの動作です。パスワードの表示非表示を制御する
あとそうだ。先ほどUX的に
password_confirmation
は使いませんという話をしました。
しかし、今のままではパスワードが非表示しか対応していないので、ユーザーは自分の思ったパスワードが正しく入力できているか確認できません。
ただ、周りから見えないようにするのが目的でマスク化しているので、常に平文にすることもUX的によろしくないでしょう。ということで、「パスワードを表示する」チェックボックスを用意して、チェックが入っている間だけ表示されるようにしようと思います。
まず、new.html.erb
にチェックボックスを追加します。
今回は@user
に紐づかないフォーム要素になるのでcheck_box_tag
を利用します。これはinput type="check_box"
タグを作ってくれるやつです。app/views/users/new.html.erb... <div class="form-group"> <%= form.label :password %> <%= form.password_field :password, class: "form-control" %> </div> <div class="form-check"> <%= check_box_tag :visible_password, :visible, false, class: "form-check-input" %> <%= label_tag :visible_password, "パスワードを表示する" %> </div> ...↓
... <div class="form-group"> <label for="user_password">パスワード</label> <input class="form-control" type="password" name="user[password]" id="user_password"> </div> <div class="form-check"> <input type="checkbox" name="visible_password" id="visible_password" value="visible" class="form-check-input"> <label for="visible_password">パスワードを表示する</label> </div> ...ただ今のままではただのチェックボックスにチェックを入れたり外したりできるだけです。
このチェックボックスの状態に合わせて「パスワード」のフィールドをマスク化したりマスク解除したりしていきましょう。
どうやるかというと、今マスク化されているのはinput
のtype
がpassword
になっているからです。他のinput
のフィールドは普通に文字が見えていますが、これはtype
がtext
になっているからです。
なので、チェックボックスの状態に合わせて、チェックが入っている場合はtype="text"
、チェックが入っていない場合はtype="password"
と切り替えることができれば、パスワードの表示非表示を制御できるはずです。これを実装するには、フロントエンドで動作するjavascript(jQuery)を使います。
ごちゃごちゃするといけないので、
application.js
ではなくファイルを追加してそちらでコーディングしていきましょう。# touch app/javascript/packs/visible_password.jsapp/javascript/packs/visible_password.js$(function() { $("#visible_password").change(function() { type = "password" if ($(this).prop("checked")) { type = "text" } $("#user_password").attr("type", type) }) })まず、型として
$(function() { ~ })
で囲みまして、{}
の中に処理をコーディングしていきます。$("#visible_password").change(function() { ... })最初に
$("#visible_password").change
と書きました。これはid
がvisible_password
のinput
タグに変化が起きたときに処理されることを意味しています。こういった何かが起こったときに処理が実行されることを『トリガー』とか『発火する』とか言うので覚えておきましょう!
今回の場合はid
がvisible_password
のinput
の変化をトリガーにする、とか、変化が起きた時に発火する、みたいな表現をするってことです。type = "password"処理の中をみると、まず最初に
type = "password"
の変数定義をしていますね。if ($(this).prop("checked")) { type = "text" }その後、
if ($(this).prop("checked"))
の条件分岐を書いています。
$(this)
はjQueryの特殊な書き方だと思いますが、トリガーの元になった要素のことです。
prop("checked")
はその要素のチェックボックスがチェックされているかを取得するメソッドなので、$(this).prop("checked")
はvisible_password
のチェックボックスにチェックが入っていればtrue
、そうでなければfalse
になります。
つまりif
文の部分は、「チェックボックスにチェックが入っていればtype
変数を"text"
に更新する」、ことが記述されています。$("#user_password").attr("type", type)最後に、
$("#user_password")
、つまりid
がuser_password
の要素(パスワードのinput
タグ)にattr("type", type)
をしています。
attr
はその要素の属性を取得したり更新したりするメソッドです。引数が2つの場合は1つ目の引数の属性を2つ目の引数の値に更新します。今回の場合はid="user_password"
のtype
を変数type
に更新しています。変数
type
はデフォルトではpassword
、チェックボックスにチェックが入っている場合はtext
になるので、チェックボックスにチェックを入れるとパスワードが表示される仕組みです。さて、実際に使えるようにするには、このファイルを読み込めるようにする必要があります。
このファイルはアプリケーションの全てのページで使うのではなく、Sign upページでのみ利用するようなファイルなので、new.html.erb
で読み込みを定義してあげます。app/views/users/new.html.erb... <%= javascript_pack_tag 'visible_password' %>Sign upページをリロードして試してみましょう!
チェックなし??チェックあり
期待通りの動作になりましたね!
トップページからリンクさせる
最後にトップページの「Sign up now!」ボタンからSign upページにリンクを貼ってあげましょう。
前回時点では
app/views/static_pages/home.html.erb
の該当のボタンのコードは以下のようになっていますね。app/views/static_pages/home.html.erb... <%= link_to "Sign up now!", "#", class: "btn btn-lg btn-primary mt-5" %> ...この
"#"
の部分がリンク先になるので、これをルーティングで名前づけしたsign_up_path
に更新します。app/views/static_pages/home.html.erb... <%= link_to "Sign up now!", sign_up_path, class: "btn btn-lg btn-primary mt-5" %> ...はい、これで完了です!
トップページ(http://localhost:3000/
)にアクセスして「Sign up now!」ボタンをクリックしてみましょう。ちゃんとSign upページに遷移するはずです。後片付け
いつものように、次回に向けてデータを消します。
$ docker-compose down $ docker-compose run --rm web rails db:migrate:resetDBコンテナが立ち上がった状態だと思うのでdownさせます。
$ docker-compose downまとめ
今回は、サインアップページとユーザー登録機能を作っていきました。
今までと比べると少し複雑なControllerのコーディングをしましたね。バリデーションの結果に合わせてエラーメッセージを表示させてみたり、登録完了後のウェルカムメッセージを表示させたりしてみました。また、jQueryを使ってパスワードの表示非表示をクライアントサイドで変更するコーディングもやってみました。
jQuery(javascript)はWebアプリケーションを作る上では欠かせない技術ですのでぜひ覚えてくださいね。さて、今回はユーザー登録はできたものの、サインイン(ログイン)してそのユーザー独自の機能を提供する、ということはできていません。例えば、今のまま開発を進めてしまっては誰もが全てのユーザーの情報をみれてしまったり更新できてしまったりします。
そこで次回は、セッション管理をすることでサインイン機能を実装してみようと思います。では、次回も乞うご期待!ここまでお読みいただきありがとうございました!
Reference
- Ruby on Rails チュートリアル:実例を使って Rails を学ぼう
- 登録フォームにおけるパスワード確認用の入力欄は必要か | UX MILK
- Action Controller の概要 - Railsガイド
- jQuery 属性値を取得/設定/削除する(attr/removeAttr) | ITSakura
- jQueryでチェックボックスのチェック状態を取得する (jQuery + JavaScript プログラミング)
Links
・ Vol.1 - Introduction -
・ Vol.2 - Hello, Rails on Docker -
・ Vol.3 - Scaffold, RESTful, MVC -
・ Vol.4 - Static pages -
・ Vol.5 - Model and CRUD -
・ Vol.6 - Model validation -
・ Vol.7 - Secure password -
・ Vol.8 - Sign up - ?この記事
- 投稿日:2020-02-18T22:46:05+09:00
Docker上でPHP拡張モジュール『GD』を有効化する
この記事ではDocker上でPHP拡張モジュール『GD』を有効化する方法をお伝えします。
どうしてGDの有効化が必要になったか
LaravelとVueを用いたSPAを勉強したく、『Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう』に取り組んでいました。
(9)写真投稿APIでテストを実行した際に
Error: Call to undefined function Illuminate\Http\Testing\imagecreatetruecolor().
というエラーで行き詰まり、原因を調査したところPHP拡張モジュール『GD』の有効化が必要との情報にたどり着きました。環境
version PHP 7.4.1 Laravel 6.15.0 Docker for Mac 19.03.5 GD有効化の方法
DockerファイルにGDの有効化、必要なライブラリのインストールの部分を記載することでGDを有効化できます。
有効化した後、再ビルドすることで正しく動作するようになります。まずはGDが使えない状態のDockerfileをご紹介します。
DockerfileFROM php:7.4.1-fpm COPY install-composer.sh / RUN apt-get update \ && apt-get install -y wget git unzip libpq-dev \ && : 'Install Node.js' \ && curl -sL https://deb.nodesource.com/setup_12.x | bash - \ && apt-get install -y nodejs \ && : 'Install PHP Extensions' \ && docker-php-ext-install -j$(nproc) pdo_pgsql \ && : 'Install Composer' \ && chmod 755 /install-composer.sh \ && /install-composer.sh \ && mv composer.phar /usr/local/bin/composer WORKDIR /var/www/html/vuesplash【参考】
Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう (3) SPA開発環境とVue Routerこれを下記のように変更します。
:Dockerfile FROM php:7.4.1-fpm COPY install-composer.sh / RUN apt-get update \ && apt-get install -y wget git unzip libpq-dev libfreetype6-dev libjpeg62-turbo-dev libpng-dev \ && : 'Install Node.js' \ && curl -sL https://deb.nodesource.com/setup_12.x | bash - \ && apt-get install -y nodejs \ && : 'Install PHP Extensions' \ && docker-php-ext-install -j$(nproc) pdo_pgsql \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j$(nproc) gd \ && : 'Install Composer' \ && chmod 755 /install-composer.sh \ && /install-composer.sh \ && mv composer.phar /usr/local/bin/composer WORKDIR /var/www/html/vuesplash変更点は3行です。
まずは5行目。
- && apt-get install -y wget git unzip libpq-dev \ + && apt-get install -y wget git unzip libpq-dev libfreetype6-dev libjpeg62-turbo-dev libpng-dev \
libfreetype6-dev
、libfreetyep6-dev
、libjpeg62-turbo-dev
、libpng-dev
の4つのライブラリを追加しています。【参考】
docs/php at master · docker-library/docs
2点目の変更点は、変更後のファイル11行目に新たに一行挿入しています。
+ && docker-php-ext-configure gd --with-freetype --with-jpeg \PHP7.4系では
docker-php-ext-configure
の引数が変更されているので注意が必要です。【参考】
【PHP】Docker PHP7.4系でgdをインストールしてimagecreatefromjpegを使う
docs/php at master · docker-library/docs
最後に変更後のファイルの12行目のように、GDのインストールコマンドを追加して変更完了です。
+ && docker-php-ext-install -j$(nproc) gd \【参考】
docs/php at master · docker-library/docsまとめ
Laravelを勉強しているものの、基本的な言語仕様は同じだろうと高をくくっており、PHP自体の構成や拡張モジュールについては全く勉強しておらず、長時間ハマり続けてしまいました…
これを機に基本的な言語仕様や拡張モジュールについても勉強していければと思います。
また、長時間ハマり続けた別の理由として、古い情報がうまくいかない場合が多かったこともあるので、今回の記事のように苦労して解決したことは積極的に記事にしていきたいです。
まだまだPHPもLaravelもDockerも未熟なので、誤りがありましたらご指摘いただけると幸いです。
参考
- 投稿日:2020-02-18T20:21:17+09:00
docker-airflow で ログイン認証機能を設定する
docker-airflowでログイン機能を設定したい人向け。
docker-airflowの場合、公式ドキュメントの手順通り実行すると、スクリプトでのユーザー登録でこける。sqlite3.OperationalError: no such table: usersなので、自力でpasswordのハッシュ値生成して、直接ユーザー登録する必要があるので、手順をメモ。
CeleryExecutorの前提で書くけど、LocalExecutorでも同じだと思う。1. airflow.conf を編集する
${PROJECT}/config/airflow.cnf
の[webserver]
の項目のauthの設定(airflow-1.10.9ではL300あたり)を以下のようにする~略~ [webserver] ~略^ # Set to true to turn on authentication: # https://airflow.apache.org/security.html#web-authentication authenticate = True auth_backend = airflow.contrib.auth.backends.password_authとりあえず、これでログイン必須になる。アクセスするとログイン画面は表示される。
2. パスワードのハッシュを取得
pythonスクリプトで取得する。ハッシュが取れればなんでもok。
# なければ、flask-bcryptをインストール pip install flask-bcrypt # pythonスクリプトを実行しハッシュを取得 python >>> from flask_bcrypt import generate_password_hash >>> generate_password_hash('your_password', 12) # 出力されたハッシュ値をメモ3. postgreSQLに直接ユーザー情報を登録する
直接postgreSQLでuser登録を行う。
# コンテナ一覧表示 docker ps # postgreSQLのコンテナにsshログイン docker exec -it ${PSQL_CONTAINER_ID} bash # airflowユーザーでpsqlにログイン psql -U airflow # ユーザーをinsert INSERT INTO users (username, email, superuser, password) VALUES ('your_name', 'your_email', True, '2で取得したハッシュ値');これでdockerを再ビルドして、起動すればok。
参考
Fail to create user on users table on Docker Webserver Container
- 投稿日:2020-02-18T19:10:58+09:00
Dockerのログをrsyslogで出力する
概要
Dockerのログをrsyslogで出力する方法。
関連
環境
- CentOS 7.7
- rsyslog 8.24.0-41.el7_7.2
Dockerの設定
Dockerもしくはdocker-composeで、以下のパラメータを指定し、rsyslogにログが渡るようにする。
ログには、This is a example.
という文字列が出力されるようにする。
設定内容 Docker docker-compose syslogを使う --log-driver=syslog logging.driver ログの種類の分類 --log-opt syslog-facility={facility名} logging.options.syslog-facility ログやファイル名に使用する名前 --log-opt tag={任意の文字列} logging.options.tag dockerコマンドの場合
$ sudo docker run --rm \ --name sample-container \ --log-driver=syslog \ --log-opt syslog-facility=daemon \ --log-opt tag=sample-app/{{.Name}}/{{.ID}} \ -it ${Dockerイメージ名} \ /bin/bash -c 'echo "This is a example."'docker-composeの場合
docker-compose.ymlversion: '3' services: sample-container: image: sample-image command: 'echo "This is a example."' logging: driver: syslog options: syslog-facility: daemon tag: sample-app/{{.Name}}/{{.ID}}
変数 意味 {{.Name}} コンテナ名 {{.ID}} コンテナID rsyslogの設定
rsyslogのtemplateという機能を使って、ログファイル名の指定をする。
/var/log/docker/sample-app_年月日.logというログファイル名になるようにする。/etc/rsyslog.d/10-docker.conf
/etc/rsyslog.d/10-docker.conf$template DockerLogs, "/var/log/docker/%programname%_%$year%%$month%%$day%.log" if $syslogfacility-text == 'daemon' and $programname contains 'sample-app' then -?DockerLogs & stop
変数 意味 $template templateを使うための宣言 DockerLogs template名。任意の文字列でOK %programname% ログを出力しているプログラム名 $programname ログを出力しているプログラム名 $syslogfacility-text --log-opt syslog-facility もしくは logging.options.syslog-facility に指定した文字列 その他の変数は以下を参照
rsyslog.confの文法if $syslogfacility-text == 'daemon' and $programname contains 'sample-app' then -?DockerLogs
$syslogfacility-text
がdaemon
で、$programname
にsample-app
という文字列が含まれるときのみログを出す。
$syslogfacility-text
は--log-opt syslog-facility
もしくはlogging.options.syslog-facility
と、$programname
は--log-opt tag
もしくはlogging.options.tag
と合わせる必要がある。rsyslogのrestart
/etc/rsyslog.d/10-docker.confを変更したあとはrestartが必要。
$ sudo systemctl restart rsyslog出力されるログ
Dockerもしくはdocker-composeを実行。
実際に出力されるログ。
- Format:
/var/log/docker/{%programname%}_{%$year%%$month%%$day%}.log
- e.g.):
/var/log/docker/sample-app_20200218.log
sample-app/{コンテナ名}/{コンテナID}
の部分は、--log-opt tag
もしくはlogging.options.tag
に指定した文字列。/var/log/docker/sample-app_20200218.logFeb 18 17:03:19 example-hostname sample-app/sample-container/{コンテナID}[{dockerdのプロセスID}]: This is a example.コンテナIDのみを抽出してログファイル名にする
nomatch-Modeを使って、文字列を抽出してファイル名に使用する方法。
この方法を利用して、コンテナIDのみをログファイル名にしてみる。rsyslogの設定
/etc/rsyslog.d/10-docker.confに以下のように設定する。
/etc/rsyslog.d/10-docker.conf$template DockerLogs, "/var/log/docker/%syslogtag:R,ERE,1,FIELD:sample-app/sample-container/(.*)\[(.*)\]:--end%.log" if $syslogfacility-text == 'daemon' and $programname contains 'sample-app' then -?DockerLogs & stop
"/var/log/docker/%syslogtag:R,ERE,1,FIELD:sample-app/sample-container/(.*)\[(.*)\]:--end%.log"
の部分の説明。
変数 意味 /var/log/docker/ ログファイルを出力する場所 %syslogtag% --log-opt tag もしくは logging.options.tag に指定した文字列。正規表現で抽出する対象文字列となる。 R nomatchを利用するときはここはR ERE 正規表現のタイプ。BRE of ERE。EREはBREを拡張したモード。通常こちらを選択する。 1 submatchの番号 FIELD nomatchモードの指定。枠下参照。 sample-app/sample-container/(.*)\[(.*)\]:
「R」の前の文字列(この場合は%syslogtag%)からこの正規表現で文字列を抽出し、ファイル名に使用する --end%.log 最後に必ず書く 今回の設定の場合は、
%syslogtag%
から正規表現sample-app/sample-container/(.*)\[(.*)\]:
で抽出した文字列をファイル名として使用するということになる。nomatchモードについて
正規表現でマッチするものがなかった場合に返す、デフォルトの文字列をModeによって指定する。
各Modeごとに返す文字列は以下のようになっているが、FIELD
を指定した場合は、正規表現対象の文字列全てが返される。(この場合は%syslogtag%)
Mode Returned DFLT "**NO MATCH**" BLANK "" (empty string) ZERO "0" FIELD full content of original field 引用元:Property Replacer nomatch mode
今回のFIELDの正規表現の場合の挙動
%syslogtag%
=sample-app/sample-container/f76f6af73829[27081]
から、以下の正規表現で抽出をする。
sample-app/sample-container/(.*)\[(.*)\]:submatchは
1
を指定しているため、1つ目の(.*)
のみが抽出される。
つまり、コンテナIDであるf76f6af73829
が抽出される。結果、以下がファイル名となる。
/var/log/docker/f76f6af73829.logrsyslogのrestart
/etc/rsyslog.d/10-docker.confを変更したあとはrestartが必要。
$ sudo systemctl restart rsyslog出力されるログ
Dockerもしくはdocker-composeを実行。
この設定で実際に出力されるログ。
- Format:
/var/log/docker/sample-app/{コンテナ名}/{コンテナID}.log
- e.g.):
/var/log/docker/f76f6af73829.log
sample-app/{コンテナ名}/{コンテナID}
の部分は、--log-opt tag
もしくはlogging.options.tag
に指定した文字列。Feb 18 17:21:23 example-hostname sample-app/sample-container/f76f6af73829[27081]: This is a example.正規表現にマッチしない場合
rsyslogの設定
/etc/rsyslog.d/10-docker.confの正規表現の一部を、
sample-app_nomatch
としてマッチしないようにしてみる。/etc/rsyslog.d/10-docker.conf$template DockerLogs, "/var/log/docker/%syslogtag:R,ERE,1,FIELD:sample-app_nomatch/sample-container/(.*)\[(.*)\]:--end%.log" if $syslogfacility-text == 'daemon' and $programname contains 'sample-app' then -?DockerLogs & stoprsyslogのrestart
/etc/rsyslog.d/10-docker.confを変更したあとはrestartが必要。
$ sudo systemctl restart rsyslog出力されるログ
Dockerもしくはdocker-composeを実行。
この設定で実際に出力されるログ。
- Format:
/var/log/docker/sample-app/{コンテナ名}/{コンテナID}[{dockerdのプロセスID}].log
- e.g.):
/var/log/docker/sample-app/sample-container/de64dadc7e97\[27081\]\:.log
sample-app/{コンテナ名}/{コンテナID}
の部分は、--log-opt tag
もしくはlogging.options.tag
に指定した文字列。Feb 18 17:21:23 example-hostname sample-app/sample-container/de64dadc7e97[27081]: This is a example正規表現がマッチせず、
FIELD
をしているので、%syslogtag%
の中身がそのままファイル名となる。
前述したように、DFLT
の場合はファイル名が**NO MATCH**.log
、ZERO
の場合は0.log
がファイル名となる。BLANK
の場合はログファイルが出力されない。参考
- 投稿日:2020-02-18T18:46:01+09:00
Dockerコマンド自分用メモ
dockerfileをビルドしてイメージを作成
docker-compose buildコンテナの起動(イメージがない場合は構築も)
docker-compose up -dコンテナの停止
docker-compose stopコンテナを停止して削除
docker-compose down実行中のプロセス確認
docker psプロセス確認
docker ps -aコンテナ全削除
docker rm -f `docker ps -a -q`イメージ確認
docker imagesイメージ全削除
docker rmi `docker images -q`
- 投稿日:2020-02-18T16:33:45+09:00
laravelでのメール通知実装(SendGridAPI)
laravelでお問い合わせフォームを作成し、入力された内容をメールに通知する必要があったので、そこで学習したことを残しておきます。(WebAPI経由)
SendGrid APIKeyの取得
まずはSendGridのアカウントを作成する。
APIキーを発行する。発行ページがなかなかわかりづらいが、マイページの左側のメニューバーのSettings内にある。「CreateAPIKey」をクリックし、下記の画面に移ったら、APIキーに名前をつける。ここでは"laravel"。メールを送るだけなので、API Key Permissionsは Restrictedにしておく。
ここもメールを送るだけならMail Sendのみで良い。Create&Viewへ。
APIKeyが表示されるはず。クリックするだけでコピー可能。一度しか表示されないのでコピーを忘れずに。
envファイルにAPIキー、メールドライバ(ここではSendGrid)、Fromアドレス、From名を記述する。
デフォルトではSendGridをドライバーに指定できないが、パッケージを作ってくださった方がいるので、composerを使ってインストール。
ありがたいドライバー様(問題あれば消します。)MAIL_DRIVER=sendgrid SENDGRID_API_KEY='コピーしたAPIKey' MAIL_FROM_ADDRESS=送信元メールアドレス MAIL_FROM_NAME="送信元の名前"mailable作成
いよいよ実装部分。Mailableクラスを作成する。
php artisan make:mail SendGridSample
App/Mail/SendGridSampleというファイルができる。これを編集する
(忘れずに先ほどのありがたいドライバー様のuseも記述しておく。)
buildメソッドを作り、その中に処理を書いていく。fromはenvファイルに書いているのでここに書かなくても良い。
SendGridSample.php<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; use Sichikawa\LaravelSendgridDriver\SendGrid; class SendGridSample extends Mailable { use SendGrid; /** * Create a new message instance. * * @return void */ // 引数で受け取ったデータ用の変数 protected $contact; public function __construct($contact) { // 引数で受け取ったデータを変数にセット $this -> contact = $contact; } /** * Build the message. * * @return $this */ public function build() { return $this ->view('emails.email') //呼び出すテンプレートを指定 ->subject('お問い合わせ内容確認') //件名 ->with(['contact' => $this -> contact]) //withオプションでセットしたデータをテンプレートに渡す ]); } }service.phpファイルに、envのSENDGRID_API_KEYの使用を記述する。
service.php[ 'sendgrid' => [ 'api_key' => env('SENDGRID_API_KEY') ] ];メールテンプレート作成
お名前、メールアドレス、受信したお問い合わせ内容を返す簡単なもの。
<div class="row"> <h1>お問い合わせ内容を受け付けました。</h1> </div> <br> ・お名前<br> {{ $contact['name'] }}様<br> <br> ・メールアドレス<br> {{ $contact['email'] }}<br> <br> ・お問い合わせ内容<br> {!! nl2br(e($contact['post'])) !!}<br> <div class="row"> <p>お問い合わせありがとうございました。</p> </div>ContactControllerを編集
ContactController.php<?php // 作成したメールクラスをuseする use Illuminate\Support\Facades\Mail; use Sichikawa\LaravelSendgridDriver\SendGrid; public function send(Request $request) { \Mail::to($request -> email) ->send(new SendGridSample($request)); }これでお問い合わせ完了メールを送ることができる。
- 投稿日:2020-02-18T15:32:26+09:00
WordPressのソースをいじってみる(Docker調整編)
PHP出来るけど全然WordPressわからないので使ってみる(環境準備編)でサクッとDockerで環境を用意しました。
ただ、この方法だとWordPressのソースコードをいじることが難しいので少し修正します。コンテナの停止
$ docker-compose downこれで今動いているコンテナを停止します。
docker-compose.yamlの書き換え
docker-compose.yamlversion: '2' services: db: image: mysql:5.7 container_name: test-wp-db volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: wordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: image: wordpress:latest container_name: test-wp depends_on: - db ports: - "8000:80" restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_PASSWORD: wordpress volumes: - ./html:/var/www/html volumes: db_data:
wordpress
部分にvolumes
を追加しています。
これによりローカルの./html
にwordpressのソースがマウントされます。コンテナの起動
$ docker-compose up -d書き換えてみる
./html/index.php
の頭にexit;
と書いてみます。
これでhttp://localhost:8000
にアクセスするとワードプレスの画面でなく、真っ白画面になることが確認できたらOKです。まとめ
DockerのWordPress環境で、WordPressのソースコードをいじれるようにしました。
これでさらにいろいろ試せますね。
- 投稿日:2020-02-18T14:44:04+09:00
dockerで環境構築する際にrails5.2.0環境以降でcredential.ymlを編集する方法
はじめに
初投稿です。よろしくお願いします。
忘備録として投稿します。内容
docker-compose.ymlにvimを入れてインストールしたはずなのにcredential.ymlを編集しようとしても暗号化されたまま編集できませんでした。
他にも方法があるかもしれませんが、全くの初心者レベルの人が解決できると仮定してその道筋を投稿します。開発環境
docker 19.03.5
docker-compose 1.25.4
rails 5.2.4.1
ruby 2.5.1
nginx 1.15.8
Mysql 5.7docker-compose.yml
docker-compose.ymlversion: '3' services: app: &app_base build: context: . env_file: - ./environments/db.env command: bundle exec puma -C config/puma.rb volumes: - .:/webapp - public-data:/webapp/public - tmp-data:/webapp/tmp - log-data:/webapp/log depends_on: - db tty: true stdin_open: true db: image: mysql:5.7 env_file: - ./environments/db.env volumes: - db-data:/var/lib/mysql ports: - "4306:3306" web: build: context: containers/nginx volumes: - public-data:/webapp/public - tmp-data:/webapp/tmp ports: - 80:80 depends_on: - app volumes: public-data: tmp-data: log-data: db-data:Dockerfile
FROM ruby:2.5.1 # リポジトリを更新し依存モジュールをインストール RUN apt-get update -qq && \ apt-get install -y build-essential \ nodejs \ vim # ルート直下にwebappという名前で作業ディレクトリを作成(コンテナ内のアプリケーションディレクトリ) RUN mkdir /webapp WORKDIR /webapp # ホストのGemfileとGemfile.lockをコンテナにコピー ADD Gemfile /webapp/Gemfile ADD Gemfile.lock /webapp/Gemfile.lock # bundle installの実行 RUN bundle install # ホストのアプリケーションディレクトリ内をすべてコンテナにコピー ADD . /webapp # puma.sockを配置するディレクトリを作成 RUN mkdir -p tmp/socketsdocker-compose build→up -d
コンテナをbuildしてvimインストールして起動したが、あれ? credential.yml編集できない...
なぜだ....
vimインストール出来ているか見てみよう!
作業ディレクトリでwhich vimコマンド
which vim /usr/bin/vimインストールはされているな.....どうやって起動すれば良いんだ
コンテナの中に入ってみよう
コンテナの中に入ればできるかも....
docker-compose exec app bash ⬆️docker-composeのrails名そうするとroot@というところに入るので以下のコマンドを打ちましょう
EDITOR=vim bin/rails credentials:editcredentialに入れた!
credentials.yml.enc# aws: # access_key_id: 123 # secret_access_key: 345 # Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies. secret_key_base: 8be8e637d755f79c799048bed8be0c...最後に
手順を書いてある記事が少なかったので少しでも参考になればと思います。
何かあればご意見ください!
- 投稿日:2020-02-18T14:40:24+09:00
FluentdとDockerとKinesis Firehose その2(fluent.conf作成編)
はじめに
前回の続きです。
fluent.confを書いてローカルからkinesis data firehoseに流し込むところまでです前回からのDockerfileの修正点
公式をみていたら
"3. Customize Dockerfile to install plugins (optional)"の節を見落としていました。
fluent.confの場所をCOPYする場所が最後の方だったので、修正しました。修正後はこんな感じになっています。(ほとんど公式通り)
FROM fluent/fluentd:v1.9-1 USER root # install plugin RUN apk add --update-cache --virtual .build-deps sudo build-base ruby-dev \ && gem install fluent-plugin-kinesis -v 3.0.0 --no-document \ && gem sources --clear-all \ && apk del .build-deps \ && rm -rf /var/cache/apk/* \ /home/fluent/.gem/ruby/*/cache/*.gem # set timezone (Alpine) RUN apk --update-cache add tzdata && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ apk del tzdata && \ rm -rf /var/cache/apk/* COPY ./kinesis.conf /fluentd/etc/fluent.conf USER fluentつづいて、fluent.confですが下記の感じにしてみました
kinesis.conf<source> @type forward @id input1 @label @mainstream port 24224 </source> <filter **> @type stdout </filter> <label @mainstream> <match kinesis.**> @type kinesis_firehose @id output_docker1 region ap-northeast-1 aws_key_id your_aws_access_key_id aws_sec_key your_aws_secret_key delivery_stream_name test-kinesis-firehose-fluentd <buffer tag,time> @type file path /fluentd/log/kinesis timekey 30 timekey_wait 30 timekey_use_utc true </buffer> <format> @type json </format> </match> <match **> @type file @id output1 path /fluentd/log/data.*.log symlink_path /fluentd/log/data.log append true time_slice_format %Y%m%d time_slice_wait 10m time_format %Y%m%dT%H%M%S%z <format> @type json </format> </match> </label>fluent.confの定義から抜粋すると
指定方法 説明 source インプットを定義する所 match アウトプットを定義する所 label 内部ルーティング用のアウトプットとフィルターのグループに関する定義 @include 他のファイルを含める命令 filter イベント処理のパイプラインを決定する命令 となっているので、読み方としては
入力
- foward: tcp経由で来たイベントを取得する(内部でfluent-catを使用するfluent-loggerというライブラリなどで送信)
- label: @mainstreamというlabelで定義されたoutputに紐づくことをさす
- port: 24224で受け付けます
- ip: 指定していないとデフォルト "0.0.0.0"
フィルター
- stdout: 標準出力
2020-02-14T10:48:53+09:00 docker.test {"key":"value"}
こんな感じで処理される
出力
- match kinesis.**: "kiensis.hoge"というイベントで出力しますよという定義
- aws_key_id, aws_sec_key: kinesisにアクセスできる権限を持ったcredentialを定義(ECS等の場合はRole)
- type: kinesis_firehose
- delivery_stream_name: kinesis data firehoseのdelivery_stream_name
- buffer: 出力ファイルを分割する定義. * path*を定義しないとkinesis_firehoseに飛ばしてくれない
- timekey: 30秒たったらbufferとしてpath以下に吐き出す設定
は公式のまんまです。debug用としてデータが吐き出されるかみてるだけです。
ハマったのはbufferは設定したもののpathを設定してなかったので、ファイルが吐き出されずに、吸い取られる(flush)されることなく永遠にkinesis data firehoseに送り込まなかったことでした。
あと、confがイケてるかチェックするには
fluentd --dry-run -c confの場所
でできます。/fluentd/log/kinesis $ echo '{"I say":"hello"}' | fluent-cat kinesis.test /fluentd/log/kinesis $ echo '{"I say":"hello"}' | fluent-cat kinesis.test /fluentd/log/kinesis $ echo '{"I say":"hello"}' | fluent-cat kinesis.test /fluentd/log/kinesis $ echo '{"I say":"hello"}' | fluent-cat kinesis.test /fluentd/log/kinesis $ pwd /fluentd/log/kinesis /fluentd/log/kinesis $ ls -la total 16 drwxr-xr-x 6 fluent nogroup 192 Feb 18 11:56 . drwxr-xr-x 14 fluent nogroup 448 Feb 18 11:51 .. -rw-r--r-- 1 fluent nogroup 21 Feb 18 11:56 buffer.b59ed0d18a89e7ab3ccaa887b7ccfb789.log -rw-r--r-- 1 fluent nogroup 86 Feb 18 11:56 buffer.b59ed0d18a89e7ab3ccaa887b7ccfb789.log.meta -rw-r--r-- 1 fluent nogroup 126 Feb 18 11:56 buffer.b59ed0d197a62770a411b37f39a5d3f3a.log -rw-r--r-- 1 fluent nogroup 86 Feb 18 11:56 buffer.b59ed0d197a62770a411b37f39a5d3f3a.log.meta /fluentd/log/kinesis $ cat buffer.b59ed0d197a62770a411b37f39a5d3f3a.log ��{"I say":"hello"} ��{"I say":"hello"} ��{"I say":"hello"} ��{"I say":"hello"} ��{"I say":"hello"} ��{"I say":"hello"}こんな感じでbufferが吐き出されて、30秒ほどまつと吸い取られます。
kinesisのモニタリングをみると
s3をみると
できてました。
次回はECSにのっけます。
- 投稿日:2020-02-18T13:53:07+09:00
【docker】mysqlのコンテナがバグで立ち上がらなくなった
状況
dockerでmysqlのコンテナが全く起動できなくなってしまいました。
db | 2020-02-18 11:55:23+09:00 [Note] [Entrypoint]: Entrypoint script for MySQ db | 2020-02-18 11:55:23+09:00 [Note] [Entrypoint]: Switching to dedicated use db | 2020-02-18 11:55:23+09:00 [Note] [Entrypoint]: Entrypoint script for MySQ db | 2020-02-18T02:55:23.964250Z 0 [Warning] TIMESTAMP with implicit DEFAULT verver option (see documentation for more details). db | 2020-02-18T02:55:23.970525Z 0 [Note] mysqld (mysqld 5.7.29) starting as p db | 2020-02-18T02:55:23.987944Z 0 [Note] InnoDB: PUNCH HOLE support available db | 2020-02-18T02:55:23.988018Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC db | 2020-02-18T02:55:23.988026Z 0 [Note] InnoDB: Uses event mutexes db | 2020-02-18T02:55:23.988030Z 0 [Note] InnoDB: GCC builtin __atomic_thread_ db | 2020-02-18T02:55:23.988033Z 0 [Note] InnoDB: Compressed tables use zlib 1 db | 2020-02-18T02:55:23.988037Z 0 [Note] InnoDB: Using Linux native AIO db | 2020-02-18T02:55:23.988249Z 0 [Note] InnoDB: Number of pools: 1 db | 2020-02-18T02:55:23.988361Z 0 [Note] InnoDB: Using CPU crc32 instructions db | 2020-02-18T02:55:23.990183Z 0 [Note] InnoDB: Initializing buffer pool, to db | 2020-02-18T02:55:23.997519Z 0 [Note] InnoDB: Completed initialization of db | 2020-02-18T02:55:23.999353Z 0 [Note] InnoDB: If the mysqld execution userhe man page of setpriority(). db | 2020-02-18T02:55:24.090309Z 0 [ERROR] [FATAL] InnoDB: Table flags are 0 i db | 2020-02-18 11:55:24 0x7fb2e0664740 InnoDB: Assertion failure in thread 1 db | InnoDB: We intentionally generate a memory trap. db | InnoDB: Submit a detailed bug report to http://bugs.mysql.com. db | InnoDB: If you get repeated assertion failures or crashes, even db | InnoDB: immediately after the mysqld startup, there may be db | InnoDB: corruption in the InnoDB tablespace. Please refer to db | InnoDB: http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.ht db | InnoDB: about forcing recovery. db | 02:55:24 UTC - mysqld got signal 6 ; db | This could be because you hit a bug. It is also possible that this binary db | or one of the libraries it was linked against is corrupt, improperly buil db | or misconfigured. This error can also be caused by malfunctioning hardwar db | Attempting to collect some information that could help diagnose the probl db | As this is a crash and something is definitely wrong, the information db | collection process might fail. db | db | key_buffer_size=8388608 db | read_buffer_size=131072 db | max_used_connections=0 db | max_threads=151 db | thread_count=0 db | connection_count=0 db | It is possible that mysqld could use up to db | key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 681 db | /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7fb2de9cf42a] db | mysqld(+0x699b25)[0x5562a20f0b25] db | mysqld(_ZN2ib5fatalD1Ev+0x12d)[0x5562a2b60d8d] db | mysqld(+0x11b68f1)[0x5562a2c0d8f1] db | mysqld(_Z6fil_ioRK9IORequestbRK9page_id_tRK11page_size_tmmPvS8_+0x2b0)[0x5562a2c17110] db | mysqld(_Z13buf_read_pageRK9page_id_tRK11page_size_t+0xce)[0x5562a2bcc33e] db | mysqld(_Z16buf_page_get_genRK9page_id_tRK11page_size_tmP11buf_block_tmPKcmP5mtr_tb+0x4aa)[0x5562a2b9b57a] db | mysqld(_Z31trx_rseg_get_n_undo_tablespacesPm+0x143)[0x5562a2b3f1f3] db | mysqld(+0x698c99)[0x5562a20efc99] db | mysqld(_Z34innobase_start_or_create_for_mysqlv+0x2f3d)[0x5562a2b0c06d] db | mysqld(_Z24ha_initialize_handlertonP13st_plugin_int+0x4f)[0x5562a216b0ff] db | mysqld(+0xb8c0f6)[0x5562a25e30f6] db | mysqld(_Z40plugin_register_builtin_and_init_core_sePiPPc+0x2f0)[0x5562a25e6300] db | mysqld(+0x6bbece)[0x5562a2112ece] db | mysqld(_Z11mysqld_mainiPPc+0xc71)[0x5562a2114a71] db | /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7fb2de9bb2e1] db | mysqld(_start+0x2a)[0x5562a210aeaa] db | The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains db | information that should help you find out what is causing the crash.ログを見てみるとなにやら恐ろしげなことが書いてあります。
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built or misconfigured. This error can also be caused by malfunctioning hardwar Attempting to collect some information that could help diagnose the problem As this is a crash and something is definitely wrong, the information collection process might fail.どうやらmysqlのバグが原因のようです。なんらかの原因によりクラッシュしたみたいです。
何度、やり直してもこのエラーが出ます。
このコンテナを削除しまったく新しくmysqlのコンテナを作り直してもダメです。とりあえず解決
こちらを参考に対処しました。
https://github.com/laradock/laradock/issues/1173結局mysqlのイメージ、コンテナ、data volumeを削除してから再起動して解決しました。
イメージの削除
docker images
で一覧を取得します。$ docker images REPOSITORY TAG IMAGE ID CREATED mysql 5.7 c4f186b9e038 2 weeks ago 435MB
コンテナを停止させてから
docker rmi (IMAGE ID)
で削除します。$ docker rmi c4f186b9e038
data volumeの削除
data volumeとしてマウントしているフォルダを削除します。docker-compose.ymlのvolumesで指定のファイルになります。
docker ├─mysql │ ├─conf.d │ └─data ←削除立ち上げてみます
$ docker-compose up -d --build自分はこれで無事起動することができました。
- 投稿日:2020-02-18T11:08:47+09:00
【docker】ERROR:OCI runtime create failedが出る。
状況
DockerfileFROM php:7.3-fpm COPY php.ini /usr/local/etc/php/ RUN apt-get update \ && apt-get install -y zlib1g-dev libzip-dev mariadb-client \ && docker-php-ext-install zip pdo_mysql #Composer install RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" RUN php -r "if (hash_file('sha384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" RUN php composer-setup.php RUN php -r "unlink('composer-setup.php');" RUN mv composer.phar /usr/local/bin/composer ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME /composer ENV PATH $PATH:/composer/vendor/bin RUN composer global require "laravel/installer"php:7.3-fpmのDockerfile下のように書き、
docker-compose up -d --build
すると、次のようなエラーが出る。ERROR: for php-fpm Cannot start service php-fpm: OCI runtime create failed: container_linux.go:344: starting container process caused "chdir to cwd (\"/var/www/html\") set in config.json failed: permission denied": unknown ERROR: Encountered errors while bringing up the project.
chdir to cwd (\"/var/www/html\")
などを見るとphp-fpmの作業ディレクトリの問題だろうと思いDockerfileを修正する。DockerfileWORKDIR /var/www今回はアプリを
/var/www
に置いているので、そこを作業ディレクトリに指定してみる。
再びdocker-compose up -d
してみると無事コンテナが起動する。原因
単純にDockerfileに作業ディレクトリの指定がなく、
/var/www/html
となっていたこと。
なぜ/var/www/html
となっていたかはわからない。デフォルトではそうなるのだろうか。
- 投稿日:2020-02-18T09:01:48+09:00
Laravel Graphql Server using Lighthouse-PHP
みなさんこんにちは、最近行方不明になって申し訳ありませんが、仕事で忙しくて、ブログを更新する時間を見つけることができませんでした
Hello everybody, sorry I´ve been missing lately, but I´ve been busy with work, and couldn´t find the time to update the blog
始めましょう
Dockerコンテナを使用してlaravelをインストールする
Install laravel using docker container
Create Laravel Project using Docker
初期移行を実行する
Run Initial Migrations
sudo docker-compose exec app-server php artisan migrateLighthouse PHPをインストールする
Install
lighthouse-php
lighthouse-php
をインストールするdocker run --rm -v $(pwd):/app composer require nuwave/lighthousegraphqlのデフォルトスキーマを公開する
Publish default schema for graphql
sudo docker-compose exec app-server php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider" --tag=schema
app-server
で、docker-composeファイルで使用する名前を忘れずに変更してくださいin
app-server
, remember to change for the name you use on your docker-compose fileGraphql Playgroundをインストールする
次の手順はオプションですが、推奨されますが、graphql-playgroundをインストールします
Next step is optional, but recommended, install the graphql-playground
docker run --rm -v $(pwd):/app composer require mll-lab/laravel-graphql-playground遊び場のURLは
http://localhost/graphql-playground
url for the playground is
http://localhost/graphql-playground
構成
コンテナをもう一度実行し、
docker-compose up --build
graphqlのデフォルト設定をエクスポートします
run the containers once more,
docker-compose up --build
export the graphql default config
docker-compose exec app-server php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider" --tag=config突然変異とクエリ
クエリを実行する前に、データを挿入する必要があります。最初に突然変異を作成します
Before doing a query, we need to insert data, lets first create a mutation
sudo docker-compose exec app-server php artisan lighthouse:mutation createUserこれにより、
app \ graphql \ mutations
フォルダー内にCreateUser.php
が作成されます。簡単なリゾルバを追加しましょう
This will create a
CreateUser.php
inside theapp\graphql\mutations
folderLets add a simple resolver
public function __invoke($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo) { $args["password"] = Hash::make($args["password"]); return User::create($args); }
schema.graphql
ファイル内にルート変更を追加しますAdd the route mutation inside the
schema.graphql
filetype Mutation { createUser(name: String!, email: String!, password: String!): User }これで、不眠症を使用しているので、簡単な突然変異を作成できます。これが私の突然変異の作成方法です
または、
http:// localhost / graphql-playground
のプレイグラウンドを使用できますWith this, you can create a simple mutation, since I´m using insomnia, this is how I create my mutation
or you can use the playground at
http://localhost/graphql-playground
Insomnia POST : http://localhost/graphql Playground : http://localhost/graphql-playground mutation{ createUser(name:"My Name",email:"my@email.com",password:"mypassword"){ id, name, } }200を取得すると、応答がすでにjsonであることがわかります。クエリリクエストを作成してユーザーを確認できます。
Once you get the 200, you can see the response is already a json, we can check the users by going making a query request
POST: http://localhost/graphql Playground : http://localhost/graphql-playground query{ users{ data{ id, name, email } } }
- 投稿日:2020-02-18T09:01:48+09:00
Lighthouse-PHPを使用したLaravel Graphqlサーバー
みなさんこんにちは、最近行方不明になって申し訳ありませんが、仕事で忙しくて、ブログを更新する時間を見つけることができませんでした
Hello everybody, sorry I´ve been missing lately, but I´ve been busy with work, and couldn´t find the time to update the blog
始めましょう
Dockerコンテナを使用してlaravelをインストールする
Install laravel using docker container
Create Laravel Project using Docker
初期移行を実行する
Run Initial Migrations
sudo docker-compose exec app-server php artisan migrateLighthouse PHPをインストールする
Install
lighthouse-php
lighthouse-php
をインストールするdocker run --rm -v $(pwd):/app composer require nuwave/lighthousegraphqlのデフォルトスキーマを公開する
Publish default schema for graphql
sudo docker-compose exec app-server php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider" --tag=schema
app-server
で、docker-composeファイルで使用する名前を忘れずに変更してくださいin
app-server
, remember to change for the name you use on your docker-compose fileGraphql Playgroundをインストールする
次の手順はオプションですが、推奨されますが、graphql-playgroundをインストールします
Next step is optional, but recommended, install the graphql-playground
docker run --rm -v $(pwd):/app composer require mll-lab/laravel-graphql-playground遊び場のURLは
http://localhost/graphql-playground
url for the playground is
http://localhost/graphql-playground
構成
コンテナをもう一度実行し、
docker-compose up --build
graphqlのデフォルト設定をエクスポートします
run the containers once more,
docker-compose up --build
export the graphql default config
docker-compose exec app-server php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider" --tag=config突然変異とクエリ
クエリを実行する前に、データを挿入する必要があります。最初に突然変異を作成します
Before doing a query, we need to insert data, lets first create a mutation
sudo docker-compose exec app-server php artisan lighthouse:mutation createUserこれにより、
app \ graphql \ mutations
フォルダー内にCreateUser.php
が作成されます。簡単なリゾルバを追加しましょう
This will create a
CreateUser.php
inside theapp\graphql\mutations
folderLets add a simple resolver
public function __invoke($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo) { $args["password"] = Hash::make($args["password"]); return User::create($args); }
schema.graphql
ファイル内にルート変更を追加しますAdd the route mutation inside the
schema.graphql
filetype Mutation { createUser(name: String!, email: String!, password: String!): User }これで、不眠症を使用しているので、簡単な突然変異を作成できます。これが私の突然変異の作成方法です
または、
http:// localhost / graphql-playground
のプレイグラウンドを使用できますWith this, you can create a simple mutation, since I´m using insomnia, this is how I create my mutation
or you can use the playground at
http://localhost/graphql-playground
Insomnia POST : http://localhost/graphql Playground : http://localhost/graphql-playground mutation{ createUser(name:"My Name",email:"my@email.com",password:"mypassword"){ id, name, } }200を取得すると、応答がすでにjsonであることがわかります。クエリリクエストを作成してユーザーを確認できます。
Once you get the 200, you can see the response is already a json, we can check the users by going making a query request
POST: http://localhost/graphql Playground : http://localhost/graphql-playground query{ users{ data{ id, name, email } } }
- 投稿日:2020-02-18T01:09:21+09:00
【ハンズオン】Docker+KubernetesでHelmを使ってみよう
本記事ではKubernetesの周辺技術の一つとして使われているHelmを、実際に触って理解をしたい方向けにハンズオンを掲載しています。
やること
- DockerでKubernetes構築(kubernetes-dashboardのデプロイ)
- Helmでnginxのデプロイ
対象者
・Kubernetes、Helmの概要を知りたい方
・概要だけでなくKubernetes、Helmを実際に動かして理解したい方
・Kubernetesはなんとなく分かってきたけど、Helmはまだ触ったことがない方前提(バージョン)
docker desktop 2.2.0.3
Kubernetes v1.15.5
kubectl
$ kubectl version --short --client Client Version: v1.17.1helm
$ helm version version.BuildInfo{Version:"v3.1.0", GitCommit:"b29d20baf09943e134c2fa5e1e1cab3bf93315fa", GitTreeState:"clean", GoVersion:"go1.13.8"}本ハンズオンを行う上での注意事項
本ハンズオンでは、Helm3を利用しています。
Helm2で行った場合、本記事で記載している方法と実行方法が異なることがあるためできる限り上記のバージョンに合わせてハンズオンを実施いただくことを推奨します。Kubernetesを使ってみる
Kubernetesとは、デプロイ、スケーリング、アプリやコンテナの運用自動化を実現するオープンソースのプラットフォームです。
リソースを定義したyaml形式のファイルを利用してアプリやミドルウェアを構築します。
またリソースの使用状態に合わせて安定的にスケーリングさせることが可能です。1.Docker Desktop for Macをインストールする。
https://hub.docker.com/editions/community/docker-ce-desktop-mac
「Get Docker」を押下する。
2.kubernetesを有効にする
kubernetesを有効にする。
Enable Kubernetesにチェックを入れてapplyをクリック
(※kubernetesの起動に少々時間がかかります。)
3.起動確認 context切り替え
「docker-desktop」 が存在することを確認します。
$ kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * docker-desktop docker-desktop docker-desktop次にcontextを切り替えます。
$ kubectl config use-context docker-desktop Switched to context "docker-desktop".4.kubectlコマンドでkubernetes-dashboardのデプロイ
kubectlコマンドでkubernetes-dashboardというアプリケーションをデプロイしてみましょう。
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc5/aio/deploy/recommended.yaml namespace/kubernetes-dashboard created serviceaccount/kubernetes-dashboard created service/kubernetes-dashboard created secret/kubernetes-dashboard-certs created secret/kubernetes-dashboard-csrf created secret/kubernetes-dashboard-key-holder created configmap/kubernetes-dashboard-settings created role.rbac.authorization.k8s.io/kubernetes-dashboard created clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created deployment.apps/kubernetes-dashboard created service/dashboard-metrics-scraper created deployment.apps/dashboard-metrics-scraper created5.起動確認
localhostとKubernetes API Serverの間にプロキシサーバーまたはアプリケーションレベルのゲートウェイを作成して、アプリケーションにアクセスします。
$ kubectl proxy Starting to serve on 127.0.0.1:8001ブラウザから以下のURLでアクセスしてください。
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
※「8001」というポート番号だけは5の手順で行った「127.0.0.1:8001」の8001に合わせてください。仮に「127.0.0.1:8002」だった場合、「http://localhost:8002/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/」 でアクセスを行ってください。6.トークンの取得
ダッシュボード へアクセスするにはアクセストークンを発行する必要があります。
ターミナルを新規ウィンドウで立ち上げて以下のコマンドを実行して取得しましょう。$ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep eks-admin | awk '{print $1}')結果がたくさん出てくるかと思いますが、どこでも良いので「token: 」の値だけまるっとコピーしてください。
7.ダッシュボード へアクセス
「トークン」を選択し、先程の値を貼り付けて「サインイン」を押下してください。
Helmを使ってみる
Kubernetesのパッケージマネージャーおよびアプリケーション管理ツールであり、複数のKubernetesリソースをChartと呼ばれるファイルにし、パッケージ管理することが可能です。シンプルなコマンドで複数回、Kubernetesリソースを展開したい場合や、他のアプリケーションおよびサービスの特定のバージョンを使用して、アプリケーションの依存関係を管理したい時に利用されます。
1.Helmのインストール
Homebrewでインストールします。
$ brew install kubernetes-helmインストールされたか確認しましょう。
$ helm version version.BuildInfo{Version:"v3.1.0", GitCommit:"b29d20baf09943e134c2fa5e1e1cab3bf93315fa", GitTreeState:"clean", GoVersion:"go1.13.8"}念のためhelmのレポジトリを最新化させます。
$ helm repo update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "stable" chart repository ...Successfully got an update from the "bitnami" chart repository Update Complete. ⎈ Happy Helming!⎈2.bitnamiをHelmクライアント環境へ追加する
helmレポジトリにbitnamiを追加します。このようにhelmレポジトリに資材が追加されることにより、yamlファイルを使用せずとも複数回同じリソースを展開することができるようになります。
※bitnamiとは?
BitnamiはWordPressやRedmineなどのウェブアプリケーションをPHPやMySQLなどのミドルウェアとともに一式設定済みでパッケージ化して提供してくれるソリューションです。$ helm repo add bitnami https://charts.bitnami.com/bitnami "bitnami" has been added to your repositories3.新しいリリースの作成とKubernetesにデプロイ
Kubernetesにnginxをデプロイします。
$ helm install nginxserver bitnami/nginx NAME: nginxserver LAST DEPLOYED: Tue Feb 18 00:10:51 2020 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: Get the NGINX URL: NOTE: It may take a few minutes for the LoadBalancer IP to be available. Watch the status with: 'kubectl get svc --namespace default -w nginxserver' export SERVICE_IP=$(kubectl get svc --namespace default nginxserver --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}") echo "NGINX URL: http://$SERVICE_IP/"4.確認
デプロイしたnginxを確認しましょう。
$ kubectl get pods -l app.kubernetes.io/name=nginx NAME READY STATUS RESTARTS AGE nginxserver-7f8f4c554d-xfmzc 1/1 Running 0 5m26s $ kubectl get service nginxserver NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginxserver LoadBalancer 10.104.187.33 localhost 80:30421/TCP,443:31118/TCP 5m45sブラウザで「localhost」と入力して表示が以下のようになっていればデプロイ完了です。
お掃除
最後にデプロイしたリソースを削除しましょう。
$ kubectl delete -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc5/aio/deploy/recommended.yaml $ kubectl delete svc nginxserverもっと実践的にKubernetes周辺技術を学びたい方へ
Amazon EKS Workshopの記載されている手順にしたがってハンズオンすることをお勧めします。
https://eksworkshop.com/上記のハンズオンでは、
- Kubernetes
- Helm
- EKS
- RBAC
- Elasticsearch
- Grafana
など今求められているKubernetesの周辺技術を網羅的に学習できるため大変お勧めです。
時間があればぜひ試してみてください。おまけ
最初に注意事項でも書きましたが、Helm2ハンズオンを行いたい場合は以下の手順を参考ください。※古いバージョンとなるため動作は保証できませんのでご理解ください。
1.Helmのインストール
$ cd ~/downloads $ curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh $ chmod +x get_helm.sh $ ./get_helm.sh2.tillerのインストール
helmコマンドを使用して、tillerをクラスターにインストールします。
これでクラスター内のリソースを管理するためのアクセスが許可されます。
※tillerとは?
Helmでリソースをサーバ側にchartをデプロイした場合、
chartが直接デプロイされるわけでなく、tillerという形でデプロイ先のサーバに置かれる$ helm init --docker-desktop tiller3.Helmレポジトリへの追加
$ helm repo add bitnami https://charts.bitnami.com/bitnami "bitnami" has been added to your repositories4.nginxをインストールする。
ここがhelm3と異なっておりオプション「 --name 」を指定する必要があります。
$ helm install --name mywebserver bitnami/nginx