1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

docker-composeを使ってDocker上にLaravelを構築する方法(Nginx & php-fpm & MySQL)

Last updated at Posted at 2021-01-27

docker-composeを使ってDocker上にLaravelを構築する方法。WebサーバーはNignx + php-fpmを使用。

##目次

  1. Laravelをローカルに構築
  2. .envファイルの設定
  3. dockerにcomposerのデータをコピー
  4. docker-compose.ymlを作成
  5. Dockerfileの作成
  6. PHPの構成
  7. NginxとPHP-FPM
  8. Nginxの設定
  9. MySQLの設定
  10. コンテナ起動
    11. コンテナの起動状況の確認
    12. ブラウザで確認
  11. (補足)ブラウザ表示でエラーが出た場合の対処法

##1. Laravelをローカルに構築する

###1-1. githubからクローン

git clone https://github.com/laravel/laravel.git <プロジェクト名>

###1-2. composerを使ってバンドルをインストールする。
$ composer update

composer.jsonに書いてあるバンドルがズラーっとインストールされる。

###1-3 .envファイルの設定
まずは.envファイルを作成する。(.env.exampleをコピーする)

cp .env.example .env

次にキーを作成する。

$ php artisan key:generate

MySQLと接続するためにDBの設定を変更する。

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=******

DB_DATABASEとDB_PASSWORDは次で作成するdocker-composer.ymlと合わせる。


###(補足)composerでプロジェクトを作成する方法

以下リンクのNo3まででローカルで動くLaravelの環境を構築できる。

Laravelプロジェクトの作り方


##2. dockerにcomposerのデータをコピー プロジェクトのルートディレクトリに移動後、以下を実行。
$ docker run --rm -v $(pwd):/app composer install
  • composerイメージからコンテナを作成しinstallを実行。
  • 現在のディレクトリをコンテナ内の/appにマウント。
  • コンテナ起動後にコンテナを削除する。

composerの必要なデータのみローカルの現在のディレクトリにコピーする。

バンドルが記述されたcomposer.lockがローカルのルートディレクトリに追加される。

docker runコマンド

docker run [オプション] イメージ [コマンド] [引数...]

####--rmオプション
コンテナ終了時、自動的に削除。
composerのイメージとコンテナは不要なため。必要なデータのみマウントしたボリュームにコピーしておく。

####-vオプション
ボリュームのマウント。
ローカルのディレクトリをコンテナ内のディレクトリにマウントする。

--volumeの略。

▼ボリュームのマウント方法

-v [ホスト側ソース:]コンテナ側送信先[:<オプション>]

  • -v $(pwd):/app
  • ホスト側ソースは絶対パスか、ボリューム名で指定。
    • $(pwd):ホスト側の現在のディレクトリパス
    • /app: コンテナ内のappディレクトリ

####起動するイメージの指定 imageに`composer`を指定。タグを指定していない場合は`latest`。

dockerはまず、localでcomposer:latestを探す。なければdocker hubから指定のイメージを探す。

docker hun公式 composer image


####コマンド実行例
$ docker run --rm -v $(pwd):/app composer install
Unable to find image 'composer:latest' locally
latest: Pulling from library/composer
8bb409133b6b: Pull complete 
Digest: sha256:447516936298f9f63d0b718d1a21bd70066b6c206e174cd29938c79b8eefe7b1
Status: Downloaded newer image for composer:latest
No lock file found. Updating dependencies instead of installing from lock file. Use composer update over composer install if you do not have a lock file.
Loading composer repositories with package information
Updating dependencies
Lock file operations: 105 installs, 0 updates, 0 removals
  - Locking asm89/stack-cors (v2.0.2)
  - Locking brick/math (0.9.2)
  (省略)
Writing lock file
Installing dependencies from lock file (including require-dev)
Nothing to install, update or remove
77 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fideloper/proxy
Discovered Package: fruitcake/laravel-cors
Discovered Package: laravel/sail
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
74 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

ボリュームをマウントしているので、作成されたファイルがローカルに保存される。

image.png


##3. docker-compose.ymlを作成する
$ vim docker-compose.yml

vimエディタでiをクリックしてinsertモードに入り、以下をコピペ。

コピペ後は、esc + :wqで保存して終了。

(参考)vimの使い方

###docker-compose.yml

