たくろぐ!

世界一のチラ裏

Ubuntuでのlaradockを利用したlaravel環境構築したら15分どころじゃ済まなかった

はじめに

とりあえずやってみた。

Mac多すぎ問題。

Ubuntuいいよね。

ちなワイ氏、MacBook ProUbuntu入れてる勢。

Macは見た目かっこいいから買っただけ(5年目)。

Surface Book2ほしい。

15分でできるLaravel環境構築やっていくで。

qiita.com

docker入れる

まずはそもそものところから。

上記の環境構築はすでにdocker等のインストールが終わってる前提になってるのでまずはdocker入れておく。

入れないでやっていくと以下のエラーで怒られる。

ERROR: Couldn't connect to Docker daemon. You might need to install Docker:

基本は以下の記事を参考にやっていく。

qiita.com

sudo apt-get update
Hit:1 https://deb.nodesource.com/node_10.x xenial InRelease
Hit:2 http://archive.ubuntu.com/ubuntu xenial InRelease                                                                                               
Get:3 http://ppa.launchpad.net/ondrej/php/ubuntu xenial InRelease [23.9 kB]                                                
Hit:4 http://security.ubuntu.com/ubuntu xenial-security InRelease               
Hit:5 http://archive.ubuntu.com/ubuntu xenial-updates InRelease                     
Ign:3 http://ppa.launchpad.net/ondrej/php/ubuntu xenial InRelease                   
Hit:6 http://archive.ubuntu.com/ubuntu xenial-backports InRelease
Fetched 23.9 kB in 1s (16.1 kB/s)
Reading package lists... Done
W: GPG error: http://ppa.launchpad.net/ondrej/php/ubuntu xenial InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 4F4EA0AAE5267A6C
W: The repository 'http://ppa.launchpad.net/ondrej/php/ubuntu xenial InRelease' is not signed.
N: Data from such a repository can't be authenticated and is therefore potentially dangerous to use.
N: See apt-secure(8) manpage for repository creation and user configuration details.

こんなん言われたら以下やっとく。

co.bsnws.net

docker-compose入れる

docs.docker.com

まずこれ入れる。

sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose  

laradock入れる

次にこれ入れる。

git clone https://github.com/laradock/laradock.git
warning: unable to access '/home/vagrant/.config/git/attributes': Permission denied

こうやって怒られたら以下を実行する。
多分ワイだけだと思うけど。

sudo chown -R $(whoami) ~/.config

実行権限を与える。

sudo chmod +x /usr/local/bin/docker-compose

nginxを起動する

続いてこれやる。

docker-compose up -d nginx
ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running?

If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.

これでたらsudoつけて実行する。

Recreating laradock_nginx_1 ... error

ERROR: for laradock_nginx_1  Cannot start service nginx: driver failed programming external connectivity on endpoint laradock_nginx_1 (da38cc5608cf47384f0fd9a8c42b78b34eb8113cae80e05c1e783e8e2fc37ad9): Error starting userland proxy: listen tcp 0.0.0.0:443: bind: address already in use

↑こうなったらローカルでインストールしているnginxが起動中で同じポート使おうとしているから衝突しないよう以下を実行する。

sudo systemctl stop nginx

くっそ起動長い。

5分は優にやってたと思われる(ネットワークの問題もあるかもしれないけどw)。

Laravelの環境を起動する

composer create-project laravel/laravel app01

swapファイルが云々言われる。

akamist.com

この辺頑張ったが無理だったので、そもそも仮想環境へのメモリの割り当てが少ないのかと自力で考え抜く(一通りググってもダメだったので(ここまで15分))。

  config.vm.provider "virtualbox" do |vb|
    # vb.cpus = 1
    vb.memory = 2048
  end

これでうまくいった。

vagrantUbuntu環境なので config.vm.network "private_network", ip: "192.168.33.10" の部分がゲストのURLとなる。

