自作Webアプリを作る!その6 - DockerでLaravel+MySQL開発環境構築

システム開発

こんにちは、いちのです!

今回は、前回選定した言語・フレームワークで開発環境を構築する!です!

記事を書くにあたって環境構築してみるのにとても苦労したので投稿が遅くなってしまいました・・つかれた。くじけそうでした。

というわけで、今回環境構築するにあたって私が四苦八苦した様をご覧ください。

まずは調査

新しいことをするのでまずは調査!です。

今回作りたい環境は、

  • laravel(PHP)の環境
  • DBも使いたい(MySQLで良さそう)
  • ローカルで動作確認するのにWebサーバーも必要

調べてみるとやたらと出てくる「Docker」の文字。そういえば最近よく目にします。

Dockerとは?

一台のマシン上に複数の隔離された環境を構築する軽量なコンテナ型の仮想化技術です。

https://laraweb.net/environment/8652/

だそうです。

隔離された仮想環境が作れる・・・私みたいに色んな開発環境入れちゃってる人にぴったりなやつ!

これやってみよう!(単純)

Docker前準備

まずは前準備として、Hyper-V(仮想化機能)の有効化が必要らしいです。はじめてきいた・・・。

あ、因みに今まで触れてこなかった気がしますがWindows10での環境構築です。

Windows10のproならコントロールパネルから「Windowsの機能の有効化または無効化」を開くと設定できるようです。設定が見つからない場合はBIOSで設定の変更が必要だとか。

proでない場合はまた別の方法があるようなので、そちらは調べてみてください。

Dockerインストール

まずはDockerを使えるようにするために、「Docker Desktop」をインストールします。

Docker Desktopのインストール

下記のリンクから公式サイトへアクセスして、インストーラーをダウンロードします。

↓「Download from Docker Hub」をクリック

↓「Get Docker Desktop for Windows」でインストーラーのexeがダウンロードされます。

インストーラーを実行してデフォルトのままインストールします。

↓インストールが完了するとこんな表示が出ます。
 「Close and restart」ボタンを押してPCを再起動しましょう。

WSLのインストール

再起動してDockerが起動すると、こんな警告が表示されます。

WSLもインストールしないと使えないようなので、ダイアログ内のURLへアクセスしてこれもインストールします。

これで無事Dockerが起動できました。

ちょっと放置すると「Get started width Docker in a fer easy steps!」と表示されて簡単チュートリアルができるようになっていましたが私はスルーしました。やっとけばいいのに。

Dockerのインストール確認

一応、本当にちゃんとDockerがインストールされたかを確認します。1つずつ確認するの大事。

「Windowsキー+R」で検索窓に「cmd」と入力し、コマンドプロンプトを開きます。

「docker」と打ち込んでEnterキー。「Usage: docker [OPTIONS] COMMAND」の文字列と、コマンド一覧が表示されればOKです。

エディタについて

開発にあたって、便利なエディタはたくさんあると思います。

私の場合は今まで仕事で使っていた「Visual Studio Code」が既にインストールされていました。

それなりに使い慣れている&ソースをいじりつつターミナルが使いやすい(気がする)ので、今回もVSCodeを使っていきます。

コンテナ作成

Dockerについて全然説明してないのでいきなりコンテナと言われて「???」な方は調べてみてください。

正直私もちゃんとわかってない気がします。

本当はもっと勉強して理解した方が良いものかと思います。

でも私の場合、いくら色んな解説を読んでも実際やってみないとピンとこないことが多いので、まずは「入門」とされるサイト等に従って環境を作って、ある程度動かしてみてから細部を勉強するというスタイルをいつもとっています。←「急がば回れ」ができない人

最終的に、Laravel・MySQL・Nginx(サーバー)のコンテナが出来上がる予定です。

今回の環境構築にあたって大いに参考にさせていただいたのがこちらのページです。

では1つずつ見ていきましょうー。

Laravelコンテナ

まずはLaravelコンテナを作ってトップ画面を表示するところまで。

