20200801のMySQLに関する記事は7件です。

MySQLとPostgreSQLでのtimezoneの取り扱いの違い

環境

  • MySQL 5.6
  • PostgreSQL 12
  • Grafana 7.0.0
  • Windows
  • DB,クライアントのタイムゾーンはAsia/Tokyo

内容

DATE型カラム(hogedate)に'2020-07-20'が入っている場合
MySQLでそのカラムをUNIX_TIMESTAMP(hogedate)すると2020-07-19 15:00:00のUNIX TIMESTAMPが得られる。
PostgreSQLでそのカラムをEXTRACT(EPOCH FROM hogedate)すると、2020-07-20 00:00:00のUNIX TIMESTAMPが得られる。

PostgreSQLは全体的にtimezoneを考慮しない方針の様子
SELECT EXTRACT(EPOCH FROM timestamp '2020-07-20 00:00:00')
=> 1595203200 (2020-07-20 00:00:00UTCのUNIX時間)
SELECT EXTRACT(EPOCH FROM timestamp with time zone '2020-07-20 00:00:00')
=> 1595170800  (2020-07-19 15:00:00UTCのUNIX時間)

試してないけど、普通にテーブルに入れて試しても同じ結果になるだろう。
日本国内に閉じたシステムであれば、 無理に考慮してくれない方が扱いやすい。

調べた経緯

GrafanaでMySQL内に入っている日時データを取得してグラフ表示しているが、どうも数が合わない。

DATEカラムを時間軸にするようなグラフを書く場合、$_timeGroupAlias(hogedatecol, '1d', 0)などとGrafanaマクロを使ってると、UNIX_TIMESTAMP(hogedatecol)が取られるが、この場合は、9時間前のUNIX時間が返ってしまう。
例)カラムの値が'2020-07-20'だと、MySQLでその値をUNIX
TIMESTAMP()すると、'2020-07-19 15:00:00'のUNIX時間が帰ってくる。そのあとで、上記例だと1日で丸めるために、86400(1日の秒数)で割って、掛け戻してるため、2020-7-19で丸められてしまう。。。

対応としてはどうするべきなのだろうか?
- Grafanaのマクロを使用しない
  => 基本これかな。面倒だけど。 
- DBのタイムゾーンの設定をしない
  => 今回は扱う必要がないのでこれでもいいけど、DBがUTC、クライアントがAsia/Tokyoの場合の動きを確認?
- PostgreSQLを使う
  => 今回はお遊びツールなのでこれでもいいけど、ちょっと今から返るの面倒だな。
   プロダクトはMySQL/MariaDBなのでDBを2つ入れるのは非力マシンなので避けたいし。
- その他

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【MySQL練習問題】特定のカラムでグルーピングを行い、それぞれのグループの代表レコードを選ぶ

従業員への給与を管理するための salaries テーブルがあります。

emp_no salary from_date to_date
10001 60117 1986-06-26 1987-06-26
10001 62102 1987-06-26 1988-06-25
10002 65828 1996-08-03 1997-08-03
10002 65909 1997-08-03 1998-08-03
499999 74327 2000-11-29 2001-11-29
499999 77303 2001-11-29 9999-01-01

それぞれのレコードにおいて、IDが emp_no の従業員に対して from_date から to_date の期間に付与した給与を salary で表しています。

(テーブルのスキーマとレコードは datacharmer/test_db からお借りしました。)

さて、データベーススペシャリストであるあなたのもとに次のような依頼がきました。

従業員1人ごとに、その人への給与が最大だった期間を抽出してほしい。
もし、最大の期間が複数ある場合は、全て抽出してほしい。

MySQLのクエリのみを用いてこの依頼に応えるには、どうすればよいでしょうか?

誤答

誤答1. GROUP BYとMAXで給与が最大のレコードを抽出する

emp_noGROUP BY し、それぞれのグループの最大値を MAX で出すと考えて、次のようなクエリはどうでしょう?

SELECT
  `emp_no`,
  MAX(`salary`) AS `max_salary`,
  `from_date`,
  `to_date`
FROM `salaries`
GROUP BY `emp_no`
;

残念ながら、これは誤答です。

