【悪戦苦闘】GCEとDockerでLaravelをインストール〜7つのステップで料理〜

こんにちは。開発環境の構築ってどうしようもなく面倒くさいですよね。慣れない中、Google Compute Engine（GCE）とDockerでLaravelをインストールしましたが、大変苦戦しました。

この記事を見れば、GCEでVMインスタンスを立て、Laravelの初期画面表示・マイグレーションするところまで完了できます。

モチベーションはクラウドでの開発環境構築です。

# 想定読者はこんな方々
想定される読者は以下の方々です。

- GCEで開発環境を構築したいけどよくわからない人💪
- Docker学習中の人💪
- Laravelの開発環境を構築したい人💪
- ローカルPCの環境構築を抜け出したい人💪

# インストールする環境

- MySQL：8.0.17
- Laravel：5.8.29
- Docker：19.03.0
- PHP：7.2.20

# 記事の構成
今回の記事の構成は以下の通り、7つのステップで進めていきます。

1. VMインスタンスを作成する
2. SSHで接続してみる
3. より簡単にSSH接続をする
4. Dockerをインストールする
5. Gitをインストール
6. Dockerを使ってLaravelの開発環境を構築する
7. MySQLとの接続をしよう

#ステップ①：VMインスタンスを作成する
GCE上でVMインスタンスを作成します。

VMインスタンス>インスタンスを作成を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203270/af87020d-32d6-146b-1d0d-bbdbc4ff40df.png)

VMインスタンスはひとまず、以下の形で設定しました。

- 名前：dev-laravel
- リージョン：us-central1（アイオワ）
- ゾーン：us-central1-a
- マシンタイプ：n1-standard-1（1 vCPU、3.75 GB メモリ）
- アクセス スコープ：デフォルトのアクセス権を許可
- ファイアウォール：「HTTP」「HTTPS」どちらもチェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203270/828b649c-71eb-bd8b-1ed9-42caeb658a53.png)

作成を押して完了です。

#ステップ②：SSHで接続してみる
（参照：[GCPにSSHで接続する方法 | エンジニアの眠れない夜](https://sleepless-se.net/2018/09/15/gcp-ssh/)）

ローカルのパソコンからSSHで接続してみましょう！以下を実行して秘密鍵・公開鍵を作成します（`<user_name>`は適宜置き換えます）。

```terminal
$ cd ~/.ssh
$ ssh-keygen -o -t rsa -C "<user_name>" -b 4096
```
公開鍵の中身をコピーします。

```terminal
$ cat ~/.ssh/id_rsa.pub
ssh-rsa <hoge>== <user name> #ssh~からコピー
```

`GCP`のVMインスタンス一覧から、先ほど作成したインスタンスを選択します。「SSHキーが0個あります」という表示がある箇所をクリックして、公開鍵の中身をペースト・保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203270/f3043b9e-2577-5f96-1022-2adaa357dc06.png)


以下のコマンドを実行して接続できるか確認します。

```terminal
$ ssh user_name@インスタンス外部IPアドレス -i 秘密鍵のパス
```

#ステップ③：より簡単にSSH接続をする

ステップ②の最後のコマンドを調べながら実行するのは面倒なので、`config`ファイルに接続情報を入力し、より簡単にSSH接続できる状況を整えましょう。

```terminal
$ vi ~/.ssh/config
```

`config`画面が表示されるので、以下の情報を入力します。

```terminal
Host 任意の接続名（インスタンス名などわかりやすい名前）
HostName VMインスタンスの外部IP
User ユーザ名
Port ポート番号（22）
IdentityFile 鍵へのPATH(例えば~/.ssh/id_rsa)
```

`Host`を仮に`dev-laravel`と入力したならば、以下のコマンドで`GCP`にログインできます。

```terminal
$ ssh dev-laravel
```

