LoginSignup
3
8

More than 1 year has passed since last update.

Dockerを用いてNginxをWebサーバーとし、PHP(Laravel)、DBはPostgresSQLの開発環境を作成する。

Last updated at Posted at 2021-11-20

目的

ローカルでのLaravelの開発環境を作ってみたいので、Dockerを用いてNginxをWebサーバーとし、PHP(Laravel)、DBはPostgresSQLでローカルの開発環境を作成したいと思います。

選定理由はそれぞれ以下の通りです。
Docker → ローカルの環境への影響をなるべく少なく開発環境を作りたい、および新しい技術の習得
Nginx → 使用したことがないので、使用してみたい。
PHP → 一般的なWeb用のプログラミング言語だと思うので、使用してみたい。
Laravel → MVCモデルのフレームワークを使用してみたい。
PostgresSQL → 最終的にHerokuへのデプロイを考えており、HerokuにおいてはデフォルトのDBであることと、使用したことがないので使用してみたい。

事前準備

参考

こちらの記事が大変参考になりました。

開発環境用ディレクトリ、ファイルの作成

powershell
mkdir docker
cd docker
mkdir docker
mkdir docker/web
mkdir docker/php
New-Item docker/php/dockerfile    #Dockerイメージを定義するファイル
New-Item docker/web/default.conf #nginx用の設定ファイル
New-Item docker-compose.yml      #Docker上で使用するサービスを定義するファイル
New-Item index.html               #動作確認用
New-Item index.php                #動作確認用
cd docker

任意のディレクトリにてPowershellから上記を実行し、開発環境用のフォルダ,ファイルを作成します。

Webサーバー(nginx)の設定、動作確認

参考記事に倣い、Webサーバー(nginx)の設定、動作確認(コンテナの定義、起動)から行います。

docker-compose.yml
version: '3'
services:
  web:
    image: nginx:1.15.6
    ports:
      - '8000:80'
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html

docker-compose.ymlを上記の様に編集します。

versionでdocker-compose.yml自体のバージョン(ファイルの書き方)を指定します。

services内に実行するサービス(今回だったらnginx)に必要な定義を書いていきます。

webはDocker内でのコンテナの名前の定義なので、自分で自由に決めてください。Dockerコマンドでコンテナを指定するときなどにも使います。

imageは用途にあったものを指定します。今回はnginxを使いたいので、nginx:1.15.6と指定しています。
下記URLのDocker Hubからimageを指定するTagを見つけられると思います。

portsは、ホスト側のポートとコンテナ側のポートをどの様に転送するかを指定します。
今回のように8000:80と記述すると、ホスト側からlocalhost:8000にアクセスすることでDocker側のlocalhost:80(80はhttpのデフォルトポート)に転送されます。

volumesはホスト側とコンテナ側のファイルの共有の設定です。
ホスト側のパスコンテナ側のパスというように記述します。
今回のように、
./docker/web/default.conf:/etc/nginx/conf.d/default.confと記述した場合、
./docker/web/default.confがホスト側のパス、
/etc/nginx/conf.d/default.confがコンテナ側のパスとなりますので、
./docker/web/default.confを編集すると、
コンテナ側の/etc/nginx/conf.d/default.confへ編集の結果が反映されます。
(いじったファイルがそのままDocker上に反映される。)

上記以外の項目を設定することもあります。下記の記事が参考になります。

続いて、Webサーバー(nginx)の設定ファイルを記述します。

default.conf
server {
    listen 80;
    root /var/www/html;
    index index.html;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
}

listenでWebサーバー(nginx)がリクエストを受け付けるポート番号、IPアドレスなどを設定します。今回は80とポート番号のみを記述し、IPアドレスの記述をしていないので、すべてのIPアドレスの80番ポートでリクエストを受け付けます。

rootでドキュメントルートのディレクトリ、indexでインデックスとして使われるファイル名を指定します。
リクエストのURIが/で終わっている場合にレスポンスとして返すディレクトリとファイル名を指定しています。
今回はroot/var/www/htmlindexindex.htmlを記述しているので、
例えば、http://localhost:8000/にアクセスした場合、/var/www/html/index.htmlをレスポンスとして返します。

access_log, error_logはそれぞれのログの出力パスを記述しています。

上記以外の項目を設定することもあります。下記の記事が参考になります。

最後に動作確認用にindex.htmlの中身を記述します。

index.html
<h1>docker-compose-laravel</h1>
<p>Served by Nginx</p>

以上でファイルの準備が終了したので、Powershellからdocker-compose up(サービス用のコンテナの構築、作成、起動、アタッチ)をします。

docker-compose up -d

docker-compose up -dはdocker-compose.ymlがあるディレクトリで実行をしてください。

コマンド実行後、localhost:8000 にブラウザでアクセスすると、index.htmlに記述した内容がブラウザから確認出来ると思います。

image.png

PHPの設定、動作確認及びPHPとnginxの連携の設定、動作確認

続いて、PHPの設定(コンテナの定義、起動)及びPHPとnginxの連携の設定、動作確認を行います。