そもそも、MySQL 5.7.5かそれ以降を使っている場合このクエリはエラーになります。
エラーになるのは、 ONLY_FULL_GROUP_BY という sql_mode がデフォルトで有効になっているためです。
この設定では、 GROUP BY でグルーピングの基準として指定していないカラムを SELECT 内に含める場合、 SUMMAX などの集約関数を使う必要があるのです。
上のクエリの場合、 from_dateto_date がグルーピングの基準でないにも関わらず、単独で登場していますね。

もちろん、一時的に sql_mode から ONLY_FULL_GROUP_BY を取り除けばエラーは出なくなります:

SET SESSION sql_mode=(
  SELECT REPLACE(@@SESSION.sql_mode, 'ONLY_FULL_GROUP_BY', '')
);

ただ、エラーが出なくなっただけで、誤答であることには変わりません。
依頼に次のような要件があったことを覚えていますか?

もし、最大の期間が複数ある場合は、全て抽出してほしい。

そうですね。
GROUP BY を使ってしまうと、emp_no が同じレコードはすべて1つのレコードに集約されてしまうのです。

では、仮に1つしか抽出できなくてもよいとしましょう。依然として誤答です。

根本的な問題は、このクエリで取れる from_dateto_date が正しいものであるという保証、つまり、給与が最大のレコードに対応する期間であるという保証がどこにもないということです。

「え、 MAX で取得したレコードの from_dateto_date が入るんじゃないの?」

MySQLのリファレンスマニュアル によると、GROUP BY でグルーピングの対象になっていないカラムを単独で SELECT しようとした場合、グループ内のどのレコードから SELECT されるかは「不確定」なのです。

実際に僕の手元で実行した結果、 SELECT された from_dateto_date は、給与が最大のレコードのものではなく、グループ内で一番最初に出現したレコードのものでした。

クエリを一見すれば正答に思えるものの、 GROUP BY の挙動を正しく理解することで避けられる誤答です。

誤答2. ORDER BYしたサブクエリをGROUP BY

まずサブクエリで salaries を降順に並び替えて、そのサブクエリを emp_noGROUP BY すると考えて、次のようなクエリはどうでしょう?

SELECT *
FROM (
  SELECT *
  FROM `salaries`
  ORDER BY `salary` DESC
) AS `ordered_salaries`
GROUP BY `emp_no`
;

残念ながら、これも誤答です。

誤答1と同様に、MySQL 5.7.5かそれ以降を使っている場合 ONLY_FULL_GROUP_BY を無効にする必要があるので、その前提で続けます。

サブクエリで salaryORDER BY をしておけば、外側の GROUP BY がそれぞれのemp_no ごとに最初に出現したレコード、
つまり、給与が最大のレコードをグループ内の代表レコードとしてくれるはず、という淡い期待が裏切られる形となりました。

誤答1と同様、複数の期間が該当する場合にも1つしか抽出できない上、結果に含まれる from_dateto_date が正しい保証がありません。
それどころか、 salary が最大であるという保証すらありません。

実際に僕の手元で実行した結果、 SELECT されたのは ORDER BY する前のテーブルでグループ内で一番最初に出現したレコードでした。

正答

正答1. サブクエリで取得した最大を使ってINNER JOIN

まずサブクエリで従業員ごとの最大の給与を取得し、その結果と元のテーブルを INNER JOIN することで、元のテーブルから給与が最大でないレコードを除外することができます。

SELECT `salaries`.*
FROM `salaries`
INNER JOIN (
  SELECT
    `emp_no`,
    MAX(`salary`) AS `max_salary`
  FROM `salaries`
  GROUP BY `emp_no`
) AS `max_salaries`
  ON `salaries`.`emp_no` = `max_salaries`.`emp_no`
  AND `salaries`.`salary` = `max_salary`
;

まず、内側のクエリで emp_no とその従業員の最大の給与を1:1で対応させるテーブルを作っています。
このテーブルと salaries テーブルを INNER JOIN するのですが、その際の条件が2つありますね。

まず1つ目の条件では、 salaries テーブルのそれぞれのレコードについて、作成した対応テーブルから同じ emp_no を持つレコードを結合しています。

