ここでは、Laravelの開発環境をDockerを用いて構築する方法についてご紹介します。
LaravelはComposerを使えば容易にインストールできますが、Dockerを利用することでさらに実践的な開発環境を用意することができます。
今回はフレームワークとしてLaravel、アプリケーションサーバにNginx、データベースにMySQL、Laravelと併せて用いられることが多いフロントエンドフレームワークであるVue.jsを採用した場合について見ていきます。

Dockerは近年非常に注目されている仮想化技術であり、実際の開発現場でも活躍しています。
Laravelも世界的に最も人気のPHPフレームワークのひとつで、幅広いスケールの開発に柔軟に対応できます。
Laravel + Nginx + MySQL + Vue.jsはかなり本格的で実践レベルでも使われている構成になります。

今すぐLaravelを学びたいなら、プログラミング経験の浅い方でも安心して始められるスクールがおすすめです。
現役エンジニアが専属のパーソナルメンターとして学習をサポートしてくれます。
まずは無料体験・無料キャリアカウンセリングにお申し込みください!
PHP/Laravelコース

事前知識

事前知識としてLinuxやインフラの知識、Dockerの基礎知識、Laravelの基礎知識などが必要になってきます。
ここでは簡単にDockerとLaravelについて説明しますが、開発に必要な各種知識は調べながら進めてください。
また、コメントやTwitterなどでお気軽にご不明点を質問していただいても構いません。

Dockerについて

なぜ開発の際にDockerのような仮想環境を利用するのでしょうか?

例えば、Aというパッケージ(プログラム)が内部的にBとCというパッケージを利用しているとします。
このときAを使うためには、BとCが必要ということになりますが、AというパッケージはVer.1.0のBとVer.2.0のCにしか対応していないとします。
これはパッケージ間の依存関係と呼ばれるもので、Ver.2.0のBを使用するとAがうまく動作しなくなってしまうかもしれません。

つまり開発を行うコンピュータをひとつのプロジェクトにフィットさせると、プログラムをアップデートした場合などに不具合が生じてしまう、といったことが起こるのです。
そこでプロジェクトごとに環境を隔離し、同じプログラムを別のバージョンで利用したりそれぞれが互いに影響を与えないようにするのが仮想化技術になります。

Dockerはコンピュータ上にコンテナと呼ばれる隔離された環境を構築することができるオープンソースのソフトウェアになります。
コンテナとは、アプリケーションの実行に必要なプログラムやライブラリなどをパッケージングしたものになります。
Dockerを利用することで得られるメリットは以下のとおりです。

  • OSのプロセスから切り離した環境で開発ができる
  • 同様の環境を容易に再現できるため、複数人での開発でも活躍する
  • 本番環境を再現した環境で開発ができるため、トラブルを防げる
  • コンテナを別のプロジェクトで使い回すことができる
  • 他の仮想化技術と比較して、起動が早く高いパフォーマンスを誇る

さらに自分が用意したコンテナだけではなく、誰かがつくったコンテナを利用することもできます。
クラウド上で誰かが公開しているプログラムを閲覧したり利用したりできるGitHubのように、DockerにはDocker Hubがあります。
このDocker Hubからコンテナを構成する元となるDockerイメージというものをダウンロードすれば、簡単に環境を構築できます。

今回はこのようなレジストリによって提供されるDockerイメージを使うのではなく、カスタムのDockerイメージを用意していきます。

Docker Compose

Docker Composeは、複数のDockerイメージを組み合わせて使いたい場合に使います。
今回の場合は、Laravel (+Vue.js) + Nginx + MySQLという3つのコンテナをDocker Composeによって統合管理する、ということを行います。

現場を意識した本格的な学習カリキュラムで、本物のスキルを身につけたいならこちら!
困ったときにいつでも相談できるバディ制度でわからないこともすぐに解決できます。
プログラミングスクールといえば【RUNTEQ】

Laravelについて

Laravelは世界的に人気の高いPHPのフレームワークのひとつです。
PHPのデファクトスタンダードといえるフレームワークで、ここ数年かなり支持を伸ばしています。
さらに、Rubyの代表的なフレームワークであるRuby on RailsやPythonのDjangoと比較しても最もホットなWeb開発フレームワークといっていいでしょう。

Laravelについて詳しく知りたい方はこちらの記事をご覧ください。

Dockerのインストール

DockerをWindows、もしくはMacで使う場合には、Docker Desktopというアプリケーションをインストールする必要があります。
DockerはLinux上で動作するため、WindowsでDockerを利用したい場合にはWSL2(Windows上でLinuxを使うためのアプリケーション)をインストールしなければいけません。
使っているコンピュータの環境によって操作が異なりやや手順が複雑なので、頑張って調べてみてください。
詳しいインストール方法はこちら(公式)
Windows版Docker Desktopのダウンロードはこちら
Mac版のDocker Desktopのダウンロードはこちら