Railsのプロジェクトのデフォルトポートは3000だけど、この環境は80番。

localhostのところを 192.168.33.10 にすればOK。

あとは docker-compose exec workspace bash でdocker環境にログインしてプロジェクトをクローンすれば環境構築完了。

docker-compose exec workspace bash  
composer install

最後の最後で以下のエラーに出くわした。

katsu-tech.hatenablog.com

Vagrantfileのディスク容量をdefaultの10GBから100GBに変更したらうまくいった。

これで1時間も調べたわ。

mysqlのポートが使われてた

こんなエラー出た。

vagrant@ubuntu-xenial:~/tmp/laradock$ sudo docker-compose up -d nginx mysql phpmyadmin redis workspace 
laradock_docker-in-docker_1 is up-to-date
laradock_redis_1 is up-to-date
Starting laradock_mysql_1 ... 
laradock_workspace_1 is up-to-date
laradock_php-fpm_1 is up-to-date
Starting laradock_mysql_1 ... error

ERROR: for laradock_mysql_1  Cannot start service mysql: driver failed programming external connectivity on endpoint laradock_mysql_1 (e1e80cbae0f0fd49e14d75830a0e58845c073bee261c7b0dcacae845c4da1581): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use

ERROR: for mysql  Cannot start service mysql: driver failed programming external connectivity on endpoint laradock_mysql_1 (e1e80cbae0f0fd49e14d75830a0e58845c073bee261c7b0dcacae845c4da1581): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use
ERROR: Encountered errors while bringing up the project.

stackoverflow.com

dockerのmysqlとローカルにインストールしてるmysqlで同じポート使用しようとしていたのでローカルのmysqlのデーモン(プロセス)を停止した。

mysql接続エラー

root@eedbed7757b6:/var/www/project_name# php artisan migrate

In Connection.php line 664:
                                                                                                                                                                                                     
  SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (SQL: select * from information_schema.tables where table_schema = project_name_dev and table_name = migrations)  
                                                                                                                                                                                                     

In Connector.php line 67:
                                                                                           
  SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client  
                                                                                           

In Connector.php line 67:
                                                                                                                
  PDO::__construct(): The server requested authentication method unknown to the client [caching_sha2_password]  
                                                                                                                

上記のエラーになったら以下を実行。

blog.janjan.net

No application encryption key has been specified.エラー

qiita.com

npm install --no-optionalでLaravel Mixをインストール

以下のエラーが出る。

  ⚠ The `/var/www/project_name/node_modules/mozjpeg/vendor/cjpeg` binary doesn't seem to work correctly
  ⚠ mozjpeg pre-build test failed
  ℹ compiling from source
  ✖ Error: autoreconf -fiv && ./configure --disable-shared --disable-dependency-tracking --with-jpeg8  --prefix="/var/www/project_name/node_modules/mozjpeg/vendor" --bindir="/var/www/project_name/node_modules/mozjpeg/vendor" --libdir="/var/www/project_name/node_modules/mozjpeg/vendor" && make -j2 && make install -j2
Command failed: ./configure --disable-shared --disable-dependency-tracking --with-jpeg8  --prefix="/var/www/project_name/node_modules/mozjpeg/vendor" --bindir="/var/www/project_name/node_modules/mozjpeg/vendor" --libdir="/var/www/project_name/node_modules/mozjpeg/vendor"
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
cat: -: No such file or directory
configure: error: in `/var/www/project_name/node_modules/mozjpeg/50dc72fd-d56a-4687-b290-d92490e310cf':
configure: error: C compiler cannot create executables
See `config.log' for more details

    at ChildProcess.exithandler (child_process.js:297:12)
    at ChildProcess.emit (events.js:193:13)
    at maybeClose (internal/child_process.js:1001:16)
    at Socket.stream.socket.on (internal/child_process.js:405:11)
    at Socket.emit (events.js:193:13)
    at Pipe._handle.close (net.js:614:12)

