Study & Practice

北海道札幌市のプログラマによる技術とか雑記のブログ

ドラッカーの「マネジメント」入門|「もし高校野球の女子マネージャーがドラッカーの『マネジメント』を読んだら」を読んでみた

f:id:carametal:20200927214747p:plain

ブログ「最も早くオシャレになる方法KnowerMag」のMBさんが成功の要因としてドラッカーのマネジメントを読み込んで徹底的に実践しているという話をしていました。マネジメントは組織経営のあり方についてまとめられている本ですが、MBさんの話を聞いていると自分自身をキャリアを形成することにもとても良い効果をもたらす模様。

読んでみたいと思ったものの、分厚く内容も非常に難解な本らしいので、まずはわかりやすく読みやすい本から始めるということで約10年前に流行った「もし高校野球の女子マネージャーがドラッカーの『マネジメント』を読んだら」、通称「もしドラ」を読んでみることにしました。

敏腕マネージャーと野球部の仲間たちが甲子園を目指して奮闘する青春小説。高校野球の女子マネージャーのみなみちゃんは、マネージャーの仕事のために、ドラッカーの『マネジメント』を間違って買ってしまいます。はじめは難しくて後悔するのですが、しだいに野球部のマネジメントにも生かせることに気付きます。これまでのドラッカー読者だけでなく、高校生や大学生、そして若手ビジネスパーソンなど多くの人に読んでほしい一冊。

出版元であるダイヤモンド社さんより引用

ドラッカーのマネジメントの内容を著者の岩崎夏海さんが非常に重要視しているもののみを厳選して引用しながら、ストーリーに絡めて読みやすく書いているという印象です。まだ本元のマネジメントを読んでいないので、実際にどの程度わかりやすくなっているかなどはわかりませんが、マネジメントはAmazonのレビューなどでも非常に難解だというコメントが多いのでもしドラはかなり読みやすくなっているのだと思います。本記事では読んでいて重要だと感じたところをまとめていきます。

マネージャーの資質

本書で一番に解説されていたの「マネージャーの資質」についてでした。

マネジャーの仕事は、体系的な分析の対象となる。マネジャーにできなければならないことはそのほとんどが教わらなくても学ぶことができる。しかし、学ぶことのできない資質、後天的に獲得することのできない資質、始めから身に着けていなければならない資質が、一つだけある。才能ではない。真摯さである。

真摯さと一言でいっても本書から読み解けるのは顧客のことを考えるというような単純なことではなく、顧客に価値を提供したうえで働いている人自身も目標を叶えられる。そんなWin-Winの状態を常に目指し続けるというようなレベルで求められます。この辺は7つの習慣の公的成功や、人格主義に通じるところがあります。

本書の著者である岩崎夏海さんはこの「真摯さ」をかなり重要視しているらしく、本書のド頭に出てくることに加えストーリーの終盤でも「真摯さ」について語る重要なシーンがあったり、本編後の著者への解説インタビューでも「真摯さ」について結構な分量で語られています。「真摯さ」はマネジメントを読む際のキーポイントになりそうです。

組織の定義づけ

本書で「真摯さ」の次に語られていたのが組織の定義付けについてでした。それは「われわれの事業は何か?」という問いで語られます。

野球部なのだから野球をすることがわれわれの事業になりそうですがドラッカーはこう語っているようです。

自らの事業は何かを知ることほど簡単でわかりきったことはないと思われるかもしれない。鉄鋼会社は鉄を作り、鉄道会社は貨物と乗客を運び、保険会社は火災の危険を引き受け、銀行は金を貸す。しかし実際には、「われわれの事業は何か」との問いは、ほとんどの場合、答えることが難しい問題である。わかりきったことが正しいことはほとんどない。

これに対してドラッカーは「われわれの事業はなにか」という問いの答えを導き出すには「顧客」が唯一の出発点だと語ります。

つまり、「顧客がわれわれに求めるものはなにか」ということにつながります。そしてここでもう一つ「顧客とはだれか」という問いが出てきます。

マネジメントではキャデラックが例として挙げられているらしく、本書でも以下のように引用されています。

一九三〇年代の大恐慌のころ、修理工からスタートしてキャデラック事業部の経営を任されるにいたったドイツ生まれのニコラス・ドレイシュタットは「われわれの競争相手はダイヤモンドやミンクのコートだ。顧客が購入するのは、輸送手段ではなくステータスだ」と言った。この答えが破産寸前のキャデラックを救った。わずか二、三年のうちに、あの大恐慌時にもかかわらず、キャデラックは成長事業へと変身した。

キャデラックは「顧客」を単に車が欲しい人ではなく「ダイヤモンドやミンクのコートを買う消費者」と定義し、性能やコストパフォーマンスではなく、高級でかっこいい「ステータス」となる車を顧客に届けることを「われわれの事業」として定義し、成長することができたということです。