docker-compose.yml
version: '3'
services:

  #PHP Service
  app:
    build:
      context: .
      #dockerfile: Dockerfile
    image: app_php-fpm
    container_name: appdocker
    restart: unless-stopped
    tty: true
    environment:
      SERVICE_NAME: app
      SERVICE_TAGS: dev
    working_dir: /var/www
    volumes:
      - ./:/var/www
      - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
    networks:
      - app-network
    links:
      - webserver
      - db

  #Nginx Service
  webserver:
    image: nginx:alpine
    container_name: webserver
    restart: unless-stopped
    tty: true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./:/var/www
      - ./nginx/conf.d/:/etc/nginx/conf.d/
    networks:
      - app-network

  #MySQL Service
  db:
    image: mysql:5.7.22
    container_name: db
    restart: unless-stopped
    tty: true
    ports:
      - "3306:3306"
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_ROOT_PASSWORD: password
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    volumes:
      - dbdata:/var/lib/mysql/
      - ./mysql/my.cnf:/etc/mysql/my.cnf
    networks:
      - app-network

#Docker Networks
networks:
  app-network:
    driver: bridge
#Volumes
volumes:
  dbdata:
    driver: local

(参考)docker-composeの処理内容詳細


##4. Dockerfileの作成
$ vim Dockerfile

vimエディタでiをクリックしてinsertモードに入り、以下をコピペ。

コピペ後は、esc + :wqで保存して終了。

Dockerfile
FROM php:7.3-fpm

# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/

# Set working directory
WORKDIR /var/www

# Install dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl \
    libonig-dev \
    libzip-dev

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install extensions
RUN docker-php-ext-install pdo_mysql zip exif pcntl
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
RUN docker-php-ext-install gd

# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

# Copy and change existing application directory permissions
COPY --chown=www:www . /var/www

# Change current user to www
USER www

# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]

FROM php:7.2-fpm
ベースイメージにphp:7.2-fpmを指定。

▼php:7.2-fpm
PHP-FPMがインストールされているDebianベースのイメージ。

(参考)Dockerfileの処理内容詳細


###5. PHPの構成 ディレクトリPHPの中にlocal.iniを作成する。
$ mkdir php
$ vim php/local.ini
local.ini
upload_max_filesize=40M
post_max_size=40M

例として、PHPの構成として、アップロードできるファイルサイズ上限を40Mに設定している。

PHPの構成が完了したら、NginxでFastCGIサーバーとしてPHP-FPMを使用するように設定する。


##NginxとPHP-FPM NignxはApachと異なりPHPを直接処理できない。このため、**PHP-FPMと接続してPHPを処理できるようにする**。

PHP-FPMはFast-CGI。Fast-CGIとは、WEBサーバー上でプログラムを動かすためのCGI(Common Gateway Interface)の改良版。Fastは速いの意味。

次のNginxの設定では、Fast-CGIとしてPHP-FPMを使うための設定を記述する。


##6. Nginxの設定 nginx/conf.dディレクトリにapp.confファイルを作成する。
$ mkdir -p nginx/conf.d
$ vim nginx/conf.d/app.conf

vimエディタでiをクリックしてinsertモードに入り、以下をコピペ。

コピペ後は、esc + :wqで保存して終了。

app.conf
server {
    listen 80;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/public;
    location ~ \.php$ {
        try_files $uri =404;
        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;
    }
    location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }
}

conf.d
.dはディレクトリ名であることを明示。
nginxではconf.d配下にあるすべての.confファイルを読み込む設定がされている。