以下のエントリーを参考にする。

github.com

sudo apt-get install libpng16-dev

自分の環境だと sudo は不要だった。

以下のエラーが出た。




以下のエントリーを参考にする。

teratail.com

npm install --save-dev cross-env

補足

dockerコマンドに毎回sudoを使わなくてもよくする方法。

sudo usermod -aG docker your-user

まとめ

余裕で2時間とかかかったわ。

多分Vagrantのメモリ設定をはじめから4Gとかにすればもっと早く終わったと思う。

あと超低速のレンタルWi-Fiのせい。

でも割と苦戦せず環境構築できた。

これからPHPやLaravelも頑張ります。

参考にした

laradock.io

qiita.com

qiita.com

追記

bladeってなに?

HTMLのテンプレートエンジン。

laraweb.net

.bladeファイルではphp(Laravel)のコードが実行できるようになる。

Railsで言うところのslimやhamlのようにより楽にhtmlを記述するにはpugを利用する?

時間操作について

PHP標準のDateTimeクラスを拡張して時間を楽に操作できるようにしてくれるCarbonクラスがある。

RailsにおけるAuthenticity Token(CSRF対策用トークン)について翻訳してみた

はじめに

トークンという普段生活していて馴染みのない言葉を調べてみた。

仮想通貨とかやってると知ってる人がいるらしいけど、僕はつい最近までよくわかっていなかったのでいい機会だと思ってStackoverflowのAuthenticity Tokenの英語の説明を翻訳してみた(意訳含む)。

ソースは以下。

stackoverflow.com

では早速やってみるぞ。

質問

I am running into some issues regarding the Authenticity Token in Rails, as I have many times now.

But I really don't want to just solve this problem and go on. I would really like to understand the Authenticity token. Well, my question is, do you have some complete source of information on this subject or would you spend your time to explain in details here?

私は今やRailsCSRF対策用トークン(Authenticity Token:本来の意味は「信頼性トークン」)に関する問題に何度も直面しています。

この問題をただ解決したり、見過ごしたくはありません。CSRF対策用トークンを本当に理解したいのです。本題ですが、質問です。ここにいる方で、この議題に関しての良質な情報源をお持ちか、または詳細について説明してくださる方はいますか?

回答

何が起こっているか?

What happens

When the user views a form to create, update, or destroy a resource, the Rails app creates a random authenticity_token, stores this token in the session, and places it in a hidden field in the form. When the user submits the form, Rails looks for the authenticity_token, compares it to the one stored in the session, and if they match the request is allowed to continue.

ユーザーがリソース(Railsアプリが扱うデータ)を生成、更新、削除するためのフォーム画面を閲覧しているとき、RailsアプリケーションはランダムのCSRF対策用トークンを生成し、セッションに保存し、フォームの隠しフィールドに設置します。ユーザーがこのフォーム(に入力し、これ)を送信するとRailsCSRF対策用トークンを探し、セッションに保存されているものと比較し、もし合致していればクライアントとの通信を保持します。

なぜこのようなことが起こるのか?

Why it happens

Since the authenticity token is stored in the session, the client cannot know its value. This prevents people from submitting forms to a Rails app without viewing the form within that app itself. Imagine that you are using service A, you logged into the service and everything is ok. Now imagine that you went to use service B, and you saw a picture you like, and pressed on the picture to view a larger size of it. Now, if some evil code was there at service B, it might send a request to service A (which you are logged into), and ask to delete your account, by sending a request to http://serviceA.com/close_account. This is what is known as CSRF (Cross Site Request Forgery).