私は現在、ソフトウェア開発を生業とする企業に勤めていますが、この「われわれの事業は何か」、「顧客とはだれか」を答えるのは非常に難しいと思いました。単に「ソフトウェアを開発すること」でも、「ソフトウェアを作ってほしい人」でもないわけです。しかも、客先常駐を長らく続けてきたこともあり、企業としての技術的な強みがなく、顧客も多岐にわたるからです。また、私個人としても「なんのためにソフトウェアを開発しているのか」と深堀りしてみると全く答えが出せません。この二つの問いについては、仮設を立てて試行錯誤しながら答えを見つけていかないといけないのかなと思いました。

マーケティング

そして顧客の定義付けができれば次はキャデラックの例で言う「ステータス」というキーワードにたどり着かなければいけません。これには

「われわれは何を売りたいか」ではなく、「顧客は何を買いたいか」を問う。

と引用されている。

そしてその時に必要になるのが「現実・欲求・価値」です。これはそれぞれ、顧客が置かれている状況、顧客が求めるもの、顧客が価値を見出すもののことです。

これは現実と欲求を調査して顧客が価値を見出すものを分析するという手順になるのかと思います。T型フォードを作ったヘンリー・フォードの「もし顧客に、彼らの望むものを聞いていたら、彼らは『もっと速い馬が欲しい』と答えていただろう。」という言葉は有名ですが、顧客が求めているのは本当に顧客が欲しいものとは限りらないからです。この辺りも仮設と検証を繰り返して顧客が真に見出すものを作り出していく必要があるのだと思います。

イノベーション

マーケティングは非常に重要であるがマーケティングだけでは大きな成果は出せない。と本書では語られており、「マネジメント」より以下のように引用されています。

マーケティングだけでは企業としての成功はない。性的な経済には、企業は存在しえない。そこに存在しうるものは、手数料をもらうだけのブローカーか、何の価値も生まない投機家である。企業が存在しうるのは、成長する経済のみである。あるいは少なくとも、変化を当然とする経済においてのみである。そして企業こそ、この成長と変化のための機関である。したがって企業の第二の機能は、イノベーションすなわち新しい満足を生み出すことである。経済的な財とサービスを供給するだけでなく、よりよく、より経済的な財とサービスを供給しなければならない。企業そのものは、より大きくなる必要はないが、常によりよくなければならない。

そしてイノベーションを起こす手法として以下のように引用されています。

イノベーションの戦略の一歩は、古いもの、死につつあるもの、陳腐化したものを計画的かつ体系的に捨てることである。イノベーションを行う組織は、昨日を守るために時間と資源を使わない。昨日を捨ててこそ、資源、特に人材という貴重な資源を新しいもののために解放できる。

つまりイノベーションを起こすにはまず初めに何かを「捨てる」ことが必要であるということです。昨今ではイノベーションは科学や技術によって起こすものと捉えられがちですが、ドラッカーの主張はそれだけではないということでしょう。

本書では「送りバント」と「ボール球を打たせる投球術」を捨てる手法を取っていた。程度の差はあるがどちらもメジャーリーグでも戦略としてあまり重要視されなくなってきている。いまだ古いセオリーに則っている高校野球に「送りバント」と「ボール球を打たせる投球術」を捨てた戦法で挑戦し結果を残すことで、高校野球界そのものにイノベーションを巻き起こそうということです。

私はイノベーションというと今まで新しいものを取り入れるという方向で物事を考えがちでしたが、捨てるという方向がイノベーションの一歩目というのは納得ができました。新しいことをする時間を作る場合でも、今まで何かをしていた時間を捨てなければいけません。日常的には無意識のうちにこういう取捨選択をしているのだと思いますが、意識的に捨てること特に「計画的かつ体系的に」というところが重要なのだと思います。

成果について

成果とは何かを理解しなければならない。成果とは百発百中のことではない。百発百中は曲芸である。成果とは長期のものである。すなわち、まちがいや失敗をしないものを信用してはならないということである。それは、見せかけか、無難なこと、下らないことにしか手をつけないものである。成果とは打率である。弱みがないことを評価してはならない。そのようなことでは、意欲を失わせ、士気を損なう。人は、優れているほど多くのまちがいをおかす。優れているほど新しいことを試みる。

「成果とは打率である。」と「優れているほど多くのまちがいをおかす」というのは矛盾しているような気がしますが、打席に立つ回数が多いからまちがいが増えるだけで打率は低くてはいけないということなのか。

それにしても「まちがいや失敗をしないものを信用してはならない」というのは強烈なメッセージかと思います。現代の日本企業は成功することよりも失敗しないことが評価されるという話を至る所で聞きますが、そのほとんどは信用してはいけない、成果を出していないということになります。これは組織作りにおいてかなり重要なポイントだと思います。しかし、個人においても失敗をするかもしれない行動を増やすというのはやはり成果を出すうえで避けては通れない道なのでしょう。