# ステップ④：Dockerをインストールする
（参照：[GCEのVMインスタンス作成からDockerの利用開始まで - Qiita] (https://qiita.com/kyohmizu/items/5f1929a2e949a9fa0da8)）

SSHでVMインスタンスに接続したので、Dockerをインストールしましょう！Dockerの詳しい概要・仕組みは、[こちら](https://qiita.com/kotaro-dr/items/b1024c7d200a75b992fc)の記事がわかりやすかったです。

以下インストール方法です。

```terminal
[user@docker-sample ~] $ curl -fsSL https://get.docker.com -o get-docker.sh
[user@docker-sample ~] $ sudo sh get-docker.sh
```

`Docker-machine`をインストールします。

```terminal
[user@docker-sample ~] $ curl -L https://github.com/docker/machine/releases/download/v0.16.1/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine && chmod +x /tmp/docker-machine && sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
```

`Docker-compose`をインストールします。

```terminal
[user@docker-sample ~] $ sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
[user@docker-sample ~] $ sudo chmod +x /usr/local/bin/docker-compose
```

Dockerのインストールに成功したら、バージョン確認をします。

```terminal
[user@docker-sample ~] $ sudo docker version
   Client:
       Version:           18.09.8
       API version:       1.39
       Go version:        go1.10.8
       Git commit:        0dd43dd87f
       Built:             Wed Jul 17 17:41:13 2019
       OS/Arch:           linux/amd64
       Experimental:      false
      
      Server: Docker Engine - Community
       Engine:
        Version:          18.09.8
        API version:      1.39 (minimum version 1.12)
        Go version:       go1.10.8
        Git commit:       0dd43dd
        Built:            Wed Jul 17 17:07:25 2019
        OS/Arch:          linux/amd64
        Experimental:     false
```

#ステップ⑤：Gitをインストール
（参照：[github - How to Install git in google compute engine? - Stack Overflow](https://stackoverflow.com/questions/27460923/how-to-install-git-in-google-compute-engine)）

`apt-get`パッケージをアップデートします。

```terminal
[user@docker-sample ~] $ sudo apt-get update
[user@docker-sample ~] $ sudo apt-get install git
```

以下のコマンドを入力すると`/usr/bin/git`という表示が出るので、ここまで来たら完了です。

```terminal
[user@docker-sample ~] $ which git
/usr/bin/git
```

#ステップ⑥：Dockerを使ってLaravelの開発環境を構築する
（参照：[Docker環境でLaravelを構築するまで、わずか15分。 - Qiita] (https://qiita.com/hosono/items/dd404f3f074722ef989d)）

それでは、インストールしたDockerを使ってLaravelの開発環境を構築しましょう！まずは、作業ディレクトリを作成します。

```terminal
[user@docker-sample ~] $ mkdir dev-laravel
[user@docker-sample ~] $ cd ~/dev-laravel
```

今回はLaradockというものを使います。LaradockはDocker上で動作するPHP開発環境で、便利なDockerイメージをサポートしています。

早速、Laradockをクローンします。

```terminal
[user@docker-sample ~] $ git clone https://github.com/Laradock/laradock.git
```

.envファイルを作成します。

```terminal
[user@docker-sample ~] $ cd laradock/
[user@docker-sample ~] $ cp env-example .env
```

`nginx`の設定ファイルを編集します。

```terminal
[user@docker-sample ~] $ cd nginx/sites
[user@docker-sample ~] $ cp default.conf default.conf.bak
[user@docker-sample ~] $ cp laravel.conf.example default.conf
[user@docker-sample ~] $ vi default.conf
```

`root /var/www/laravel/public`の箇所を`root /var/www/app01/public`に変更して保存します（あとでDockerのプロジェクトの名称を「app01」にするため、設定を変更しています）。

さぁ、ここでDockerコンテナを立ち上げましょう。nginxとphp-fpmが構築されたサーバーを立ち上げます（かなり時間がかかります）。

```terminal
[user@docker-sample ~] $ cd ../..
[user@docker-sample ~] $ sudo docker-compose up -d nginx mysql phpmyadmin redis workspace
```

コンテナが立ち上がっているかどうかを確認します。

```terminal
[user@docker-sample ~] $ sudo docker-compose ps
```

StateがUPになっていればOKです。

自動的にLinuxコンテナもセットアップされているので、workspaceにログインします。

```terminal
[user@docker-sample ~] $ sudo docker-compose exec workspace bash
```

`/var/www#`というディレクトリに入るので、ここで以下のコマンドを打ちます。

```terminal
[root@~:/var/www#] composer create-project laravel/laravel app01
```

ここでLaravelの初期画面を表示しようとすると、パーミッションエラーが返ってきます（参照：[Laravelでエラー　The stream or file "/var/www/html/laravel_pj/storage/logs/laravel-2018-04-06.log" could not be opened: failed to open stream: Permission denied / エラーサーチ] (https://error-search.com/error-post/detail/175/Laravel%25E3%2581%25A7%25E3%2582%25A8%25E3%2583%25A9%25E3%2583%25BC%25E3%2580%2580The%2Bstream%2Bor%2Bfile%2B%2522%252Fvar%252Fwww%252Fhtml%252Flaravel_pj%252Fstorage%252Flogs%252Flaravel-2018-04-06.log%2522%2Bcould%2Bnot%2Bbe%2Bopened%253A%2Bfailed%2Bto%2Bopen%2Bstream%253A%2BPermission%2Bdenied)）。

これは、`laravel.log`に書き込む際、権限がないためエラーになります。解消するには、プロジェクト直下のstrageディレクトリの権限を変更する必要があります。Workspaceにログインしたまま以下のコマンドを打ちましょう。

```terminal
[root@~:/var/www#] cd app01/
[root@~:/var/www/app01#] chmod 777 -R storage/
```

さぁ、Laravelの初期画面を表示させましょう！VMインスタンスの「外部IP」をコピペしてブラウザでアクセスします。Awesome!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203270/22eecd60-057f-15c8-245b-35d6b505fc92.png)


# ステップ⑦：MySQLとの接続をしよう
（参照：[Laravelのphp artisan migrateでSQLSTATE{HY000} {2002} Connection refusedが返る - Qiita] (https://qiita.com/coldsleep6666/items/506fd6a92ff29aee90bb)）
（参照：[【2019年2月】Laradockの初期環境設定方法 - Qiita](https://qiita.com/don-bu-rakko/items/0297280553e99aa6d7b8)）

ここで、Workspaceにログインしたまま、マイグレーションを試みます。すると、エラーが表示されて先に進めません。

```terminal
[root@~:/var/www/app01#] php artisan migrate
Illuminate\Database\QueryException  : SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = homestead and table_name = migrations and table_type = 'BASE TABLE')
 				 
Exception trace:
1   PDOException::("SQLSTATE[HY000] [2002] Connection refused")
 				/var/www/app01/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70
2   PDO::__construct("mysql:host=127.0.0.1;port=3306;dbname=homestead", "homestead", "secret", [])            /var/www/app01/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70
```

これは`.env`ファイルを修正していないために生じるエラーです。`laradock`側と`app01`側の`.env`ファイルの設定を合わせる必要があります。今回はひとまず、MySQLに登録されている`default`データベース・ユーザーにログインする形にしてみます。それでは、`Workspace`から`exit`し、`laradock`側の`.env`ファイルを確認します。

```terminal
[user@docker-sample ~] $ vi .env
		 
MYSQL_VERSION=latest
MYSQL_DATABASE=default
MYSQL_USER=default
MYSQL_PASSWORD=secret
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_ENTRYPOINT_INITDB=./mysql/docker-entrypoint-initdb.d
```

今度は`app01`側の`.env`ファイルを修正します。`laradock`側の設定と合うように、以下の通り修正します。

```terminal
[user@docker-sample ~] $ sudo vi ../app01/.env
 			 
DB_HOST=mysql
DB_DATABASE=default
DB_USERNAME=default
```

これで、`.env`ファイルの修正は完了です。ただ、実はこの修正だけで進めると、`SQLSTATE[HY000] [2054]`エラーが出てしまいます（参照：[phpからMySQL 8.0へPDOで接続時「SQLSTATE{HY000} {2054} The server requested authentication method unknown to the client」 - Symfoware](https://symfoware.blog.fc2.com/blog-entry-2160.html)）。

原因は、PHPの接続ライブラリが`caching_sha2_password`に対応していないためです。`MySQL 8.0`のデフォルトの接続方式は`caching_sha2_password`となっているため、これを変更する必要があります。

`laradock`ディレクトリから`root`ユーザーで`MySQL`へのログインを試みます。`mysql>`の表示が出れば、ログイン完了です。

```terminal
[user@docker-sample ~] $ sudo docker-compose exec mysql mysql -uroot -proot
mysql>
```

以下のコマンドを入力して、各ユーザーの接続方式を確認してみましょう。

```terminal
mysql> SELECT user, host, plugin FROM mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| default          | %         | caching_sha2_password |
| root             | %         | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
```

接続しようとしている`default`の接続方式が`caching_sha2_password`であることを確認しました。これを`mysql_native_password`に変更します。

```teminal
mysql> ALTER USER 'default'@'%' IDENTIFIED WITH mysql_native_password BY 'secret';
```

接続方式を確認します。

```terminal
mysql> SELECT user, host, plugin FROM mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| default          | %         | mysql_native_password |
| root             | %         | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
```

`mysql_native_password`への変更が確認できました。
`exit`でMySQLを抜け出し、再度Workspaceにログインしましょう。

```terminal
[user@docker-sample ~] $ sudo docker-compose exec workspace bash
```

ログインできたら、マイグレーションしてみます。

```terminal
[root@~:/var/www#] cd app01/
[root@~:/var/www/app01#] php artisan migrate
Migration table created successfully
```
できました！！