設定ファイルの読み込み指示例
include /etc/nginx/conf.d/*.conf;

server
httpのサーバーの設定。

index
indexディレクティブ。URIが/で終わる場合(ディレクトリが指定されている)場合にリダイレクトするファイルを指定する。

indexディレクティブの例
index index.php index.html;

リクエストされたURIが/hoge/の場合に、index.phpがあれば、hoge/index.phpにリダイレクトする。ない場合はhoge/index.htmlにリダイレクトする。

デフォルトはindex index.htmlとなっている。

listen 80
listenディレクティブ。nginxサーバーが使用するポート番号に80を指定。

error_log
エラーログを書き込むためのファイルを指定。

access_log
アクセスログを書き込むためのファイルを指定。

root
ドキュメントルートのディレクトリを指定する。
「/var/www/public」を指定している。

location
特定のuriでリクエストがきた場合の処理を設定。prefixを使って指定する(完全一致や正規表現など)。

指定したuriに一致したら{ }内の処理を実行する。

location <prefix> <uri> {
    処理
}

▼正規表現の指定

prefix 内容
なし 前方一致
= 完全一致
~ 正規表現(大文字・小文字を区別する)
~* 正規表現(大文字・小文字を区別しない)

####実例(PHP-FPMの設定)
以下はNginxをPHP-FPMに接続する設定。

    location ~ \.php$ {
        try_files $uri =404;
        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;
    }

正規表現で、\.php$ (末尾が.php)なら処理を実行。

####・try_files
指定したパスの存在確認をする。(if文に似た処理)
上記であれば、.phpにアクセスした場合は404を返す。

####・fastcgi_split_path_info
リクエストで渡されたURIを2分割する。

fastcgi_split_path_info ^(正規表現1)(正規表現2)$;

▼正規表現1
$fastcgi_script_nameの値になる。
ここでは、(.+.php)なので、「*.php」が該当。

▼正規表現2
$fastcgi_path_infoの値になる。
ここでは、(/.+)なので、*.php/以下が該当。

▼実例
例えばリクエストが/show.php/article/0001の場合以下のようになる。

$fastcgi_script_name=$document_root/show.php
$fastcgi_path_info=article/0001

####・fastcgi_pass アドレス
Fast-CGIサーバーのアドレスを指定する。

####・include ファイル
指定したファイルを読み込む。
ここでは設定ファイルとしてfastcgi_paramsを読み込んでいる。

DebianやUbuntuの場合設定ファイルはデフォルトで/etc/nginx/fastcgi_paramsにある。
NGINX PHP FastCGI Example

####・fastcgi_index ファイル
URIのパスがスラッシュ/で終わる(ディレクトリを指定)場合に開くファイルを指定。

####・fastcgi_param SCRIPT_FILENAME ファイル
実行するファイル名を指定する。

$document_root$fastcgi_script_nameなので、ドキュメントルートの後に、$fastcgi_script_nameの値が続く。

▼$fastcgi_script_name
fastcgi_split_path_infoの一つ目の正規表現が該当する。つまり「*.php」となり、リクエストされたURIと一致するphpファイルが実行される。

####fastcgi_indexとfastcgi_param SCRIPT_FILENAME
渡されたURIによって使用するphpファイルを切り替える処理になる。

fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;

上記設定に対して、/page.phpが渡された場合、SCRIPT_FILENAMEが処理され、/home/www/scripts/php/page.phpが実行される。

一方、URIの終わりがスラッシュで、/page.php/の場合、fastcgi_indexが処理され、home/www/scripts/php/index.phpが実行される。

####・fastcgi_param PATH_INFO
パスの情報。
ここではリクエストされたパスの.php以降の内容が入る。

・(参考)Nginx http_fastgis_modules


###2つ目のlocationの処理内容
location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }

リクエストされたURIが/*(前方一致)の場合、処理を実行する。

####・try_files $uri $uri/ /index.php?
ファイルの存在確認をしあれば実行。なければ次のファイルの存在確認を行う。
存在確認する優先順位は、$uri, $uri/, /index.php?となる。

####・gzip_static on;
gzipで圧縮済みのファイル「.gz」があればそちらを配信する。


##7. MySQLの設定 mysqlディレクトリの中にmy.cnfファイルを作成する。
$ mkdir mysql
$ vim mysql/my.cnf

vimエディタでiをクリックしてinsertモードに入り、以下をコピペ。

コピペ後は、esc + :wqで保存して終了。

app.conf
[mysqld]
general_log = 1
general_log_file = /var/lib/mysql/general.log

ここではMySQLのログの設定をしている。

####・general_log
値を1(or ON)にするとログを出力する。
0(or OFF or 記述なし)の場合はログ出力をしない。

####・general_log_file
指定したファイルにログを出力する。


##7. コンテナ起動 docker-compose.ymlのあるディレクトリで以下を実行する。
$ docker-compose up -d app

サービスappを起動すれば、linkでwebserver, dbもつながっているため同時に起動する。

-dは デタッチド・モード。バックグラウンドでコンテナを実行するため、コンテナ起動後もそのターミナルでコマンドが打てる状態になる。

▼(補足)サービスを指定しない場合
サービスの指定がなければ、docker-composeに記述されたすべてのサービスが起動する。

###コンテナの起動状況の確認
$ docker psコマンドで起動中のコンテナ一覧を表示できる。

$ docker ps
CONTAINER ID   IMAGE                       COMMAND                  CREATED          STATUS          PORTS                                      NAMES
04012cd50d18   mysql:5.7.22                "docker-entrypoint.s…"   6 minutes ago    Up 6 minutes    3306/tcp, 0.0.0.0:3306->3306/tcp           db
6d0cd9138856   app_php-fpm                 "docker-php-entrypoi…"   6 minutes ago    Up 6 minutes    9000/tcp                                   app
f02cf8788728   nginx:alpine                "/docker-entrypoint.…"   6 minutes ago    Up 6 minutes    0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   webserver

docker-composeのサービスで定義した、app, webserver, dbが起動している。

###ブラウザで確認

localhost:80を入力するとLaravelのwelcome.blade.phpが表示される。

image.png


##(補足)ブラウザ表示でエラーが出た場合の対処法 以下のようなエラーが出たらPHPのバージョンを上げ、インストールするバンドルやエクステンションを変更することで解決できる。

Fatal error: Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= x.x.x". You are running y.y.y. in /var/www/vendor/composer/platform_check.php on line 24

PHPバージョンエラー対処法


以上。
1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?