CSRF対策用トークンがセッションに保存されるとき、クライアント(Chromeなどのブラウザのこと)はその値を知ることはできません。これは他人がRailsアプリ自体にあるフォームを見ることなくアプリへフォームを送信するのを防ぐためです。サービスAを使うことを想像してください。あなたはサービスにログインし問題がないことを確認します。では次にサービスBを使うようになったのを想像してください。あなたは好きな写真をみたり、大きく引き伸ばしたりします。そこでもしそのサービスBに悪意のあるコードがあればあなたがログインしていたサービスAに http://serviceA.com/close_account というようなリクエストを送信して、アカウントを削除するよう問い合わせするかもしれません。これがよく知られているクロスサイトリクエストフォージェリCSRF)というものです。

If service A is using authenticity tokens, this attack vector is no longer applicable, since the request from service B would not contain the correct authenticity token, and will not be allowed to continue.

もしサービスAがCSRF対策用トークンを使っているなら、サービスBからのリクエストに正しいCSRF対策用トークンが含まれていないのでこの方向(B→A)の攻撃は適用されず、リクエストを継続することはできません。

API docs describes details about meta tag:

APIドキュメントにはメタタグに関しての詳細が記載されています。

CSRF protection is turned on with the protect_from_forgery method, which checks the token and resets the session if it doesn't match what was expected. A call to this method is generated for new Rails applications by default. The token parameter is named authenticity_token by default. The name and value of this token must be added to every layout that renders forms by including csrf_meta_tags in the HTML head.

CSRF対策はCSRF対策用トークンをチェックしてくれる protect_from_forgery メソッドで動作し、もし想定しているトークンと合致しない場合セッションを削除してくれます。このメソッド呼び出しは最新のRailsアプリケーションではデフォルトで生成されます。このトークンパラメータはデフォルトでは authenticity_token と名付けられています。このトークンの名前と値はHTMLヘッダーに csrf_meta_tags を含めることによってフォームをレンダリングするどのレイアウトにも挿入されているはずです。

注記

Notes

Keep in mind, Rails only verifies not idempotent methods (POST, PUT/PATCH and DELETE). GET request are not checked for authenticity token. Why? because the HTTP specification states that GET requests is idempotent and should not create, alter, or destroy resources at the server, and the request should be idempotent (if you run the same command multiple times, you should get the same result every time).

RailsはPOSTやPUT/PATCH、DELETEのような冪等(べきとう:後述)性を持つメソッド以外のもののみ検証することを覚えておいてください。GETでのリクエストはCSRF対策用トークンではチェックされません。なぜでしょうか?それはHTTP通信の特徴は「GETリクエストは冪等性を持ち、サーバ内のリソースの生成や変更、削除するべきではない」ということを物語っているからです。それがリクエストが冪等的(同じコマンドをいつ何度やってもその度に全く同じ結果が返るべきであるということ)であるということです。

※注釈:「冪等的」という言葉はあまり使われません。うまく訳できませんでした。どげざ。

Also the real implementation is a bit more complicated as defined in the beginning, ensuring better security. Rails does not issue the same stored token with every form. Neither does it generate and store a different token every time. It generates and stores a cryptographic hash in a session and issues new cryptographic tokens, which can be matched against the stored one, every time a page is rendered. See request_forgery_protection.rb.

また最初に定義されている実際の実装は少し複雑ですが、強固なセキュリティを保証します。Railsはどのフォームであっても保存されているトークンと同じトークンを発行しません。また毎回異なったトークンを生成したり保存したりもしません。Railsはセッションに毎回ページがレンダリングされるたびに(以前)保存されたものとは一致しない暗号化された新しいハッシュを生成・保存します。詳しくは request_forgery_protection.rb をご覧ください。

練習

Lessons

Use authenticity_token to protect your not idempotent methods (POST, PUT/PATCH, and DELETE). Also make sure not to allow any GET requests that could potentially modify resources on the server.

冪等性を持たないメソッド(POST, PUT, PATCH, DELETE)を保護するためにCSRF対策用トークンを利用してください。またサーバーのリソースを変更しうるGETリクエストを通さないことも確認してください。

まとめ

トークンってピクミンみたいなかわいい生物の名前っぽい響きだよね?

今日も平和な世界!!

オワオワリ。