また、成果については以下のような引用もありました。

成果よりも努力が重要であり、職人的な技能それ自体が目的であるかのごとき錯覚を生んではならない。仕事のためではなく成果のために働き、贅肉ではなく力をつけ、過去ではなく未来のために働く能力と意欲を生み出さなければならない

努力してるから良い。努力していないから悪い。ではなく成果に価値を置かなければならない。そして職人的な技能を持っていることよりも実際に生み出す成果が重要である。これは我々のような技術者として生計を立てている人たちには少し耳が痛い部分であるかもしれません。いくら技術的に優れていてメンテナンス性やパフォーマンスに優れたシステムを開発しても成果が生まれなければならない。非常にシビアですが、事業においては最も重要なことだと思いました。

まとめ

「マネジメント」をストーリーに絡めて読みやすくした内容ではありますが、本書に書かれている内容を理解し自分の環境で実践することでドラッカーの恩恵を十分に受けられると感じました。

私はビジネス書として読んでいたのであまり気になりませんでしたが、小説として特別面白いものだとは感じませんでした。とはいえ、夏の西東京大会決勝戦のラストシーンは私自身も高校時代に野球部だったこともあって高揚感を覚えました。その点で言うとそこそこ楽しめる本だともいえると思います。

次はドラッカーの「マネジメント」を読んでみたいと思います。

EC2インスタンスにApacheのサーバーを立ててのテストページを表示する

今まで何回もやったことあるけど毎回忘れて調べてるので備忘録として手順を残す

VPCの作成

マネジメントコンソール上部のサービスタブからVPCを選択してVPC管理画面で「VPCの作成」ボタンを押す

VPCの設定では名前とCIDRブロックを設定する
今回は名前をtrial-vpc、CIDRブロックをデフォルトの10.0.0.0/24を選択

作成ボタンを押してVPCの作成は完了

サブネットの作成

VPC管理画面の左側メニューから「サブネット」を選択し、上部の「サブネットの作成」ボタンを押す

サブネットの作成画面では名前、VPCアベイラビリティーゾーン、CIDR ブロックを以下に設定する

名前 trial-subnet
VPC trial-vpc
アベイラビリティーゾーン ap-northeast-1a
CIDRブロック 10.0.0.0/24

VPCは先ほど作ったVPC選択する。本記事ではtrial-vpc

アベイラビリティーゾーンはどれを選んでも問題ない。本記事ではap-northeast-1aを選択

CIDRブロックはVPC内でネットワークを分ける場合は細かく設定する必要があるが
今回は分けないで行うためVPCと同じ10.0.0.0/24を設定

作成ボタンを押してサブネットの作成は完了

インターネットゲートウェイの作成

画面左側のメニューから「インターネットゲートウェイ」を選択し、「インターネットゲートウェイの作成」ボタンを押す

名前タグに「trial-ig」を設定して「インターネットゲートウェイの作成」ボタンを押す

インターネットゲートウェイの一覧画面から「trial-ig」の行を選択し、「アクション」、「VPCにアタッチ」を選択

「使用可能なVPC」の欄で[trial-vpc]を選択して「インターネットゲートウェイのアタッチ」ボタンをおして完了

ルートテーブルの作成

画面左側のメニューから「ルートテーブル」を選択し「ルートテーブルの作成」ボタンを押す

ルートテーブルの作成画面で名前タグを「trial-rt」、VPCを「trial-vpc」を選択して「作成」ボタンを押す

ルートテーブル一覧から[trial-rt]の行を選択して、下部の「ルート」タブを選択し「ルートの編集」ボタンを押す

「ルートの追加ボタン」を押し、送信先を「0.0.0.0/0」、ターゲットを「Internet Gateway」の「trial-ig」を設定して「ルートの保存」ボタンを押す

ルートテーブル一覧から[trial-rt]の行を選択して、下部の「サブネットの関連付け」タブを選択し「サブネットの関連付けの編集」ボタンを押す

サブネット一覧から「trial-subnet」を選択して「保存」ボタンを押して完了

EC2インスタンスの作成

画面上部のサービスタブからEC2を選択してEC2の管理画面を開く。
次に画面左側のメニューから「インスタンス」を選択し、「インスタンスの作成」ボタンを押す

ステップ 1: Amazon マシンイメージ (AMI)では「Amazon Linux 2 AMI (HVM), SSD Volume Type」を選択
ステップ 2: インスタンスタイプの選択では「t2.micro」を選択し次のステップへ
ステップ 3: インスタンスの詳細の設定では以下の設定をし次のステップへ

ネットワーク trial-vpc
サブネット trial-subnet
自動割り当てパブリックIP 有効

そのほかは任意の設定で問題ない。本記事ではデフォルトのまま進める。