2つ目の条件を AND で合わせることで、salaryemp_no に対応する max_salary に一致する場合のみ結合の対象となるようになります。
結果として、それぞれの emp_no で最大の給与でないレコードは結合の対象外となり、結合結果には給与が最大であるレコードだけが残ります。

複数レコードが max_salary に一致する場合、その全てが結合の対象になるため、誤答であったような取り残しの心配もありませんね。

正答2. 自己結合を使う

自己結合を使うことで、さらにエレガントで実行効率の良いクエリに書き換えられます。

SELECT `left`.*
FROM `salaries` AS `left`
LEFT OUTER JOIN `salaries` AS `right`
  ON `left`.`emp_no` = `right`.`emp_no`
  AND `left`.`salary` < `right`.`salary`
WHERE `right`.`salary` IS NULL
;

サブクエリがなくなったのでお上品な雰囲気になりましたが、同時にやや近寄りがたい雰囲気も出ています。解読してみましょう。

まず1つめの条件では、 salaries テーブル内で emp_no が同じレコード同士の組み合わせが結合の結果となります。
仮に emp_no = 10001 のレコードが5件あったとすると、それに対応するレコードは結合結果には 5 × 5 = 25 件含まれる、という具合ですね。

これに2つ目の条件を AND で合わせることで、結合元のレコードの salary が結合先のレコードの salary より少ない場合のみ結合が成功するという条件が加わります。
よって、 salary が最大であるレコードは結合相手が見つからないため、結合に失敗します。
ここで、結合の種類が LEFT OUTER JOIN であるため、この場合 right のカラムがすべてNULL であるという扱いになります。

最後に、 WHERE を使って結合に失敗したレコードのみ抽出しています。
結合に失敗したレコードというのは、つまり salary が最大であるレコードのことなので、給与が最大のレコードのみが残ります。

正答1と比べると直感的とは言い難いですが、サブクエリが無い分実行効率の向上が期待できます。
レコード数2,844,047件の salaries テーブルで試したところ、正答1が平均で565 msかかったところ、正答2は平均で8 msでした。
パフォーマンスは総レコード数、グループ内の平均レコード数、インデックスの有無等に影響するため一概にどちらが良いとは言えないですが、クエリ最適化をする際のために頭の片隅に置くといいでしょう。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQLのカラム名に "key" は使えない

何度読み返しても正しい文法のSQL文でSyntax Errorが出続けて困ったときは、
どこかに予約語が含まれていないか確認しましょう

予約語一覧 (ver 5.6)

強力な助っ人

私を救ってくれたオンラインの文法チェッカーです
EverSQL SQL Query Syntax Check & Validator

私を悩ませていたのは

INSERT INTO table (id, key, name) VALUES (1, 'A', 'abc'), (2, 'B', 'def'), (3, 'C', 'ghi')

みたいなSQL文なのですが、ちゃんとprettyした上で key をハイライトして教えてくれて本当に有能です

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker-composeで、MySQLの設定ファイル変更を適用させる

何をするのか

docker-composeでMySQLの設定ファイル(my.conf)の中身を更新したが、作り直したコンテナに反映されなかったため、これを反映させる。

環境

  • Laravel
  • MySQL8.0
  • docker-compose version 1.26.2

こちらを参考にDockerでLaravelの環境構築をしていました。
【初心者向け】20分でLaravel開発環境を爆速構築するDockerハンズオン

問題が起きた背景

Laravelでは、MySQLのバージョンが8の場合にデータベース接続がうまくできない不具合があります。

MySQLのバージョンが8.0.4以降の場合、デフォルトの認証方式がcaching_sha2_passwordになっており、PHPのMySQL接続ライブラリがcaching_sha2_passwordに対応していないため、MySQLに接続できない(ログインできない)というエラーが発生していました。

引用:Laravel+MySQL8.0環境でマイグレートできない場合の原因と対処法

このため、「認証方法を変更」を行いました。

ただ、↓のリンクに「すでに認証方法が対応された」と書かれていたのであえて変更する必要もないと思いMySQLの設定の以下をコメントアウトしました。(これが間違いだった。)
MySQL8.0 認証方式を変更する(Laravel5) - Qiita

my.cnf
# MySQL8 caching_sha2_password to mysql_native_password
default-authentication-plugin = mysql_native_password