任意の場所にプロジェクトディレクトリlaravel_dockerを作成し、作成したディレクトリに移動します。本環境では/Users/reffect/Desktopの下に作成しています。

https://reffect.co.jp/laravel/finally-understand-laravel-on-docker#Laravel

私の場合はCドライブの勉強用ディレクトリ内に「mytasks」ディレクトリを作成しました。

Windowsで任意の場所にディレクトリを作成し、VSCodeでそのフォルダを開きます。

docker-compose.yml

docker-compose.ymlを利用することで複数のコンテナを一度に作成、制御することが可能になり効率的に環境構築を行うことができます。

https://reffect.co.jp/laravel/finally-understand-laravel-on-docker#docker-composeyml

まずはLaravelに関する部分。

version: '3.7'

services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: php
    volumes:
      - ./src:/var/www/html
    ports:
      - "8000:8000"

Dockerfile

Dockerfileにはコンテナに利用するイメージ情報とそのイメージに追加するパッケージや構成変更を行うコマンド等を記述することができます。イメージ情報に構築するユーザ毎の個別の設定を追加しておくことで全く同じ環境を容易に構築することができます。

https://reffect.co.jp/laravel/finally-understand-laravel-on-docker#Dockerfile

mytasksディレクトリに「Dockerfile」というファイルを作って下記の内容で保存します。

拡張子はいりません。

FROM php:7.4-fpm-alpine

RUN docker-php-ext-install pdo pdo_mysql

コンテナ作成

ここまで出来たらコンテナを作成してみます。

VSCodeのターミナルで下記を打ち込みます。

$ docker-compose up -d

これでバックグラウンドでDockerが起動し、コンテナが稼働している状態になるようです。

下記コマンドでコンテナのステータスを確認します。

$ docker-compose ps -a
Name              Command              State                Ports
-------------------------------------------------------------------------------
php    docker-php-entrypoint php-fpm   Up      0.0.0.0:8080->8080/tcp, 9000/tcp

phpのStateがUpになっていればOKです。

Laravelのインストール

ターミナルで以下を実行します。

$ docker run --rm -v C:\***\mytasks\src:/app composer create-project --prefer-dist laravel/laravel

開発サーバーの起動

$ docker exec -it php php artisan serve --host=0.0.0.0 --port=8000

これでphpコンテナのコマンドをローカルから実行できる・・・らしいのですが、環境のせいか「Could not open input file: artisan」(artisanが開けません)と言われてしまったので、下記で起動しました。

$ cd src\laravel
$ php artisan serve --host=0.0.0.0 --port=8080

これでブラウザから「127.0.0.1:8000」にアクセスするとLaravelの初期画面が無事表示されました。ふー。

ていうかまだサーバー入れてないのに・・Laravel入れただけでそこまでしてくれるなんてなんという親切設計・・・!!

MySQLコンテナ

次はMySQLです。

docker-compose.yml

docker-compose.ymlファイルのservicesにmysqlを追加します。

version: '3.7'
services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: php
    volumes:
      - ./src:/var/www/html
    ports:
      - "8000:8000"
  mysql:
    image: mysql:8.0
    container_name: mysql
    ports:
      -  "3306:3306"
    volumes:
      -  ./db:/var/lib/mysql
      -  ./my_conf:/etc/mysql/conf.d
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: laravel

解説のページではmysqlのバージョンが違いますが、最新バージョンを調べて書き換えました。

docker-composeのバージョンは最新を調べ忘れてそのままです・・・あんまりよくないです。

Volumes

docker-compose.ymlに書いた「db」「my_conf」ディレクトリを
最初に作った「mytasks」ディレクトリの直下に作ります。

私はこういうの、コマンドではなくUIでやる人です。エンジニアっぽくない。

my_confの中に「mysql8.0.cnf」ファイルと作成し、下記のように文字コードの設定を書きます。

[mysqld]
character-set-server=utf8mb4

[client]
default-character-set=utf8mb4