ステップ 4: ストレージの追加では必要な分のストレージを設定し次のステップへ。本記事ではデフォルトのままとした
ステップ 5: タグの追加では必要に応じてタグを設定して次のステップへ。本記事ではタグを1つ追加してキーを「Name」、値を「trial-ec2」のみを設定
ステップ 6: セキュリティグループの設定では新しいセキュリティグループを作成するを選択しセキュリティグループ名を「trial-ec2-sg」として以下を設定して「確認と作成」ボタンを押す

タイプ ソース
SSH マイIP
HTTP カスタム(0.0.0.0/0, ::/0)

ステップ 7: インスタンス作成の確認では入力に間違いがないかを確認し、「起動」ボタンを押す

上記を行うと「既存のキーペアを選択するか、新しいキーペアを作成します。」というダイアログが出てくる

キーペアを使いまわすことは推奨されていないので「新らしいキーペアの作成」を選択し、キーペア名を「trial-ec2-key」と設定して「キーペアのダウンロード」を押す
キーペアのダウンロードが完了したら「インスタンスの作成」ボタンを押す

インスタンス画面に戻りNameがtrial-ec2となっている行のインスタンスの状態が「running」になれば問題なくEC2インスタンスが起動している。
インスタンスの状態が「pending」になっている場合は数十秒から数分程度までば「running」に遷移するはず

EC2インスタンスApacheをインストールする

インスタンス画面で「trial-ec2」の行を選択して出てくる画面下部の「説明」欄からIPv4 パブリック IPをクリップボードにコピーする

ターミナルソフトを開き(本記事ではWindowsコマンドプロンプト)キーペアのあるディレクトリに移動したら下記コマンドを実行する

ssh -i trial-ec2-key.pem ec2-user@コピーしたIPアドレス

キーペア名(trial-ec2-key.pem)はキーペアのダウンロード時に設定したキーペア名を入力する
コピーしたIPアドレスの部分は本記事のようにインスタンス作成のステップ 3で自動割り当てパブリックIPを有効にした場合、EC2インスタンスを起動するごとにインスタンスIPアドレスが変わるので注意

初回ログイン時は下記のようなメッセージが出てくるがyesで問題ない

The authenticity of host 'IPアドレス (IPアドレス)' can't be established.
ECDSA key fingerprint is SHA256:Je2wxOb+fwZosDX/qZKL1AjOojfiwedHag2M/5mRe9U.
Are you sure you want to continue connecting (yes/no)?

ログインできたら下記のコマンドでApacheをインストールしてApacheを起動する

sudo yum install -y httpd
sudo systemctl status httpd

ブラウザからEC2にアクセスする

sshで繋いだのと同じIPアドレスにブラウザからアクセスしたらApacheのテストページが表示されるはず

以上で「EC2インスタンスApacheのサーバーを立ててのテストページを表示する」が完了

composer install で「Your requirements could not be resolved to an installable set of packages.」のエラーになる件

本記事の環境は以下

  • Windows10 Home
  • WSL2 Ubuntu18.04
php artisan serve

を実行すると

PHP Warning:  require(/var/www/html/pf-blog/vendor/autoload.php): failed to open stream: No such file or directory in /var/www/html/pf-blog/artisan on line 18
PHP Fatal error:  require(): Failed opening required '/var/www/html/pf-blog/vendor/autoload.php' (include_path='.:/usr/share/php') in /var/www/html/pf-blog/artisan on line 18

っていうエラーを吐いてしまう

調べてみると

composer install

で解決するらしいのだがそもそもこれがうまくいかない
最初は気づかなかったのだがログをよく見てみると

Your requirements could not be resolved to an installable set of packages.

というエラーで止まってしまっているらしい
ログを見てみるとどうやらmbstringとdomが入っていないようだ

sudo apt install php7.2-mbstring php7.2-dom

そして今度は以下のようなエラーが

Failed to download league/flysystem from dist: The zip extension and unzip command are both missing, skipping.
Your command-line PHP is using multiple ini files. Run `php --ini` to show them.
    Now trying to download from source

どうやらzipとunzipコマンドが入っていないらしい

sudo apt install -y zip unzip

もう一度

composer intall

すると

Package manifest generated successfully.
46 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

どうやら解決したようだ

php artisan serve

してhttp://127.0.0.1:8000にアクセスしてみると

f:id:carametal:20200730230739p:plain

無事テストページが表示された

AWS管理インターフェースについて調べた

5月から客先常駐ではなく在宅による受託開発になり、記念すべき一発目の仕事でクラウドを利用するとのことなので改めてAWSを学び始めた。

ひとまずAWS クラウドラクティショナーの無料トレーニング動画を見始めたのだが、気になったことがあったので調べてみた。

AWS管理インターフェース(AWS Management Interfaces)とは

AWSリソースを作成、及び管理する方法の総称で以下の3つが存在する(2020年7月10日時点)

インターフェースはこのうちの1つに絞る必要はなく、組み合わせて使うことができる
※複数のインターフェースをまたいでAWSを使用した時、一方での操作が反映されるまで時間がかかることがあるので注意


