【docker-comose】git cloneしたLaravelプロジェクト(Nginx+php-fpm)がDockerで起動するまでの流れ

個人用メモです。

dockerのLaravelプロジェクトをローカルで展開するまでの流れ。



##1. git clone
githubからプロジェクトの元となるデータを取得する。

```
$ git clone --recursive <URL>
```

サブモジュールがある場合は、`--recursive`必須。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/95166a48-4be6-a56a-3ab0-287d1fd9c6c3.png)



###.envファイル
重要な.envファイルはサブモジュールに保存している。
サブモジュールのレポジトリはawsに作成しているため特定の権限がある人しかDLできない仕様。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/8f68a3d6-035b-2354-676f-9af0ce10d546.png)


<br>
##2. プロジェクトの初期設計
.envファイルを作成する。
また、webserverのベースイメージとなるphp-fpmのイメージを作成する。（公式のイメージをpullしてプロジェクト用にカスタマイズする）

```
#init
alias aaa-init="cp ./aaa-deploy/.env.* ./ && \
  cp ./.env.local ./.env && \
  docker-compose build php-fpm
  aaa-fpm-push-image"
```

最初にinitしないとエラーが出て動かない。

###2-1 .env関連ファイルのコピー

```
cp ./aaa-deploy/.env.* ./
```

サブモジュールの.envファイルをルートディレクトリ直下に保存する。


###2-2 .envファイルの作成

```
cp ./.env.local ./.env
```

2-1でコピーした .env.localファイルを複製し、ファイル名を.envにする。

.env.localはデフォルト設定が書かれたバックアップファイル。運用は.envで行う。


###2-3 php-fpmイメージの作成

```
docker-compose build php-fpm
```


####2-3-1 docker-compose.yml
docker-compose.ymlに記述された、内容をベースにphp-fpmのイメージを作成する。

```yml:docker-composer.yml
  # Php+Nginx service
  php-fpm:
    build:
      context: ./
      dockerfile: 


docker/php-fpm/Dockerfile
      args:
        - DOCKER_PHP_VERSION=7.3
    image: aaa_php-fpm
```



####2-3-2 Dockerfile (php-fpm用)
php-fpmのベースイメージを公式ページから拾ってきて、必要なパッケージを入れ込む。

