初めてDockerの開発環境を一から用意したので、その時の奮闘を内心も含めて記録しました。環境は以下になります。
- Windows 10 20H2
- Docker Desktop for Windows v20.10.8
- npm v6.14.16(あまり関係ないけど)
- composer v2.1.6(こちらもあまり関係ない)
- Visutal Studio Code v1.60.2(Remote containersの拡張機能を使う)
覚えが悪くコマンドの書き方を忘れてしまうので、以下の説明では同じコマンドを何度も記載しています。ご了承ください。
経緯
思い立ったきっかけ
LaravelとNuxt.jsをなんとなく使えるようになったし、自分でなにかWebアプリケーション作りたいな。よし、作ろう!
どこで作ろうか?
LaravelとNuxt.jsを多少使えるからそれが簡単に使えそうなところがいいな。ConoHaのVPSだとLaravelがテンプレートから作れる。よし、これにしよう!
どうやって開発しよう?
Dockerとかいう便利そうなのがある。VSCodeの拡張機能にあるRemote containers というのも便利そう。よし、これ使おう!
Laravel環境構築
各種アプリのインストール
Docker、Composer、Node.jsをインストールします。Node.jsはLaravel関係ないけど一緒にインストール。
Dockerfileの作成
とりあえずC:¥projectというフォルダを作りDockerfileを作成する。
Dockerイメージの選択
ConoHaのLaravelテンプレートは「centos-7.9」ってなってるからこれにしよう。でも大抵のLaravel環境構築サンプルはCentOSから作ってる事が無いのでOSはあんまり気にすることないのかな?まあいいや。ということで以下のようにDockerfileを編集。
1 2 |
# CentOSのバージョン7を指定 FROM centos:7 |
イメージ作成
ビルドは「docker build .」だけで出来るけど一応名前も付けておこう。コマンドプロンプトを起動してC:¥projectに移動してイメージの名前はtestimg1でいっか。
c:\>cd c:\project
c:\project> docker build -t testimg1 .
コンテナ作成
作成したイメージからコンテナを作成して接続できるか試してみよう。名前はtestcon1にしておこう。よし何となく使えてる。
c:\project> docker run -itd --name testcon1 testimg1
c:\project> docker exec -it testcon1 bash
Webサーバーの用意
どうせphp artisan serveでPHPのビルトインサーバーでテストするわけだから要らない気がするけど、せっかくなのでApacheも用意しておこうかな。Apacheは動いているんだろうか?
# systemctl status httpd
なんか知らんけど「Failed to get D-Bus connection: Operation not permitted」とかいうエラーで確認できない。。。
調べてみるとDocker runする時に以下のオプション両方が必要らしい。
- --privileged
- /sbin/init
一旦コンテナから抜けて、コンテナ停止&削除して、さっきのオプションを追加して実行して再接続してsystemctlで確認。
# exit
c:\project>docker stop testcon1
c:\project>docker rm testcon1
c:\project>docker run -itd --privileged --name testcon1 testimg1 /sbin/init
c:\project>docker exec -it testcon1 bash
# systemctl status httpd
「Unit httpd.service could not be found.」とメッセージが表示され、systemctlが動いてくれて、Apacheがインストールされていないことが確認できた。
入ってなかったのでApacheをインストールするために以下のようにDockerfileを編集し再度testimg1をビルドする。インストールコマンドはググって出てきたのを適当にコピペ。とりあえず動けばいいや。
1 2 3 4 5 6 7 8 |
# CentOSのバージョン7を指定 FROM centos:7 # apacheのインストール RUN yum -y update RUN yum clean all RUN yum -y install httpd RUN systemctl enable httpd.service |
# exit
c:\project>docker build -t testimg1 .
また何かエラーでた。「Failed to connect to ~~」となっていて通信できてないっぽい。そういえばプロキシ通さないと外出られなさそう。
CentOSでプロキシ使うには環境変数http_proxy、https_proxyを指定してやれば良いらしい。
参考 Docker + CentOS7 で Proxy 越え - しまかぜメモしまかぜメモという事でDockerfileを以下のように編集。勿論プロキシのIPやポートは自分の環境に合わせる。
1 2 3 4 5 6 7 8 9 10 11 12 |
# CentOSのバージョン7を指定 FROM centos:7 # Proxyの設定 ENV http_proxy http://192.168.1.250:8080 ENV https_proxy http://192.168.1.250:8080 # apacheのインストール RUN yum -y update RUN yum clean all RUN yum -y install httpd RUN systemctl enable httpd.service |
再度ビルドして、既存のコンテナを削除して、コンテナを再作成して、コンテナに再接続して、Apacheのインストール結果を確認してみる。
c:\project>docker build -t testimg1 .
c:\project>docker rm testcon1
c:\project>docker run -itd --privileged --name testcon1 testimg1 /sbin/init
c:\project>docker exec -it testcon1 bash
# systemctl status httpd
先ほどと違ってactiveって表示されたりしてるので入ったっぽい。
PHPの用意
phpも入っていないようなのでインストールする。
インストールするコマンドをググってDockerfileにコピペ。いるかどうか分からないモジュールがいっぱいあるけどまあいいや。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# CentOSのバージョン7を指定 FROM centos:7 # Proxyの設定 ENV http_proxy http://192.168.1.250:8080 ENV https_proxy http://192.168.1.250:8080 # apacheのインストール RUN yum -y update RUN yum clean all RUN yum -y install httpd RUN systemctl enable httpd.service # PHPのインストール RUN yum -y install epel-release RUN rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm RUN yum -y install --enablerepo=remi,remi-php80 php \ php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd php-phpunit-PHPUnit \ php-pecl-xdebug php-gd php-intl php-symfony php-pdo php-xml php-tokenizer php-pear php-zip |
ビルドしてコンテナを再作成して接続するとphpがインストールされた。
Laravelのプロジェクト作成
そろそろLaravelのプロジェクト作ろうかな。フォルダもちょっと整理しよう。C:¥projectの下にapiというフォルダを作ってLaravelの開発環境はそっちにまとめよう。ソースはDockerとは別にしようと思ったけどVSCodeのRemote containersでDocker上で開発するからこっちでいっか。ホスト上で作成したファイルをコンテナ内にコピーしようとすると同じフォルダに無いとコピーできないし。
c:\project>mkdir api
c:\project>move Dockerfile api
c:\project>cd api
c:\project>composer create-project laravel/laravel src
ちなみに--prefer-distは要らないはず。
Laravelのプロジェクト作成コマンドの意味さて、Laravelのプロジェクトも作成できたのでコンテナ内で動かしてみよう。まずはDockerfileでファイルをコンテナ内にコピーするよう編集して。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# CentOSのバージョン7を指定 FROM centos:7 # Proxyの設定 ENV http_proxy http://192.168.1.250:8080 ENV https_proxy http://192.168.1.250:8080 # apacheのインストール RUN yum -y update RUN yum clean all RUN yum -y install httpd RUN systemctl enable httpd.service # PHPのインストール RUN yum -y install epel-release RUN rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm RUN yum -y install --enablerepo=remi,remi-php80 php \ php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd php-phpunit-PHPUnit \ php-pecl-xdebug php-gd php-intl php-symfony php-pdo php-xml php-tokenizer php-pear php-zip # Laravelのコードのコピー COPY src/ /var/www/html/ |
イメージを再作成&コンテナ再作成してコンテナに接続し、ソースはコピーされてるかな?
されてる。よし、次はブラウザで接続してみよう。一旦コンテナを抜けて削除して、ポートのマッピングはphp artisan serve用の8000番とApacheの80番でいっか。
# exit
c:\project\api>docker stop testcon1 && docker rm testcon1
c:\project\api>docker run -itd -p 8000:8000 -p 80:80 --privileged --name testcon1 testimg1 /sbin/init
c:\project\api>docker exec -it testcon1 bash
# cd /var/www/html/
# php artisan serve
これでブラウザからアクセス出来ると思うけどどうだろう?
ちくしょう。
調べてみるとデフォルトではphpのビルトインサーバーはリモートからの接続は許可していないらしく実行時に「--host 0.0.0.0」と指定が必要の様です。自分のPC上で動いているんだからリモートじゃないじゃんと思うかもしれないけど多分Docker内のネットワークを経由しているのでリモート扱いとなるのでしょう。コンテナ内で以下の様にコマンドを実行し、再度ブラウザでアクセスすると開発サーバーに接続することが出来ました。
# php artisan serve --host 0.0.0.0
Apacheでの実行
php artisan serveだけで十分な気がするけどついでにApacheからのアクセスも試してみよう。DocumentRootを/var/www/html/publcにするだけでいいか。設定ファイルの場所を調べてみると/etc/httpd/conf/httpd.confなので変更してApacheを再起動っと。これで出来るかな?
# vi /etc/httpd/conf/httpd.conf
~DocumentRootを/var/www/html/publicに変更~
# systemctl restart httpd
やっぱダメかー。
logsディレクトリに権限設定して。
# chown apache:apache /var/www/html/storage/logs
まだダメ。
sessionsにも権限設定。既存のセッションファイルらしきものがあるので-Rで再帰指定。
# chown apache:apache -R /var/www/html/storage/framework/sessions
出来た!
せっかくなのでDockerfileに追記しておこう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# CentOSのバージョン7を指定 FROM centos:7 # Proxyの設定 ENV http_proxy http://192.168.1.250:8080 ENV https_proxy http://192.168.1.250:8080 # apacheのインストール RUN yum -y update RUN yum clean all RUN yum -y install httpd RUN systemctl enable httpd.service # PHPのインストール RUN yum -y install epel-release RUN rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm RUN yum -y install --enablerepo=remi,remi-php80 php \ php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd php-phpunit-PHPUnit \ php-pecl-xdebug php-gd php-intl php-symfony php-pdo php-xml php-tokenizer php-pear php-zip # Laravelのコードのコピー COPY src/ /var/www/html/ # パーミッションの設定 RUN chown apache:apache /var/www/html/storage/logs RUN chown -R apache:apache /var/www/html/storage/framework/sessions RUN chown -R apache:apache /var/www/html/storage/framework/views RUN chown -R apache:apache /var/www/html/storage/framework/cache |
後々似たような事が他のディレクトリでもあったので27~28行目も一緒に追記。まだ他にもあるかも。
それからhttpd.confも編集しておかないと。まずはコンテナ内からhttpd.confを取り出して。
c:\project\api>docker cp testcon1:/etc/httpd/conf/httpd.conf ./httpd.conf
DocumentRootを/var/www/html/publicに変更しておいて、ビルド時にイメージ内にコピーするようDockerfileを編集。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# CentOSのバージョン7を指定 FROM centos:7 # Proxyの設定 ENV http_proxy http://192.168.1.250:8080 ENV https_proxy http://192.168.1.250:8080 # apacheのインストール RUN yum -y update RUN yum clean all RUN yum -y install httpd RUN systemctl enable httpd.service # PHPのインストール RUN yum -y install epel-release RUN rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm RUN yum -y install --enablerepo=remi,remi-php80 php \ php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd php-phpunit-PHPUnit \ php-pecl-xdebug php-gd php-intl php-symfony php-pdo php-xml php-tokenizer php-pear php-zip # Laravelのコードのコピー COPY src/ /var/www/html/ # パーミッションの設定 RUN chown apache:apache /var/www/html/storage/logs RUN chown -R apache:apache /var/www/html/storage/framework/sessions RUN chown -R apache:apache /var/www/html/storage/framework/views RUN chown -R apache:apache /var/www/html/storage/framework/cache # httpd.confのコピー COPY ./httpd.conf /etc/httpd/conf/ |
これでコンテナ起動するだけでApacheからLaravelが見られるようになった。
Laravelのテスト
試しに一個ルートを作ってみよう。/var/www/html/routes内のweb.phpを編集してtestというルートを作ってみる。
あれ?見えない?
調べてみるとhttpd.confの151行目にある「AllowOverride None」を「AllowOverride All」にする必要があるとのこと。編集してApacheを再起動すると表示された。.htaccessの設定が使えるようにする必要があると書いてあったけどよくわからない。もうちょっとちゃんと理解して設定するべきかもしれないけどとりあえずいいや。
最後に
あんまり開発環境と関係ない話も入ってきてしまい、長くなったので一旦ここまで。