AWSクラウドラクティショナー無料トレーニング動画のかなり序盤ににAWS管理インターフェースの名前が出てくるのだが、ググっても全然出てこない。この呼称はあまり使われていないらしい

今まで個人的にEC2やS3を遊びで使っていたが、AWSマネジメントコンソールとAWSコマンドラインインターフェースしか知らなかった。

それぞれの特徴

AWSマネジメントコンソール(AWS Management Console)について
  • AWSの様々なサービスや機能をGUIを通して使用することができる
  • AndroidiOSで操作できるアプリも用意されている
  • アラームを設定してタスクを実行させることができる
AWSコマンドラインインターフェース(AWS Command Line Interface)について
AWS SDK(AWS Software Development Kit)について
  • 既存のアプリケーションでAWSを使用できる
  • システムをデプロイしてモニタリングするようなアプリケーションを1から作成できる
  • AWS CLIと組み合わせることでAWSをカスタマイズしたツールを作成できる


以上、簡単にだがAWS管理インターフェースをまとめてみた。

まだまだAWS自体を使えているわけではないので基本的な知識や使い方を学んでいきたいところではあるが、そのうちAWS SDKを使ったコアな開発というのもやってみたい。

Laravle+ApacheでDocument Root以外にアクセスすると404エラーになる際の対処法

こちらの記事にて解決しました

teratail.com

以下のコマンドでmod_rewriteを有効化するだけでDocument Root以外も表示されるようになった

cat /etc/apache2/mods-available/rewrite.load
sudo a2enmod rewrite

しかし、さっぱり何をしているのかわからなかったので少し深堀してみる

ちなみに公式ドキュメントにmod_rewiteを有効にしろと書いてあった
https://readouble.com/laravel/6.x/ja/installation.html?header=Apache

mod_rewriteとは

まず、mod_rewriteはサーバーへのリクエストに応じてURLを書き換え、リダイレクトを行ってくれる

といってもよくわからなかったのでmod_rewriteの設定ファイルである.htaccessを確認する
mod_rewriteはlaravelのプロジェクトであればpublicディレクトリの直下にある

僕の場合は以下のような設定になっていた

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>


正直よくわかっていないのだが今回重要なのが

# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

この部分

RewriteRuleは文字通りRewriteのルールを定義していて
RewriteCondはそのルールを適用する条件を設定している

RewriteCondの行の-dと-fはそれぞれディレクトリとファイルを表しており
RewriteCondが複数並んだ際はAnd条件となる

REQUEST_FILENAMEはファイルシステムにおけるフルパスのことなので

今回の場合、リクエストが指すパスの先がディレクトリでもなくファイルでもないときRerwiteを行うという条件になる

そしてRewriteRule

RewriteRuleはでは^という記号が使われている

^は正規表現において行頭を指す。
今回のRewriteRuleでいうと行頭をすべてindex.phpに置き換えるということになる

今回の設定値だと「/test」へのアクセスは「index.php/test」に変換しているということになる
この感じだと最初の/がなくなってしまっているがそこは内部的に変換しているのだと思う

ためしにmod_rewriteを無効にして「/index.php/test」にアクセスしてみるとちゃんとページが表示された
mod_rewriteを無効にするコマンドは以下

sudo a2dismod rewrite

a2enmonはenableで有効化
a2dismodはdisableで無効化ということらしい

ネット上によく見るものでは「RewriteRule ^ /index.php [L]」や「RewriteRule . /index.php [L]」ばかりなので
記載としては「RewriteRule ^ /index.php [L]」が正しいんじゃないかなと思っている

こうして振り返ってみると大した内容ではなかったが答えにたどり着くまでにも、何をしているのかを理解するのにも時間がかかってしまったが
こうして1歩ずつ成長していきたい

参考記事
html-coding.co.jphttps://murashun.jp/blog/20190215-01.html
https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
基本的な正規表現一覧 | murashun.jp

AWS EC2にLarabel + MySQL + Apache + Vue.jsの環境を一歩ずつ作ってみる

EC2でWebアプリの公開するための土台作りとして環境構築を行っていく
codeDeployでの自動化とかも調べてみたけどとりあえず一番シンプルな方法か始めることにしました

以下、EC2インスタンス内での操作

すべて下記のAmazon Linux上で実施する

$ cat /etc/system-release
Amazon Linux AMI release 2018.03

まずはApacheのインストールと起動

sudo yum install -y httpd24
sudo service httpd start

Apache自動起動設定も行っていく

sudo chkconfig httpd on

ここで一旦Apacheが動いているか動作確認

http://EC2インスタンスIPアドレス/ にアクセスして以下が表示されたらOK

Amazon Linux Test Page
Amazon Linux Test Page

次はドキュメントルートにファイルを配置して正常に表示されるかの確認

ドキュメントルートのデフォルトディレクトリに移動

cd /var/www/html/

