Dockerを使ってLaravelとAngular環境構築！

# 概要
Dockerを使ってLaravelとAngular環境構築を構築してみます。

[Github](https://github.com/Akira-Demizu/developments/tree/main/angular_laravel)

# 構成

```
.
├── back
├── docker
│   ├── mysql
│   ├── ├── Dockerfile
│   │   └── my.cnf
│   ├── nginx
│   │   └── default.conf
│   └── php
│       ├── Dockerfile
│       └── php.ini
├── docker-compose.yml
└── front
```

# 環境

- node:16.6.2
- php:8.0.9
- Angular:12.2.1
- Laravel:8.55.0

※ AngularとLaravelはバージョン指定してインストールしていないので、タイミングによっては上記より上のバージョンがインストールされます。

# 手順

## 1. Docker環境構築

### 1-1. docker-compose作成
今回は、node, php, nginx, mysqlの4つのコンテナを用意します。

```docker-compose.yml
version: '3.9'

services:
  node:
    image: node:16.6.2
    working_dir: /projects
    ports:
      - 4200:4200
    volumes:
      - ./front:/projects:cached
    tty: true
#    command: bash -c "
#      npm cache clean -f;
#      npm install;
#      cp -f src/environments/environment.develop.ts src/environments/environment.ts;
#      npm link @angular/cli && export PATH='$HOME/.npm-global/bin:$PATH';
#      npm start;
#      "

  php:
    build: ./docker/php
    volumes:
      - ./back:/var/www:cached
#    command: -c "
#      cp -f .env.develop .env;
#      composer install;
#      php artisan config:cache && php artisan config:clear;
#      "

  nginx:
    image: nginx
    ports:
      - 8080:80
    volumes:
      - ./back:/var/www:cached
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:cached
    depends_on:
      - php

  mysql:
    build: ./docker/mysql
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: sample
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    restart: on-failure
    volumes:
      - mysqldb:/var/lib/mysql:cached
    ports:
      - 3306:3306

volumes:
  mysqldb:
```

後述していますが、angularのインストールが終わるまでは`command: bash -c "npm cache clean -f && npm install && npm start"`はコメントしておいてください。

### 1-2. 各コンテナの設定ファイル作成

#### mysqlコンテナ
##### Dockerfile

```Dockerfile
FROM mysql:8
COPY my.cnf /etc/mysql/conf.d/
RUN chmod 644 /etc/mysql/conf.d/my.cnf
```

##### my.cnf
```my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

[client]
default-character-set=utf8mb4
```


#### nginxコンテナ
##### default.conf

```nginx
server {
    listen 80;
    server_name example.com;
    root /var/www/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
```

#### PHPコンテナ

##### Dockerfile

```Dockerfile
FROM php:8.0.9-fpm

COPY php.ini /usr/local/etc/php/

RUN apt-get update \
    && apt-get install -y zlib1g-dev libzip-dev mariadb-client libpng-dev unzip
RUN docker-php-ext-install zip pdo_mysql gd

#Composer install
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin

WORKDIR /var/www

RUN composer global require "laravel/installer"
```

##### php.ini

```php.ini
zend.exception_ignore_args = off
expose_php = on
max_execution_time = 30
max_input_vars = 1000
upload_max_filesize = 64M
post_max_size = 128M
memory_limit = 256M
error_reporting = E_ALL
display_errors = on
display_startup_errors = on
log_errors = on
error_log = /dev/stderr
default_charset = UTF-8

[Date]
date.timezone = Asia/Tokyo

[mysqlnd]
mysqlnd.collect_memory_statistics = on

[Assertion]
zend.assertions = 1

[mbstring]
mbstring.language = Japanese
```

## 2. Dockerの起動

```sh
docker-compose up -d
```

## 3. Angularプロジェクトを作成

### nodeコンテナにインスペクションします。

```sh
docker-compose exec node bash
```

### Angularインストール

```bash
npm install -g @angular/cli
```

### プロジェクトの作成

#### プロジェクト作成コマンド
`sample`というプロジェクトを作る場合は以下のようになります。
※ frontディレクトリ内にangularプロジェクトを作りたいのでオプション `--directory ./` をつけています。

```bash
ng new sample --directory ./
```

上記のコマンドを実行すると2つ質問されます。

#### 1つ目の質問

```bash
Would you like to add Angular routing?
```
Angularにrouting機能を持たせますか？という質問で、YesかNoで答える必要があります。
一つのページで完結しない限りNoにはならないので基本Yesだと思います。  

#### 2つ目の質問

```bash
Which stylesheet format would you like to use?
```

自分が使いたいスタイルシートのフォーマットを選択しましょう。
`scss`が一般的かなーと思ってはいます。

### `package.json`編集
nodeコンテナでangularサーバーを動かすために以下のように`package.json`を編集します。

```
"start": "ng serve",
↓
"start": "ng serve --host 0.0.0.0 --poll",
```

### Angularサーバーの起動

```bash
npm start
```

### Angular画面の確認

ブラウザから http://localhost:4200 にアクセスしてみてください。
![スクリーンショット 2021-08-18 18.19.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290840/e679efe2-bd48-e84a-c3e9-dd4f012d056b.png)

## 4. Laravelプロジェクト作成

### phpコンテナにインスペクションします。

```sh
docker-compose exec php bash
```

### プロジェクトの作成
以下のコマンドで`back`ディレクトリ直下に新しくLaravelプロジェクトが作成されます。

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

### Laravel画面の確認

ブラウザから http://localhost:8080 にアクセスしてみてください。
![スクリーンショット 2021-08-18 19.57.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290840/bb3e39d0-0495-11c1-76cf-4aff1ff23129.png)

## 5. DB接続設定
Laravelの.envを編集以下のように編集しましょう。

```.env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=sample
DB_USERNAME=root
DB_PASSWORD=root
```

`.env`をコピーして`.env.develop`としてgitなどにプッシュしておくと良さそうですね。

## 6. おまけ
npmやcomposerで管理しているパッケージが追加されたり、環境ファイルが変わった場合にもdocker起動時に自動で対応できるようにカスタマイズしてみます。

### environment.develop.tsの作成
Angularプロジェクトの開発環境用の環境ファイルを用意しましょう。
`front/src/environments/environment.ts`をコピーして、`front/src/environments/environment.develop.ts`を用意しましょう。

### docker-compose.ymlの調整
docker-compose.ymlのnodeコンテナとPHPコンテナのコメントアウトを除けてみましょう。

```docker-compose.yml
version: '3.9'

services:
  node:
    image: node:16.6.2
    working_dir: /projects
    ports:
      - 80:4200
    volumes:
      - './../../user:/projects:cached'
    tty: true
    command: bash -c "
      npm cache clean -f;
      npm install;
      cp -f src/environments/environment.develop.ts src/environments/environment.ts;
      npm link @angular/cli && export PATH='$HOME/.npm-global/bin:$PATH';
      npm start;
      "
  php:
    build: ./docker/php
    volumes:
      - ./../../php:/var/www:cached
    command: -c "
      cp -f .env.develop .env;
      composer install;
      php artisan config:cache && php artisan config:clear;
      "
```

**node**
コンテナ立ち上げ時に、npmキャッシュのクリア、npmパッケージのインストール、Angular環境ファイルのコピー、`ng`コマンドが利用できるようにパスの設定、Angularサーバーの起動を行うようになります。

**php**
コンテナ立ち上げ時に、環境ファイルのコピー、composerパッケージのインストール、laravelのキャッシュクリアをします。

## 7. 最終確認

### 起動
```sh
docker-compose up -d
```

### Angular
http://localhost:4200

`Angularはコンパイルに時間かかることがあるので数分待つ必要がありそうです。`

### Laravel
http://localhost:8080

### MySQL
Laravelのマイグレーションが正常に実行できればOKです。

```sh
docker-compose exec php bash -c "php artisan migrate"
```

```
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (46.45ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (41.81ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (42.92ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (58.75ms)
```

### 停止

```
docker-compose down
```