docker-compose.yml
version: '3'
services:
  web:
    image: nginx:1.15.6
    ports:
      - '8000:80'
    depends_on:
      - app
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html
  app:
    image: php:7.2-fpm
    volumes:
      - .:/var/www/html

docker-compose.ymlにPHP用の記述を追加します。
web内にdepends_on要素を追加し、新たにappコンテナの定義を追加します。
depends_onを指定すると、サービス間の依存関係を定義することができます。

今回のようにweb内のdepends_onappを指定すると、
web(nginx)はapp(PHP)に依存しているということになり、
app(PHP)のコンテナが先に起動し、web(nginx)のコンテナが後に起動することになります。

default.conf
server {
    listen 80;
    root /var/www/html;
    index index.php index.html index.htm;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

}

indexの記述をindex.html;からindex.php index.html index.htm;へ変更しています。
この様に、複数のindexファイルを指定すると、左から順にindexのファイルを探していき、一致したものをレスポンスとして返します。
この記述の場合、例えば、ディレクトリ内にindex.phpとindex.htmlがあった場合は、index.phpを返し、index.htmlとindex.htmがあった場合は、index.htmlを返します。

location / {~ ~}については下記のページがとてもわかりやすかったです。

location ~ \.php$ {~ ~}はWebサーバー(nginx)からPHP(PHP-FPM)へリクエストを渡す設定です。
fastcgi_pass app:9000;という書き方は、Dockerのコンテナで動かす場合のみ有効です。
本来は、127.0.0.1:9000のように設定するようです。

index.php
<h1>docker-compose-laravel</h1>
<p>Served by Nginx</p>
<?php phpinfo(); ?>

動作確認用にindex.phpを上記の様に編集・保存してください。

docker-compose up -d

docker-compose upを実行します。

コマンド実行後、localhost:8000 にブラウザでアクセスすると、index.phpに記述した内容がブラウザから確認出来ると思います。

image.png

データベース(PostgressSQL)の設定、動作確認

続いて、PostgresSQLおよびPG Admin(PostgreSQL用のWebのGUI)の設定(コンテナの定義、起動)、動作確認を行います。

下記記事を参考にいたしました。

version: '3'

services:
  web:
    image: nginx:1.15.6
    ports:
      - '8000:80'
    depends_on:
      - app
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html
  app:
    image: php:7.2-fpm
    volumes:
      - .:/var/www/html
  postgres:
    image: postgres:latest
    restart: always
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      PGPASSWORD: password123
      POSTGRES_DB: sample
      TZ: "Asia/Tokyo"
    ports:
      - 5432:5432
    volumes:
      - postgres:/var/lib/postgresql/data

  pgadmin:
    image: dpage/pgadmin4
    restart: always
    ports:
      - 81:80
    environment:
      PGADMIN_DEFAULT_EMAIL: ***
      PGADMIN_DEFAULT_PASSWORD: password
    volumes:
      - pgadmin:/var/lib/pgadmin
    depends_on:
      - postgres

volumes:
  postgres:
  pgadmin:

docker-compose.ymlにPostgresSQL,PG Admin用の記述を追加します。
postgres, pgadminコンテナ用の記述と、volumesの記述を追加します。

restart要素では、コンテナの自動再起動の設定ができます。今回のようにalwaysを指定すると、コンテナが停止した場合基本的に勝手に再起動します。(手動除く)

environment要素ではそれぞれのコンテナ内での環境変数を指定します。postgres内では、PostgresSQL内で使用するDB名やユーザー名、パスワードなどを設定しています。

トップレベルにあるvolumespostgres, pgadminを指定することによって、
他のコンテナ(app(PHP))からpostgresなどのコンテナを参照できるようになります。

PGADMIN_DEFAULT_EMAIL: ***は、適宜メールアドレスを入れて下さい。

docker-compose up -d

docker-compose upを実行します。

image.png

コマンド実行後、localhost:81 にブラウザでアクセスすると、
上画像のようにPG Adminが表示されることが確認できると思います。
起動に時間がかかる時があるっぽいです。
*
ログインはenvironmentで指定したメールアドレスとパスワードでできます。

Powershellから下記のコマンドを実行し、PostgresSQLのコンテナが起動したことを確認できると思います。

docker-compose exec postgres bash
psql -d postgres -U user;
\l
                             List of databases
   Name    | Owner | Encoding |  Collate   |   Ctype    | Access privileges
-----------+-------+----------+------------+------------+-------------------
 postgres  | user  | UTF8     | en_US.utf8 | en_US.utf8 |
 sample    | user  | UTF8     | en_US.utf8 | en_US.utf8 |
 template0 | user  | UTF8     | en_US.utf8 | en_US.utf8 | =c/user          +
           |       |          |            |            | user=CTc/user
 template1 | user  | UTF8     | en_US.utf8 | en_US.utf8 | =c/user          +
           |       |          |            |            | user=CTc/user

docker exec -it docker-compose-laravel_postgres_1 bashpostgresコンテナの中に入ります。
psql -d postgres -U user; でPostgreSQLの中に入ります。
\lを実行して、現在のデータベースの中を確認し、ymlで定義したsampleデータベースが作成されたことが確認できると思います。

Laravelのインストール