Docker DesktopをWindowsで使う際の注意

WindowsでWSL2をインストールした場合は、異常にメモリを消費してしまうことを防ぐため、設定値を調整しておくのがおすすめです。
この措置をしておかないと、コンピュータが支障をきたすレベルで重くなる場合があります。

まずは以下のようなルートディレクトリに.wslconfigというファイルを作成します。

C:\Users\[user_name]\.wslconfig

.wslconfigの中身は以下のとおりです。
memoryの値は好みに合わせて調整してください。

[wsl2]
memory = 2GB
swap=0

開発環境構築の準備

ディレクトリ構成

最終的な全体のディレクトリ構成は以下のようになります。
少し量が多いですが、それぞれのファイルはわからなければコピペで大丈夫です。

./
|- docker/
|   |- mysql/
|   |   |- Dockerfile
|   |   |- my.cnf
|   |
|   |- nginx/
|   |   |- default.conf
|   |   |- Dockerfile
|   |
|   |- php/
|       |- Dockerfile
|       |- php.ini.def
|       |- php.ini.prod
|
|- src/
|- docker-compose.yml
|- .env

それぞれのファイルの中身について解説していきます。

docker-compose.yml

docker-compose.ymlyml(ヤムル)ファイルという設定値を書くためのファイルです。
Laravel(+Vue.js)とNginxとMySQLのそれぞれのコンテナに関する情報をまとめて管理できます。
それぞれのコンテナのより詳細な設定は、dockerディレクトリの中に記述します(後述)。

version: '3.8'

networks: laravelnet;

volumes:
  mysql-data:
  vendor-store:
  node_modules-store:

services:
  app:
    build:
      context: .
      dockerfile: ./docker/php/Dockerfile
    volumes:
      - ./src/:/var/www/html
      - vendor-store:/var/www/html/vendor
      - node_modules-store:/var/www/html/node_modules
    environment:
      - DB_CONNECTION=mysql
      - DB_HOST=mysql
      - DB_PORT=3306
      - DB_DATABASE=${DB_NAME}
      - DB_USERNAME=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}

  nginx:
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    volumes:
      - ./src/:/var/www/html
    ports:
      - ${WEB_PORT}:80
    depends_on:
      - app

  mysql:
    build:
      context: .
      dockerfile: ./docker/mysql/Dockerfile
    volumes:
      - mysql-data:/var/lib/mysql
    ports:
      - ${DB_PORT}:3306
    environment:
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      TZ: 'Asia/Tokyo'
    command: --default-authentication-plugin=mysql_native_password

versionはDocker Composeの書式のバージョン番号です。

networksにはDocker Composeでまとめたコンテナを接続するネットワークの名前を指定します。
ネットワークは複数組み合わせて使うこともできます。

volumesには使用するボリュームの名前を指定します。
Dockerでは必要なときにコンテナを起動して、不要になったコンテナは破棄する、というような使い方をします。
そのため、コンテナ内で使用したデータはコンテナを破棄すると消えてしまいます
残しておきたいデータはコンテナとは別に、ボリュームとして管理します。
ここでは、データベースのデータを残しておくためのmysql-data、Laravel内のデータを残しておくためのvendor-stor、Node.jsのパッケージを残しておくためのnode_modules-store、の3つのボリュームを用意しています。
こうして用意したボリュームをコンテナにマウントすることでデータを永続化することができるのです。

serviceでは各コンテナの定義を記述します。
ここではLaravelやVue.jsといったフレームワークを含むアプリケーション全体のコンテナであるapp、Nginx用のnginx、MySQL用のmysqlという3つのサービスを定義しています。

既存のDockerイメージを利用する場合はimageプロパティにイメージ名を設定するのですが、ここではそれぞれのイメージを自作するためbuildプロパティを使用しています。
今回はdocker-compose.ymlファイルの位置とコンテナに関する更に詳しいビルド情報を書いたDockerfileが別のディレクトリにあるので、contextプロパティを設定しています。
contextプロパティには後ほどビルドコマンドを実行する際のディレクトリ(docker-compose.ymlがあるディレクトリ)を指定します。
また、dockerfileプロパティにDockerfile(後ほど作成)をの場所を指定します。

volumesプロパティには、コンテナにマウントしたいボリュームやホスト側のデータを指定します。
コロン( : )の左側がホスト側のディレクトリやボリューム、右側がコンテナ内を指しています。
Laravelアプリケーションの実装はsrcディレクトリ内に行っていくので、マウントしておきます。
それ以外のボリュームについてもお好みのパスにマウントしてください。