ファイル名はmysqlのバージョンでつけているようだったのでそれに倣ってみましたが、正しいかどうか自信ないです・・後ほどはっきりしたことがわかったら追記します。

コンテナの作成

MySQLのコンテナを作る前に、さっき作ったLaravelコンテナを一旦削除します。

$ docker-compose down
Stopping php ... done
Removing php ... done
Removing network mytasks_default

その後コンテナ作成を行うと、今度はLaravel・MySQLの2つのコンテナが作成されます。

$ docker-compose up -d
Creating network "mytasks_default" with the default driver
Creating php   ... done
Creating mysql ... done

起動チェックも忘れずに。

$ docker-compose ps -a
Name               Command              State                 Ports
---------------------------------------------------------------------------------
mysql   docker-entrypoint.sh mysqld     Up      0.0.0.0:3306->3306/tcp, 33060/tcp
php     docker-php-entrypoint php-fpm   Up      0.0.0.0:8080->8080/tcp, 9000/tcp

LaravelからDBへの接続

まだ具体的に使わないですが、LaravelからDBへアクセスできるようにDBの情報を設定ファイルに書いておきます。

「mytasks\src\laravel」ディレクトリの中に「.env」というファイルがあります。

その中の下記の部分を、先ほどdocker-compose.ymlファイルに書いたMySQLの設定にあわせて書き換えます。

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=password

Nginxコンテナ

Webサーバーってやっぱりあれでしょ?Apacheでしょ?と思ってました。違いました。

最近はこんなのも出てきているらしいです。まぁもともとApacheだってそんなに使いこなせていなかったのでそこが変わったところで大した差はないでしょう。(不勉強すぎる・・・)

docker-compose.yml

これまでと同じように、今度はNginxについてdocker-compose.ymlに追記します。


version: '3.7'
services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: php
    volumes:
      - ./src:/var/www/html
    ports:
      - "9000:9000"
------ 略 ---------
  nginx:
    image: nginx:stable-alpine
    container_name: nginx
    ports:
      -  "8080:80"
    volumes:
      -  ./src:/var/www/html
      -  ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      -  php
      -  mysql

nginxの追記の他に、phpの「port」も変更しています。

phpのポートを先ほどまで8000:8000に設定していましたが、9000:9000に変更を行ってください。Nginxと通信する際にポート9000を利用するためです。

https://reffect.co.jp/laravel/finally-understand-laravel-on-docker#docker-composeyml-3

nginxの設定ファイル

mytasksディレクトリ直下に、「nginx」ディレクトリを作成し、その中に新しく「default.conf」というファイルを配置します。内容は下記です。