index.htmlを以下の内容で作成

<p>Hello, World!!</p>

再度 http://EC2インスタンスIPアドレス/ にアクセスしてHello,World!!が表示されたらOK

次はPHPのインストールを行っていく

sudo yum install -y php72

下記の内容でindex.phpをindex.htmlと同じディレクトリに配置

<?php
phpinfo();

このままだと優先順位がindex.html > index.phpなのでindex.htmlが表示されてしまうので
Apacheの設定を変えていく

まずはバックアップを取る

sudo cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bak

次にvimhttpd.confを開いて

sudo vim /etc/httpd/conf/httpd.conf

DirecotryIndexをindex.htmlから

<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>

index.phpに変更

<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>

httpd.confはApacheの起動時にしか読み込まれないのでApacheを再起動

sudo service httpd restart

http://EC2インスタンスIPアドレス/ にアクセスして以下が表示されたらOK

result phpinfo();
phpinfo

次はMySQLのインストールと起動

sudo yum install mysql57-server -y
sudo service mysqld start

MySQLに入って

mysql

MySQLのユーザー作成と権限追加

create user ユーザー名 identified by 'パスワード';
grant all privileges on *.* to 'ユーザー名'@'%';

データベースとテーブルの作成
テーブルはテスト用のユーザーテーブルとする

create database データベース名;
create table test_user (id int auto_increment, name varchar(20));

あとで使うためにレコードを追加しておく

insert into test_user (name) values ('任意のユーザー名');
insert into test_user (name) values ('任意のユーザー名');
insert into test_user (name) values ('任意のユーザー名');

mysqlから出る

exit


PHPからMySQLを使うのに必要なものをインストール

sudo yum install php72-pdo php72-mysqlnd php72-mbstring -y

上記のインストールを有効にするためにApacheを再起動

sudo service httpd restart

以下の内容でindex.phpを更新

<?php

$dsn = 'mysql:host=localhost;dbname=データベース名;charset=utf8';
$user_name = ユーザーネーム;
$password = パスワード;

try {
        $pdo = new PDO($dsn, $user_name, $password);
        echo 'Success';
} catch (Exception $e) {
        echo 'Error.';
        exit($e->getMessage());
}

SUCCESSと表示されればOK

次は実際にDBから値を取得する

index.phpを以下に更新

<?php

$dsn = 'mysql:host=localhost;dbname=backlog_app;charset=utf8';
$user_name = ユーザー名;
$password = パスワード;

try {
        $pdo = new PDO($dsn, $user_name, $password);
	$test_users = $pdo->query("select * from test_user");
	foreach($test_users as $user) {
		echo "$user[name]<br>";
	}
} catch (Exception $e) {
        echo 'Error.';
        exit($e->getMessage());
}

http://EC2インスタンスIPアドレス/ にアクセスして先程DBに登録して任意のユーザー名
が表示されればOK

これでMySQLのセットアップは終了

これからLaravelのセットアップを行う

まずはLaravelのパッケージマネージャーであるcomposerをインストールする

ホームに戻って

cd /home/ec2-user

公式の手順https://getcomposer.org/download/にしたがって行う

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

その後ファイル名の変更とデフォルトでPATHの通ったディレクトリに移動する

mv composer.phar /usr/local/bin/composer

以下のコマンドで

composer -V

以下が表示されたらOK(2020/3/10時点でのバージョン)

Composer version 1.9.3 2020-02-04 12:58:49


Composerがinstallできたら/var/www/html配下でLaravleプロジェクトの作成

composer create-project --prefer-dist laravel/laravel .

その後以下のコマンドで依存ライブラリのインストールとアップデート

composer install
composer update


そして/etc/httpd/conf/httpd.confのドキュメントルートを
/var/www/html/から/var/www/html/publicに修正

DocumentRoot "/var/www/html/public"

これでhttp://EC2インスタンスIPアドレス/にアクセスしたらLaravelのテストーページが表示されるはず

Laravel Test Page
Laravel Test Page

これで最低限のLaravelの環境構築が完了

次はVue.jsのセットアップ
Lravelは公式でVue.jsをサポートしているので非常に簡単

laravel/uiパッケージをインストールして
Vue.js用にファイルを生成

composer require laravel/ui
php artisan ui vue

そしてnode.js

レポジトリの取得してインストールして最新に更新

curl -sL https://rpm.nodesource.com/setup_13.x | sudo bash -
sudo yum install -y nodejs
sudo npm update -g npm

そして/var/www/html配下で

npm install && npm run dev

して依存パッケージをインストール、ビルドする

するとresources/js/components配下にExampleComponent.vueが生成させているのでこれを利用する

/var/www/html/resources/views配下にexample.blade.phpというファイル名で
以下のファイルを作る

<div id="app">
        <example-component></example-component>
</div>
<script src="{{asset('js/app.js')}}"></script>

/var/www/laravel/routes配下のweb.php