[php:7.3-fpm](https://github.com/docker-library/php/blob/74175669f4162058e1fb0d2b0cf342e35f9c0804/7.3/buster/fpm/Dockerfile)はDebianをベースにしている。php.iniも含まれている。

```Dockerfile:Dockerfile
#docker-composeから変数を受け取る
ARG DOCKER_PHP_VERSION

#指定のバージョンのphpーfpmのイメージをdocker hubからDL（ここでは7.3指定）
FROM php:${DOCKER_PHP_VERSION}-fpm

#Debianのパッケージライブラリ更新
#パッケージインストール（4つ）
RUN apt-get update && apt-get install -y build-essential git nginx libxml2-dev

#php拡張パッケージのopcacheを有効化
RUN docker-php-ext-enable opcache

#Debian用の3つのパッケージをインストール
RUN apt-get install -y zlib1g-dev libzip-dev unzip \
#php拡張パッケージのzipをインストールし有効化
    && pecl install zip \
    && docker-php-ext-enable zip

#php拡張パッケージのredisをインストールし有効化
RUN pecl install redis \
    && docker-php-ext-enable redis

#php拡張パッケージのpdo_mysqlをインストールし有効化
RUN docker-php-ext-install pdo_mysql \
    && docker-php-ext-install mysqli

# OPcache
RUN docker-php-ext-install opcache

# php拡張パッケージのapcuをインストールし有効化
RUN pecl install apcu && docker-php-ext-enable apcu

#コマンドラインでapcを使えるようにする
RUN echo "apc.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini

#apcの有効化（1でON。デフォルト１）
RUN echo "apc.enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini

#apcの共有メモリに1G割り当（デフォルト30MB）
RUN echo "apc.shm_size=1G" >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini

#composerのインストール（v1.10.15）
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --version=1.10.15 \

#composerの本体（phar）をcompoesrディレクトリ配下に移動
    && mv /usr/bin/composer.phar /usr/bin/composer \

#高速化（並行処理）のためhirak/prestissimoをインストール v1系のみ（2系は不要）
    && composer global require hirak/prestissimo

#Debianの不要なパッケージを削除
RUN apt-get autoremove -y \

#Debianのパッケージのキャッシュを削除
    && rm -rf /var/cache/apt/*

#dockerコンテナの開始ディレクトリを/appにする
WORKDIR /app/
```

作成したイメージは、aaa_php-fpm:latest という名前:タグ名でdocker上に保存される。


<br>
##3. 開発プロジェクトのイメージ作成

```
alias aaa-dev-build="aaa-envvars docker-compose build dev
"
```

###3-1. gitハッシュの取得
`git rev-parse`コマンドを使って、現在（HEAD）のコミット番号を取得し、変数"GIT_HASH"に代入する。

```
alias aaa-envvars="GIT_HASH=\$(git rev-parse --short HEAD)"
```


<br>

###3-2. 開発環境のイメージ作成
2-3のphp-fpmイメージの作成で作成したイメージをベースに、開発環境のイメージを作成する。


```yml:docker-composer.yml
  development:
    build:
      context: ./
      dockerfile: Dockerfile
    image: aaa_dev:latest
    container_name: aaa_dev
    tty: true
    ports:
      - 8000:80
    env_file:
      - .env.local
    environment:
      - APP_ENV=local
      - APP_DEBUG=true
      - GRPC_VERBOSITY=debug
      - GRPC_TRACE=http_keepalive,round_robin
    volumes:
      - /app/vendor/
      - /app/node_modules/
      - /app/public/assets/js/
      - /app/public/assets/css/
      - /app/storage/
      - .:/app/
```


###3-2-1. イメージの作成

```Dockerfile:Dockerfile
#専用のphp-fpmのイメージをベースにする
FROM aaa_php-fpm:latest

#Debian用のnode v14とnpmをインストール
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - \
    && apt-get install -y nodejs \

#pythonをインストール
    && apt-get install -y python \

#php.iniを作成
RUN mv /usr/local/etc/php/php.ini-development /usr/local/etc/php/php.ini \
 
    #不要なiniファイルを削除（ini-*）
    && rm /usr/local/etc/php/php.ini-*

#webserver用のシェルファイルをコンテナにコピー
COPY docker/local/webserver.sh /docker/local/webserver.sh

#実行権限を付与
RUN chmod +x /docker/local/webserver.sh

#dockerコンテナのwebserver.shを実行（docker runのとき）
ENTRYPOINT ["/docker/local/webserver.sh"]
```

作成したイメージは、docker-composeで指定した通り、`aaa_dev:latest`という名前で保存される。


<br>
・nodeのインストール
https://github.com/nodesource/distributions

https://deb.nodesource.com/setup_14.x
node.js14を指定。

>`apt-get install update`の場合安定版がインストールされる。また、npmも別途インストールが必要。
curlでDLする場合は、npmもバンドルされている。（この取得方法をPPAという。personal package archive）


・`curl -sL URL`
-s: エラーを表示。
-L: リダイレクトがかかっている場合、リダイレクト先にアクセスする。


・`ENTRYPOINT[シェルファイル]`
ビルドの時は実行しない。docker runやupでコンテナを起動するときに実行される。（CMDも同じ）




<br>
##4. コンテナの起動

```
alias aaa-dev-up="aaa-dev-build && aaa-envvars docker-compose up dev"
```

- コンテナ起動自は毎回イメージを新規作成する。（ファイルの変更内容を反映するため）
- gitのハッシュ値もその都度取得


###4-1. コンテナ起動コマンド

```:起動コマンド
docker-compose up dev
```

devサービスで指定のイメージからコンテナを起動する。


<br>
###4-2. コンテナの作成
先ほど作成したイメージからコンテナを作成する。


```yml:docker-composer.yml
  development:
    build:
      context: ./
      dockerfile: Dockerfile
    image: aaa_dev:latest
    container_name: aaa_dev
　　 #省略
```

指定のimageを探して、コンテナを起動する。


<br>
###4-3. コンテナの起動その１（起動のための事前準備）
コンテナを起動する。
コンテナ起動時に実行されるのは、tty, ports, env_file, environment, volumes。

コンテナをホスト側とDockerで繋ぎ（ports, volumes）、Dockerに起動のための環境変数を渡す。


```yml:docker-composer.yml
  development:
　　 #省略
    tty: true
    ports:
      - 8000:80
    env_file:
      - .env.local
    environment:
      - APP_ENV=local
      - APP_DEBUG=true
      - GRPC_VERBOSITY=debug
      - GRPC_TRACE=http_keepalive,round_robin
    volumes:
      - /app/vendor/
      - /app/node_modules/
      - /app/public/assets/js/
      - /app/public/assets/css/
      - /app/storage/
      - .:/app/
```




<br>
###4-4. コンテナ起動（ENTRYPOINTで指定したシェルファイルの実行）
Dockerコンテナ内で処理を実行する。

```Dockerfile:Dockerfile
###省略
#dockerコンテナのwebserver.shを実行（docker runのとき）
ENTRYPOINT ["/docker/local/webserver.sh"]
```

```sh:webserver.sh
#!/bin/bash

#ディレクトリを作成する
mkdir -p database/factories
mkdir -p storage/app/public
mkdir -p storage/framework/sessions
mkdir -p storage/framework/views
mkdir -p storage/framework/cache
mkdir -p storage/app/json
mkdir -p storage/framework/cache/data

#composer.lockに記述してあるパッケージをインストール
composer install

#composerのクラスの再生成
composer dump-autoload

#ビューのキャッシュクリア
php artisan view:clear

#コンパイルしたクラスとサービスキャッシュのクリア
php artisan clear-compiled

#設定ファイルのキャッシュをクリア
php artisan config:clear

#ルートのキャッシュをクリア
php artisan route:clear

#アプリケーションのキャッシュをクリア
php artisan cache:clear

#npmのインストール（package.json）
npm install

#ファイル更新を自動監視（バックグラウンドで実行）
npm run watch 2>&1 &

#laravel起動（どこからでも80番ポートにアクセスできる）
php artisan serve --host 0.0.0.0 --port 80
```


以上でコンテナ起動完了。


<br>
##補足
###ポートの接続の流れ

localhost:8000
↓
dockerコンテナの80
↓
nginx(Laravel)