そのままdocker-compose up -d —buildして

マイグレーションしたらところエラー発生

Illuminate\Database\QueryException 

  SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (SQL: select * from information_schema.tables where table_schema = routine-share and table_name = migrations and table_type = 'BASE TABLE')

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:671
    667|         // If an exception occurs when attempting to run a query, we'll format the error
    668|         // message to include the bindings with SQL, which will make this exception a
    669|         // lot more helpful to the developer instead of just the database's errors.
    670|         catch (Exception $e) {
  > 671|             throw new QueryException(
    672|                 $query, $this->prepareBindings($bindings), $e
    673|             );
    674|         }
    675| 

      +34 vendor frames 
  35  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

それならば、さっきのコメントアウトを戻せば大丈夫だろうと思い
docker-compose downしてから
先程のmy.cnfの認証方法変更部分のコメントアウトを戻しました。

改めてdocker-compose up -d —buildをします。

が、マイグレーションできず、同じエラー画面になります。

解決方法

どうやらデータベース(volumes)がマウントされていると設定が変更されないようでした。

一度データベース(volumes)を削除すればOKなので、、、

docker volume prune

したところ、マイグレーションまで問題なくできました。

参考にしてもらえたらうれしいです。

以下参考:
DockerのMySQLの環境変数系の設定が反映されないのは余計なデータベースをマウントしているから - Qiita

Laravel+MySQL8.0環境でマイグレートできない場合の原因と対処法

Docker: where is docker volume located for this compose file

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

仮想DBサーバ構築(Mac編)+MySQLインストール+Sequel Proから接続

手持ちのMac端末上に仮想のDBサーバ(ubuntu16.04)を構築し、MySQLをインストールして、更にMac上からSequel Proを通して接続する方法を備忘録+参照用に記載します。

■環境

スクリーンショット 2020-08-01 13.57.12.png

  • Mac mini (Late 2014) macOS Catalina バージョン 10.15.6
  • Oracle VM VirtualBox 6.1.12
  • Vagrant 2.2.9

■構築する仮想マシン(VM)

  • Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-186-generic x86_64)
  • mysql Ver 14.14 Distrib 5.7.31, for Linux (x86_64)

■必要なソフトウェアのインストール

Macに下記のソフトウェアをインストールしておく。

  1. Vagrant
    https://www.vagrantup.com/downloads.html
    ダウンロードしたdmgイメージを展開し、vagrant.pkgをダブルクリックするとインストーラが起動するので、指示に従ってインストールを完了する。

  2. VirtualBox
    http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html?ssSourceSiteId=otnjp
    ダウンロードしたdmgイメージを展開し、VirtualBox.pkgをダブルクリックするとインストーラが起動するので、指示に従ってインストールを完了する。

  3. Sequel Pro
    https://sequelpro.com/download
    ダウンロードしたdmgイメージを展開し、アプリケーションフォルダに移動する。

これらのソフトウェアがインストール済みの前提で手順を書いていきます。そもそもこいつらってなんなの?っていうのはここでは詳しく書きませんので、別の記事を参照してください。

■仮想DBサーバ(Ubuntu16.04)の構築

今後仮想環境を複数作成する可能性を考慮して、仮想環境を括る”Vagrant”をHomeディレクトリ直下に作成し、その下に今回作成する仮想環境のディレクトリを作成

$ mkdir -p ~/Vagrant/mysql_ubuntu1604

cdコマンドで移動

$ cd ~/Vagrant/mysql_ubuntu1604

Vagrantfile の作成

$ vagrant init bento/ubuntu-16.04

Vagrantfileの編集  
作成されたVagrantfileをテキストエディタで開き、35行目、以下の部分のコメントアウトを外す

config.vm.network "private_network", ip: "192.168.33.10"

VMの起動

$ vagrant up

VMへSSH接続

$ vagrant ssh

下記のようなコマンドが返ってきたら、無事VMにSSH接続できています。
スクリーンショット 2020-08-01 12.53.14.png

■Ubuntuの日本語化

$ sudo apt-get -y install language-pack-ja-base language-pack-ja ibus-mozc
$ localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"
// パスワードを入力 vagrantの初期パスワードは"vagrant"
$ source /etc/default/locale
$ echo $LANG
ja_JP.UTF-8