さて、Webサーバー、PHP、DBの設定が終わったので、最後にLaravelのインストールをします。

FROM php:7.2-fpm

#install composer
RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer

RUN apt-get update \
&& apt-get install -y \
git \
zip \
unzip \
vim

RUN apt-get update \
    && apt-get install -y libpq-dev \
    && docker-php-ext-install pdo_pgsql

WORKDIR /var/www/html

まずdockerfileを上記の様に編集します。
FROMにはイメージを指定します。
今回は、PHPが使える環境の上にLaravelのインストールを行うので、php:7.2-fpmを指定します。

RUNはDockerのイメージがビルドされるときに、コンテナ内で実行するコマンドを指定することができます。

今回はFROMのイメージがビルドされた後、RUNに書かれたコマンドによって、
composer(PHPのパッケージ管理システム)のインストール、
コンテナ内で使用するコマンドのインストール、
docker-php-ext-installを使用したPDOのインストールをします。

RUN cd /usr/bin && curl~ で composerのインストールを行います。
RUN ~~ git zip ~~でコマンドのインストールを行います。
RUN ~~ docker-php-ext-install pdo_pgsql でPDOのインストールを行います。

WORKDIR /var/www/htmlでコンテナ内でコマンドを実行するときのディレクトリを指定しています。

version: '3'

services:
  web:
    image: nginx:1.15.6
    ports:
      - '8000:80'
    depends_on:
      - app
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html
  app:
    build: ./docker/php
    volumes:
      - .:/var/www/html
    depends_on:
      - postgres
  postgres:
    image: postgres:latest
    restart: always
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      PGPASSWORD: password123
      POSTGRES_DB: sample
      TZ: "Asia/Tokyo"
    ports:
      - 5432:5432
    volumes:
      - postgres:/var/lib/postgresql/data

  pgadmin:
    image: dpage/pgadmin4
    restart: always
    ports:
      - 81:80
    environment:
      PGADMIN_DEFAULT_EMAIL: sixeyeddogfromhell@gmail.com
      PGADMIN_DEFAULT_PASSWORD: password
    volumes:
      - pgadmin:/var/lib/pgadmin
    depends_on:
      - postgres

volumes:
  postgres:
  pgadmin:

docker-compose.yml内のappimage: php:7.2-fpmbuild: ./docker/phpへと変更します。
この変更によって、docker-compose up時に/docker/php内のDockerfileを参照し、
ビルド時にコマンドを実行します。

docker-compose up -d

Powershellよりコマンドを実行し、コンテナをビルドします。

docker-compose exec app bash
composer create-project --prefer-dist laravel/laravel my-laravel-app

Dockerfileにコマンドを記述したことによって、すでにappコンテナ内にcomposerなどがインストールされた状態になっていると思います。

docker-compose exec app bashappコンテナ内に入り、
composer create-project --prefer-dist laravel/laravel my-laravel-appを実行して、新たなLaravelプロジェクトを作ります。

プロジェクトの作成が終わると、開発環境用のフォルダの中にmy-laravel-appフォルダが作成されたことが確認できると思います。

DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=sample
DB_USERNAME=user
DB_PASSWORD=password

作成されたファイルの中に、my-laravel-app/.envというLaravelの環境変数設定ファイルがあると思いますので、該当の個所を上記の様に変更します。

docker-compose down
docker-compose up -d
docker-compose exec app bash
cd my-laravel-app/
php artisan migrate

Powershellにてコンテナの再起動を行った後、appコンテナの中でLaravelプロジェクトのソースがあるディレクトリでphp artisan migrateを行います。

php artisan migrateコマンドはLaravelのデータベースのバージョン管理用のコマンドです。
ひとまずはLaravelインストール時に作成されるファイルでマイグレーションをします。
これ以降は、マイグレーションコマンドを使用して、開発に沿ったデータベースの変更のバージョン管理を行っていくことができると思います。

cd my-laravel-app/
php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.09 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0.01 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0.01 seconds)

appコンテナ内で、my-laravel-appフォルダへ移動後、php artisan migrateを実行してマイグレーションをします。

default.conf
server {
    listen 80;
    root /var/www/html/my-laravel-app/public;
    index index.php index.html index.htm;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

nginxからLaravelアプリへリクエストを渡したいので、
default.confのrootをroot /var/www/html/my-laravel-app/public;へ変更します。
この変更によって、nginxにきたリクエストはすべて/var/www/html/my-laravel-app/public/index.php index.html index.htmいずれかへ渡ります。(ファイルがあれば)

docker-compose down
docker-compose up -d

Powershellからコンテナを再起動し、ブラウザから localhost:8000 にアクセスします。

image.png
権限関係のエラーがでてしまいました。

docker-compose exec app bash
cd my-laravel-app/
chmod -R 777 storage

参考に権限付与をしました。

image.png

環境が構築できたことを確認できました。

終わりに

一度環境を構築してから、復習しつつ記事を書きました。
環境構築時に無視したりとばしたりしたところを確認出来てよかったです。
わからないところも増えました。

内容におかしなところややめたほうがよいものが見受けられましたら、
ご連絡を頂けますと幸いです。

3
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8