server {
    listen 80;
    index index.php index.html;
    server_name localhost;
    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/html/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    location ~ \.php$ {
        try_files $uri = 404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php: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 artisan serv」で開発サーバーを起動しなくてもLaravelの初期ページが見られる・・はずでした

初期ページが表示されない問題の解決方法

でも結果は・・・

涙目。

404?そんなわけあるか!さっきちゃんと表示されたの見たもんね!

と思って色々調べました。結構調べた。けど結局大事なことは参考にしていたページに書いてありました。

rootの箇所の/var/www/html/publicがlaravelのインストールディレクトリの下にあるpublicと一致する必要があります。

https://reffect.co.jp/laravel/finally-understand-laravel-on-docker#nginx

そもそも「/var/www/html/public」って何?今作ってるディレクトリ内にはvarなんてないですけど。もしかしてDocker内の仮想Linuxさんのディレクトリ?どうやって確認するの!

と無知丸出しなことを考えていました。多分こんな知識量でやるべきことじゃなかったDocker。

でもなんとか解決しました。

$ docker exec -it php sh  

こうすると、最初に作ったphpコンテナに入ることができます。

そしてコンテナに入ったときのターミナルの表示がこれ。

/var/www/html #

varあるやん!

つまり、ここに「public」ディレクトリがあればさっきの設定値でいけるわけですね。

結果は・・・

/var/www/html # ls
laravel

publicないやん!

そんなわけで、試しにlaravelディレクトリに移動して内容をチェックしてみたところ

/var/www/html # cd laravel/
/var/www/html/laravel # ls
README.md       artisan         composer.json   config          index.php       phpunit.xml     resources       server.php      tests           webpack.mix.js
app             bootstrap       composer.lock   database        package.json    public          routes          storage         vendor

あったー!ありました。こっちでした。

というわけで、default.confのrootを書き換えます。

root /var/www/html/laravel/public;

これでコンテナを削除・作成すると・・・

Illuminate\Foundation\Bootstrap\HandleExceptions::handleError vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem.php

こんなかんじのエラーがブラウザにどーんと表示されました。

これ、調べてみると、「ファイルを読む権限がない」のが原因だとか。

というわけで、色々調べている時に見かけたやつを実行

$ chmod 777 -R storage/

これで無事、Laravelの初期ページがまた表示されました。

おまけのphpMyAdmin

mySQLも入れたけど、「127.0.0.1:3306」にアクセスしてもこれです。

↓こういうのを想像していました。

ん-?こっちも設定が違うのかなー?

なんてとんちんかんなことを考えていましたが、そういう問題じゃない

コンテナ作ったのはmySQLだけ。UIで操作できるphpMyAdminは別物ということをすっかり忘れていました。

ということでphpMyAdminのコンテナも入れてみることに。

docker-compose.yml

おなじみdocker-compose.ymlです。最終的に下記のようになりました。

version: '3.7'
services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: php
    volumes:
      - ./src:/var/www/html
    ports:
      - "9000:9000"
    depends_on: ['mysql']
  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    container_name: phpmyadmin
    environment:
    - PMA_HOSTS=mysql
    - PMA_USER=root
    - PMA_PASSWORD=password
    ports:
    - '8888:80'
  mysql:
    image: mysql:8.0
    container_name: mysql
    ports:
      -  "3306:3306"
    volumes:
      -  ./db:/var/lib/mysql
      -  ./my_conf:/etc/mysql/conf.d
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: laravel
  nginx:
    image: nginx:stable-alpine
    container_name: nginx
    ports:
      -  "8080:80"
    volumes:
      -  ./src:/var/www/html
      -  ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      -  php
      -  mysql

これでコンテナを再作成します。

$ docker-compose down              
Stopping nginx ... done
Stopping mysql ... done
Stopping php   ... done
Removing nginx ... done
Removing mysql ... done
Removing php   ... done
Removing network mytasks_default

$ docker-compose up -d
Creating network "mytasks_default" with the default driver
Creating mysql      ... done
Creating phpmyadmin ... done
Creating php        ... done
Creating nginx      ... done

$ docker-compose ps -a 
   Name                 Command               State                 Ports
---------------------------------------------------------------------------------------
mysql        docker-entrypoint.sh mysqld      Up      0.0.0.0:3306->3306/tcp, 33060/tcp
nginx        /docker-entrypoint.sh ngin ...   Up      0.0.0.0:8080->80/tcp
php          docker-php-entrypoint php-fpm    Up      0.0.0.0:9000->9000/tcp
phpmyadmin   /docker-entrypoint.sh apac ...   Up      0.0.0.0:8888->80/tcp

できたああああああああああああああああ!

これで「http://127.0.0.1:8080/」でLaravel初期ページ、

「http://127.0.0.1:8888/」でphpMyAdminが表示されるようになりました。

おしまい

ほとんど参考ページのまるパクリなソースを順番通りに並べたような記事になってしまいました。

たくさん色んなページを見て色んなところからヒントをもらいながら数時間かけて環境構築しました。

もっと勉強してからやればすんなり解決できたこともあると思いますが、

私はそれだとモチベーションが続かないんです・・・。

この記事がまた誰かの参考になればうれしいです。ほんとに。

そんなわけで、参考にさせていただいたページをいくつか貼っておくので、躓いたりもっと詳しいことが知りたくなったときはぜひ見に行ってみてください!