■Ubuntuの諸々アップデート

sudo apt-get update && sudo apt-get -y upgrade && sudo apt-get -y dist-upgrade && sudo apt-get -y autoremove && sudo apt-get -y autoclean

途中で次のような画面になったら、「install the package maintainer’s version」を選択する。
スクリーンショット 2020-08-01 13.01.14.png

sudo init 6
// 再起動

■MySQLインストール

再起動実行後、SSH接続が切れるので再度vagrant sshして、次はMySQLのインストールを進めていきます。

sudo apt-get install mysql-server

rootユーザーのパスワードを設定するよう求められるので、パスワードを設定。
スクリーンショット 2020-08-01 13.12.15.png
上記Enter後、パスワードの確認を求められるので設定したパスワードを再度入力。

■よく使うコマンド

MySQLバージョン確認

$ mysql --version
mysql  Ver 14.14 Distrib 5.7.31, for Linux (x86_64) using  EditLine wrapper

MySQLにrootユーザでログイン

$ mysql -u root -p
// パスワードを入力

MySQLの状態確認

$ mysqladmin ping -u root -p
Enter password:
mysqld is alive

■Sequel Pro 接続情報の設定

VagrantでSSH接続中であればexitしておく。exitしてもVMは止めない限り裏でずっと動いているのでDBサーバを使う作業が終わったらvagrant haltしておくのを忘れずに。vagrantの詳しい使い方はここでは触れないので別の記事を参照してください。

Sequel Proを起動して、接続情報を画像のように入力。
スクリーンショット 2020-08-01 13.35.23.png
※パスワードはMySQLのインストール時に設定したパスワード。
 SSHパスワードはvagrantユーザーのパスワード。

VM上のMySQLに接続できました。
スクリーンショット 2020-08-01 13.35.46.png

過去にWindows10でも似たようなことやってるのでWindowsの人はこっちを見てください。
https://qiita.com/ekCraft/items/3c802f684824e5765515

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2のデプロイに関わるエラーを確認するコマンド一覧

この記事の使い方

EC2、RDS(MySQL)、Rails、nginx、pumaを使用してデプロイする際のお供に。

何を隠そうこれは筆者のためのメモでもあります。笑
Amazon linuxとAmazon linux2でコマンドが違っていたりして混乱するので。

使用するAMI

Amazon linux2

Nginx関連

$ sudo systemctl start nginx.service   #起動
$ sudo systemctl status nginx.service  #ステータス確認
$ tail -f log/nginx.error.log          #エラーログ確認
$ sudo nginx -t                        #設定ファイル内の間違いを教えてくれる

puma関連

$ bundle exec pumactl start            #起動

MySQL関連

$ sudo systemctl start mysqld.service  #起動
$ sudo systemctl status mysqld.service #ステータス確認

見てくださりありがとうございました。

この記事がデプロイの助けになれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでLaravel+Apache+MySQLの開発環境を構築する

https://note.com/pocke_techblog/n/n8af813848fa0

上記の記事通りにすすめて、DockerでLaravel+Apache+MySQLの開発環境を構築しましたが、パーミションのエラーが出て解決に手こずったので記録に残しておきます。

作業環境

OS:Windows 10 Pro ver.2004
Docker:version 19.03.12, build 48a66213fe

Dockerのインストール

Dockerのインストール方法については別記事にて解説しているので、まだインストールしていないのであれば参考にしてみてください。
Windows 10 Pro : Dockerをインストールする

サンプルコードを準備する

フォルダ構成

フォルダ構成は以下の通りです。

.
├── docker/
│   ├── app/
│   │   ├ Dockerfile
│   │   ├ php.ini # PHP設定用のファイル
│   │   └ 000-default.conf  # Apacheの設定ファイル
│   └── db/
│        ├ data/ # MySQLのデータを保存しておくディレクトリ
│        └ my.cnf  # MySQLの設定ファイル
│
├── src/ # Laravelのソースを格納するディレクトリ
└── docker-compose.yml

ソースコード

Dockerfile

# どんなdockerイメージを利用して構築をするか
FROM php:7.4-apache