Route::get('/', function () {
    return view('welcome');
});

部分を

Route::get('/', function () {
    return view('example');
});

に変更する

これでhttp://EC2インスタンスIPアドレス/にアクセスすると

example.blade.php
example.blade.php

こう表示されるはず

最後にLaravelでMySQLの設定をして簡単なリスト表示をする

まずはAPIの呼べているかの確認

routes/web.phpを以下に変更してテスト用のAPI作成

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('sample');
});

Route::get('/test', function() {
    return 'This is test.';
});

次にExampleComponent.vueを以下に変更

<template>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">Example Component</div>

                    <div>{{ testData }}</div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                testData: '',
            }
        },
        mounted() {
            this.updateTableData()
        },
        methods: {
            updateTableData() {
                axios
                    .get('/test')
                    .then(response => this.testData = response.data)
            },
        }
    }
</script>

これで準備完了

http://EC2インスタンスIPアドレス/にアクセスする

f:id:carametal:20200317210013p:plain
Index Page

これが表示されるはず

次はweb.phpを以下に変更する

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('sample');
});

Route::get('/test', 'TestController@index');

そして/var/www/html/app/Http/Controllers配下にTestController.phpを以下の内容で作成

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Test;

class TestController extends Controller
{
    public function index()
    {
        return 'This is TestController.';
    }
}

http://EC2インスタンスIPアドレス/にアクセスすると以下が表示される

f:id:carametal:20200317210013p:plain
Index Page TestController

次は/var/www/html/.env以下の部分を

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

以下に変更(各項目はMySQLに設定済みの項目)

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=データベース名
DB_USERNAME=ユーザー名
DB_PASSWORD=パスワード

そしてTestController.phpを以下に変更

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;

class TestController extends Controller
{
    public function index()
    {
        $testUsers = DB::select('select * from test_user;');
        return $testUsers;
    }
}

ExampleComponent.vueを以下に変更

<template>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">Example Component</div>

                    <div v-for='user in testUsers'
                        :key='user.id'
                    >
                        {{ user.id }}: {{ user.name}}
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                testUsers: '',
            }
        },
        mounted() {
            this.updateTableData()
        },
        methods: {
            updateTableData() {
                axios
                    .get('/test')
                    .then(response => this.testUsers = response.data)
            },
        }
    }
</script>

http://EC2インスタンスIPアドレス/にアクセスすると

f:id:carametal:20200317212202p:plain
Index Page TestUsers

このような表示になるはず

これで環境構築終了

まとめ

これでタイトルの「AWS EC2にLarabel + MySQL + Apache + Vue.jsの環境を一歩ずつ作ってみる」を終えることができた

今回実際に環境を作ってみたけどまだまだ知識が足りていないと改めて実感した。
以前大ハマリしたおかげかVue.jsの導入はスムーズだったがLaravelとApacheは今回の記事に載せてないエラーに
たくさん遭遇した。そのたびにエラーメッセージを検索をかけては解決策を調べて世界のどこかにいる人たちに力を借りて
解決した。

まだまだエントリの書き方もまとまってないしブログを書く習慣もないけど一つずつエントリを増やしてこのブログと一緒に成長していけたらいいなと思う。

Dockerを使ってPHP7+Apache+MySQLの開発環境を作る

今回は前回に引き続き実技試験の予習として開発環境を作っていく

前回はPHP7+Apacheまで作ったのでMySQLを含めた環境を作っていく
carametal.hatenablog.com

こちらの記事を参考にさせていただきました。

qiita.com

こちらの記事ではMySQLクライアントにphpMyAdminを使っていますが
ひとまず環境構築のみの目的なのでphpMyAdminは扱いません。

前回の記事ではDockerfileを用いていましたが今回はdocker-composeで環境を作っていきます。

手始めにdocker-compose.ymlを作成

version: '3'

services:
  php:
    image: php:7.2-apache
    volumes:
      - ./html:/var/www/html
    ports:
      - 8000:80
    container_name: php7.2-trial2
  mysql:
    image: mysql:5.7
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=test
      - MYSQL_USER=test
      - MYSQL_PASSWORD=test
    container_name: mysql5.7-trial2
    

ほとんど参考にさせていただいた記事からの流用ですが

phpのimageは前回記事同様にphp:7.2-apacheを使用
volumes項目でカレントディレクトリにあるhtmlディレクトリを
コンテナ内の/var/www/htmlにマウント
公開ポートは8000番、ポートフォワーディング先は80番に指定
ビルド後のコンテナ名にphp7.2-trial2を指定

mysqlのimageにはmysql5.7を使用
volumes項目で./mysqlを/var/lib/mysqlにマウント(ここはよくわかっていないけどディレクトリがなくてもdocker-compose up したときに自動的に作られるみたい※要調査)
environment項目では環境変数を設定し
コンテナ名にmysql5.7-trial2を指定