environmentプロパティは、各種の環境変数を設定します。
今回はデータベースに接続するためのパスワードやデータベース名などを指定しています。
さらに、パスワードなどを直接書いてしまうとセキュリティ上あまり好ましくないので、別途.envファイルに書いておきその値を読み込んでいます。

potsプロパティはポートのマッピングを指定します。
左がホスト側のポート番号、右がコンテナ側のポート番号になります。
ホスト側からブラウザを開いてWebアプリ開発をする場合は左のポート番号を使うことになります。

depends_onプロパティを指定することで、コンテナ間の依存関係を指定します。
ここではnginxコンテナにappコンテナの依存を指定していますので、必ずappコンテナが起動したあとにnginxコンテナが起動するようになります。

.env

.envファイルにはGitリポジトリなどで共有するのが好ましくないパスワードなどの情報を書いておきます。
.gitignoreに含めておき、こういった情報が流出してしまうことを防ぎます。

WEB_PORT=80
DB_PORT=3306

DB_NAME=db_name
DB_USER=user_name
DB_PASSWORD=password
DB_ROOT_PASSWORD=password

docker-compose.ymlで利用するための設定値をこちらに記述しておきます。

Dockerfile

DockerfileDockerのビルドコマンドを使用した際に実行される、コンテナに対する操作をまとめたファイルになります。
ベースとなるイメージの指定や、そのイメージをプロジェクトに合わせて調整するためのコマンドを記述します。
ここではappコンテナ、nginxコンテナ、mysqlコンテナそれぞれに対して対応するディレクトリ(./docker/php/、./docker/nginx/、./docker/mysql/)にDockerfileをつくります。

./docker/php/Dockerfile

# ベースイメージ
FROM php:7.4.1-fpm

# php.iniのコピー
# 開発はphp.ini.dev、本番はphp.ini.prod
COPY ./docker/php/php.ini.dev /usr/local/etc/php/php.ini

# Composerのインストール
COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer

# Node.jsのインストール
COPY --from=node:10.22 /usr/local/bin /usr/local/bin
COPY --from=node:10.22 /usr/local/lib /usr/local/lib

# パッケージのインストール
RUN apt-get update && \
	apt-get -y install \
	git \
	zip \
	unzip \
	vim && \
	docker-php-ext-install pdo_mysql bcmath && \
	pecl install xdebug && \
	docker-php-ext-enable xdebug

# カレントディレクトリ
WORKDIR /var/www/html

COPY ./src/ /var/www/html/

# 権限の変更
RUN chown -R www-data:www-data /var/www/html
RUN chmod -R 777 /var/www/html/storage
RUN chmod -R 777 /var/www/html/bootstrap/cache

# Node.jsのエラー回避用
RUN npm install n -g && \
    n stable && \
    apt purge -y nodejs npm && \
    npm rebuild && \
    npm run dev

FROMコマンドでベースとなるイメージを指定します。
今回はLaravelを使用しますので、ベースイメージにはPHPを使います。
さらに、アプリケーションサーバにはNginxを採用しているため、FastCGIで動作するPHP-fpmのイメージにしています(アプリケーションサーバにApacheを採用した構成に変更する場合には通常のPHPに変更してください)。

COPYコマンドではホスト側のファイルをコンテナ何にコピーします。
4~13行目では、PHPの設定ファイルやComposer、Node.jsをコピーしています。
その他にも、29行目でアプリケーション本体を反映するためにも使用しています。

RUNコマンドではコンテナ内で実行したいコマンドを呼び出します。
ここではパッケージのインストールや権限の変更などに使っています。

./docker/nginx/Dockerfile

# ベースイメージ
FROM nginx:1.18-alpine

# タイムゾーンの環境変数設定
ENV TZ=UTC