# 設定ファイルをdockerコンテナ内のPHP、Apacheに読み込ませる
ADD php.ini /usr/local/etc/php/
ADD 000-default.conf /etc/apache2/sites-enabled/

# 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 \
libpng-dev \
libpq-dev \
&& docker-php-ext-install pdo_mysql

# Laravelで必要になるmodRewriteを有効化する
RUN mv /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled
RUN /bin/sh -c a2enmod rewrite

php.ini

docker/app/php.ini
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
docker/app/000-default.conf
<VirtualHost *:80>
       ServerAdmin webmaster@localhost
       DocumentRoot /var/www/html/laravelapp/public
       ErrorLog ${APACHE_LOG_DIR}/error.log
       CustomLog ${APACHE_LOG_DIR}/access.log combined
       <Directory /var/www/html/laravelapp/public>
           AllowOverride All
       </Directory>
</VirtualHost>

my.cnf

docker/db/my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
[client]
default-character-set=utf8mb4

docker-compose.yml

docker-compose.yml
# Compose fileのバージョン指定
version: '3'
# どんなコンテナを立ち上げるか
services:
 # laravelを動かすコンテナ
 app:
   # どのポートを開いて繋ぐか。下記はコンテナの80番ポートを開いて、ホストの8000番につなぐ
   ports:
     - "8000:80"
   # 先ほど作ったDockerfileを使って、コンテナをビルドするという指定
   build: ./docker/app
   # コンテナの名前を指定
   container_name: laravel_app
   # コンテナとホスト側のディレクトリを同期する場所の指定。laravelのソースが入る予定の場所
   volumes:
     - ./src:/var/www/html
 # MySQLを動かすコンテナ
 db:
   # Docker HubからMySQL5.7の公式イメージをダウンロードしてくる指定
   image: mysql:5.7
   container_name: laravel_db
   # コンテナ内の環境変数を指定。環境変数を渡すとビルド時に設定してくれるDockerイメージがあるので、利用の際はDocker Hubのサイトで確認すると良い
   environment:
     MYSQL_ROOT_PASSWORD: root
     MYSQL_DATABASE: laravel_db
     MYSQL_USER: laravel_user
     MYSQL_PASSWORD: laravel_pass
     TZ: 'Asia/Tokyo'
   # 起動時のコマンド
   command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
   # ディレクトリ同期。設定ファイルとMySQLのデータが保存される場所を同期している。コンテナは基本的に起動時に変更されてもコンテナ自体が止まるとデータが消えてしまうため、保存しておきたいものはホストマシンと同期しておく必要がある。
   volumes:
     - ./docker/db/data:/var/lib/mysql
     - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
   ports:
     - 3306:3306

開発環境を構築する

Docker Composeでコンテナを立ち上げる

次のコマンドを実行して、Docker Composeでコンテナを立ち上げます。

$ docker-compose build
$ docker-compose up

Laravelのプロジェクトを作成する

上記とは別の画面を立ち上げて次のコマンドを実行して、Laravelのプロジェクトを作成します。

$ docker exec -it laravel_app bash
$ composer create-project laravel/laravel --prefer-dist laravelapp

これでhttp://localhost:8000 にアクセスするとLaravelの画面が立ち上がるはずですが、パーミッションのエラーが起きてしまいました。

パーミッションのエラーを解決する

最初に以下のようなエラーメッセージが出ました。
The stream or file "/var/www/html/laravelapp/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied

ここのサイトを参考に以下のコマンドを実行しました。

$ chmod 777 /var/www/html/laravelapp/storage/logs/laravel.log
$ chmod 775 /var/www/html/laravelapp/storage/logs/

すると以下のようにエラーメッセージの文言が変わりました。
file_put_contents(/var/www/html/laravelapp/storage/framework/sessions/oI2ffP9BUcWC0llE0NEoFU09eqQyXTosSZZeq4BV): failed to open stream: Permission denied

ここのサイトを参考に以下のコマンドを実行しました。

chmod -R gu+w /var/www/html/laravelapp/storage
chmod -R guo+w /var/www/html/laravelapp/storage
cd ./laravelapp
php artisan cache:clear

これでパーミッションのエラーが解決して、Laravelの画面が表示されました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む