docker-compose.ymlはこれで完了

htmlディレクトリにはindex.phpを配置する

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>php7.2-apache</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<?php
    echo 'Hello world.';
?>
</body>
</html>mysql5.7-trial2

index.phpは一旦echoでHello world.するようにする(あとでDBのデータを取得するように変更します)

最後にphp.ini
phpの設定ファイルなわけですが今回はお試し環境構築なのでこちらから拝借させていただきました
qiita.com

以上で必要なファイルはそろいました

docker-compose up -d 

でコンテナの作成&実行する

docker container ps

を実行してphp7.2-trial2とmysql5.7-trial2の2つのコンテナが起動していれば成功

http://localhost:8000/にアクセスしてHello worldと表示されるはず

次はMySQLにアクセスしてDBから取得したtextを表示してみる

まずはmysql5.7-trial2コンテナに入って

docker exec -it mysql5.7-trial2 bash

MySQLにログイン

mysql -uroot -proot
  • uはログインユーザの指定
  • pはパスワードの指定

この2つはdocker-composeで指定したものを使用する

mysqlにログインできたら

show databases;

とするとMYSQL_DATABASEにtestと設定しているので一覧にtestというDBがあるはず

use test;
show tables;

当然まだtableはまだないはずなのでEmpty set (~~~ sec)と表示されるはず

tableを作ってテストデータを作る

create table test (id int not null auto_increment, text char(30), primary key (id));
insert into test (text) values ('first test.');
insert into test (text) values ('second test.');
insert into test (text) values ('second test.');
select * from test;

+----+--------------+
| id | text         |
+----+--------------+
|  1 | first test.  |
|  2 | second test. |
|  3 | third test.  |
+----+--------------+

これが出たら準備は完了

index.phpを修正する

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>php7.2-apache</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<?php
try {
    $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
    foreach($dbh->query('select * from test') as $row) {
        echo $row['text'] . '<br>';
    }
    $dbh = null;
} catch (PDOException $e) {
    echo $e;
    die();
}
$dbh = null;
?>
</body>
</html>

これでtestデータベースのtestテーブルのデータが表示される

と思ったが

Fatal error: Uncaught PDOException: could not find driver in /var/www/html/index.php:11

というエラーが

どうやらPDO(PHP Data Object)にMySQL用のドライバーがないというエラーの模様

今回の対応として公式のphp:7.2-apacheではなくドライバー入りのimageを作って
そっちを使うようにする

まず、以下のようなDockerfileを作る

FROM php:7.2-apache
RUN docker-php-ext-install pdo_mysql

そしてこれをbuildする

docker image build -t php7.2-apache-trial2 .
||>

このとき、php.iniやhtmlディレクトリのあるディレクトリでビルドすると下記のようなエラーが出ることがあるので注意

>||
error checking context: 'no permission to read from '/home/carametal/dev/docker/soltwarks/trial2/mysql/ca-key.pem''.

これはカレントディレクトリ配下をDockerfile内の命令からアクセス可能な範囲として指定されるため発生するらしい(以下の記事参照)
developer-collaboration.com

imageのビルドができたらdocker-compose.ymlを修正

version: '3'

services:
  php:
    image: php7.2-apache-trial2
    volumes:
      - ./html:/var/www/html
    ports:
      - 8000:80
    container_name: php7.2-trial2

  mysql:
    image: mysql:5.7
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=test
      - MYSQL_USER=test
      - MYSQL_PASSWORD=test
    container_name: mysql5.7-trial2

phpの指定imageをphp:7.2-apacheから今回新しくbuildしたphp7.2-apache-trial2に変更するだけ

さぁこれでDBから取得したデータが表示されるはず

PDOException: could not find driver in /var/www/html/index.php:12 Stack trace: #0 /var/www/html/index.php(12): PDO->__construct('mysql:host=mysq...', 'root', 'root') #1 {main}

と思いきやこのようなエラーメッセージが出てきてしまった

これは正直めちゃくちゃハマったんだけどこちらの記事のおかげで助かりました
qiita.com
内部的にどんな処理になってるのかわからないんだけど
PDOのコンストラクタに渡すhostはlocalhostではだめで

<?php
// NG
$dbh = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
//OK
$dbh = new PDO('mysql:host=mysql5.7-trial2;dbname=test', 'root', 'root');

docker-compose.ymlのcontainer_nameで指定しているコンテナ名にしなければならないらしい
ローカルにそのままMySQLサーバーを立てるんだったらlocalhostでいいんだろうけど
Dockerを使っている場合はコンテナ名を指定しなきゃいけない

ということでhttp://localhost:8000/にアクセスしたら

first test.
second test.
third test.

と表示されます

なんとかphp7+Apache+MySQL開発環境をDockerで作る目標を達成しました。

Dockerもいいけど明日からは実技試験に向けてPHPのコードを書いていきたい

面接とSPI試験の対策もしておかなきゃなぁ