# configファイルのコピー
COPY ./docker/nginx/*.conf /etc/nginx/conf.d/

# カレントディレクトリの設定
WORKDIR /var/www/html

./docker/mysql/Dockerfile

# M1 Macの場合のベースイメージ
# FROM --platform=linux/x86_64 mysql:8.0

# ベースイメージ
FROM mysql:8.0

# タイムゾーンの環境変数設定
ENV TZ=UTC

# configファイルのコピー
COPY ./docker/mysql/my.cnf /etc/my.cnf

php.ini

php.iniはPHPの設定ファイルです。
今回は開発用のphp.ini.devと本番環境用のphp.ini.prodを分けて用意しています。
内容はあくまで参考ですので、ご自分の好みに合わせて変更してください。

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 = /var/log/php/php-error.log
default_charset = UTF-8

[Date]
date.timezone = Asia/Tokyo

[mysqlnd]
mysqlnd.collect_memory_statistics = on

[Assertion]
zend.assertions = 1

[mbstring]
mbstring.language = Japanese

[xdebug]
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.log=/tmp/xdebug.log
xdebug.log_level=0
zend.exception_ignore_args = on
expose_php = off
max_execution_time = 30
max_input_vars = 1000
upload_max_filesize = 64M
post_max_size = 128M
memory_limit = 256M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = off
display_startup_errors = off
log_errors = on
error_log = /var/log/php/php-error.log
default_charset = UTF-8

[Date]
date.timezone = Asia/Tokyo

[mysqlnd]
mysqlnd.collect_memory_statistics = off

[Assertion]
zend.assertions = -1

[mbstring]
mbstring.language = Japanese

[opcache]
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 4000
opcache.validate_timestamps = 0
opcache.huge_code_pages = 0
opcache.preload = /var/www/preload.php
opcache.preload_user = www-data

default.conf

default.confはNginxの設定ファイルです。
ドキュメントルートをコンテナ内のアプリケーションのルートに合わせておきます。
それ以外の設定値はご自由に変更してください。

server {
	listen 80;

	root /var/www/html/public;

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	add_header X-Frame-Options "SAMEORIGIN";
	add_header X-Content-Type-Options "nosniff";

	index index.php index.html index.htm;

	charset utf-8;

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

	error_page 404 /index.php;

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

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

my.cnf

my.cnfはMySQLの設定ファイルです。

[mysqld]
user=mysql
character_set_server = utf8mb4
collation_server = utf8mb4_0900_ai_ci

# タイムゾーン
default-time-zone = SYSTEM
log_timestamps = SYSTEM

# エラーログ
log-error = mysql-error.log

# スロークエリログ
slow_query_log = 1
slow_query_log_file = mysql-slow.log
long_query_time = 1.0
log_queries_not_using_indexes = 0

# ログ
general_log = 1
general_log_file = mysql-general.log

[mysql]
default-character-set = utf8mb4

[client]
default-character-set = utf8mb4

プログミングでわからないことがあったら、その道のプロに質問するのが一番!
現役で活躍中のエンジニアと繋がって、効率的にWeb開発のスキルを身につけましょう。
プログラミング学習のスキルプラットフォーム【MENTA】

開発環境の構築

たくさんのファイルがありましたが、準備お疲れ様でした。
続いては実際にDockerコンテナの起動やLaravel、Vue.jsのインストールを行っていきます。

Dockerコンテナのビルドと起動

Docker Composeのコンテナの基本操作は以下のとおりです。
ここではdocker-compose.ymlファイルがあるディレクトリでbuildコマンドとupコマンドを実行してください。
コンテナを使い終わったら、downコマンドでコンテナを停止しておきます。

$ # コンテナのビルド
$ docker-compose build

$ # コンテナの起動(-dオプションでバックグラウンドでの起動)
$ docker-compose up -d

$ # コンテナの停止と破棄
$ docker-compose down

コンテナのビルドと起動に成功したかを確認するために、コンテナの状態を確認するpsコマンドを実行してみます。
app、nginx、mysqlの3つのコンテナすべてのStateがUpになっていれば成功です。

$ docker-compose ps

      Name                     Command               State                          Ports
----------------------------------------------------------------------------------------------------------------
xxx_app_1     docker-php-entrypoint php-fpm    Up      9000/tcp
xxx_mysql_1   docker-entrypoint.sh --def ...   Up      0.0.0.0:3306->3306/tcp,:::3306->3306/tcp, 33060/tcp
xxx_nginx_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:80->80/tcp,:::80->80/tcp

LaravelとVue.jsのインストール

続いてexecコマンドでappコンテナの中に入ります。

$ docker-compose exec app bash

コンテナの中に入ったら、ComposerからLaravelをインストールします。

root@xxx:/var/www/html# comoposer create-project --prefer-dist laravel/laravel .

さらに、npmでVue.jsのインストールを行います。

root@xxx:/var/www/html# npm install
root@xxx:/var/www/html# npm install -D vue

あとはLaravelの設定ファイルをDockerコンテナの設定に合わせれば(データベース設定など)、開発環境が完成します。

まとめ

今回はDockerを使ってLaravel + Nginx + MySQL + Vue.jsという、実際の開発でもよく利用されている組み合わせで開発環境を構築してきました。
Dockerは高いパフォーマンスを誇ることで非常に注目を集めている仮想化技術です。
インフラ周りの総合的な知識も必要となりますが、Webエンジニアなら絶対に身につけておくべき知識となっています。

ひとりではなかなかプログラミングの学習が続かない、未経験だから不安が多い、という方はプログラミングスクールを利用してみるのも有効です。
本物のエンジニアに学ぶことで、時間がない方でも最短でスキルを身につけることができます。
現役エンジニアのパーソナルメンターからマンツーマンで学べる

お悩みの方は、まずは無料キャリアカウンセリングにお申込みください。

おすすめ記事

この記事のタグ