先日、Laravel SailでDockerコンテナを複数起動し、片方のコンテナの中に内蔵されているmysqlにアクセスするということをした。
大変に時間がかかってしまったので、ここに記しておこうと思った。
ちなみに、未だに仕組みが良く分かっていない。
こんな感じなんだろうという理解なので、あまり参考にしすぎないでほしい。
やったこと
以下のsail upでのインストールを2つのプロジェクトで同じように行った。
Laravel Sail 9.x Laravel
最初に起動した方にはmysqlも含めた。
2つ目に起動するコンテナにはmysqlを含めず、最初に起動したほうのmysqlコンテナにアクセスする、というものだ。
この時点でDockerの仕組みをあまり理解してない自分は、??状態だった。
一つ目のdocker-compose.yml
# For more information: https://laravel.com/docs/sail version: '3' services: laravel.test: build: context: ./vendor/laravel/sail/runtimes/8.1 dockerfile: Dockerfile args: WWWGROUP: '${WWWGROUP}' image: sail-8.1/app extra_hosts: - 'host.docker.internal:host-gateway' ports: - '${APP_PORT:-80}:80' //.envにAPP_PORTがあればそれを、なければホストの80番でアプリのコンテナを起動。dockerの80番へポートフォワーディング。 - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' environment: WWWUSER: '${WWWUSER}' LARAVEL_SAIL: 1 XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' volumes: - '.:/var/www/html' networks: - sail depends_on: - mysql mysql: image: 'mysql/mysql-server:8.0' ports: - '4306:3306' environment: MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' MYSQL_ROOT_HOST: "%" MYSQL_DATABASE: '${DB_DATABASE}' MYSQL_USER: '${DB_USERNAME}' MYSQL_PASSWORD: '${DB_PASSWORD}' MYSQL_ALLOW_EMPTY_PASSWORD: 1 volumes: - 'sail-mysql:/var/lib/mysql' - './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh' networks: - sail healthcheck: test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"] retries: 3 timeout: 5s networks: sail: driver: bridge name: app-1 volumes: sail-mysql: driver: local
起動するときは0.0.0.0:80。ローカルでも80で動いてるから。
二つ目のdocker-compose.yml
version: '3' services: laravel.test: build: context: ./vendor/laravel/sail/runtimes/8.2 dockerfile: Dockerfile args: WWWGROUP: '${WWWGROUP}' image: sail-8.2/app extra_hosts: - 'host.docker.internal:host-gateway' ports: - '${APP_PORT:-8081}:80' //ホストの8081でアプリのコンテナ起動、dockerの80番に処理はお願いする - '${VITE_PORT:-5174}:${VITE_PORT:-5174}' environment: WWWUSER: '${WWWUSER}' LARAVEL_SAIL: 1 XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' IGNITION_LOCAL_SITES_PATH: '${PWD}' volumes: - '.:/var/www/html' networks: - sail networks: sail: driver: bridge external: true name: app-1 // 最初に起動したほうを指定する ?? volumes: sail-mysql: driver: local
起動するときは0.0.0.0:8001。ローカルでは8001で動いてるから。
分からないこと
コメントにしているポートフォワーディングの部分が良く分かってない。
ふたつのアプリがdockerの80番へリクエストを送っているのに、どうしてアプリ1と2で別の結果が返ってくるんだろう?
docker:80番は、Webサーバだから来たリクエストを認識して、そのパスのファイルを返すなり、routeにcontrollerの処理が書かれていればその先にお願いをするはず。
そこまではいい。ここからが分からん。
ローカル:80番がdocker80番にリクエストを送るときはこんな感じだろうか。
・ブラウザで0.0.0.0:80を入力
・ホストの80番が「お、おれの出番だな!ん?dockerの80番に処理はお願いするのね、了解!」
・docker80番「お、ローカルの80から依頼が来てる。なるほど80番からこのリクエストが来てるってことはこっちのアプリのこの処理をすればいいのね。 はい、生成できたからページのデータ返すよ~」
・ブラウザ「ページのデータが返ってきた!」
というイメージをしている。
だから、ホストの8001でリクエストをするときも同じはずだ。
・ブラウザで0.0.0.0:8001を入力
・ホストの8001番が「お、おれの出番だな!ん?dockerの80番に処理はお願いするのね、了解!」
・docker80番「お、ローカルの8001から依頼が来てる。なるほど8001番からこのリクエストが来てるってことはこっちのアプリのこの処理をすればいいのね。 はい、生成できたからページのデータ返すよ~」
・ブラウザ「ページのデータが返ってきた!」
こうなるんだろう。
ただ、その設定をしているのはどこなんだろう?
dockerの80番はどうやって、どのアプリにどの処理を依頼するのかを判断しているのか。
「ホスト8001で動いている者です!このパスにあるこのフォルダ名にあるものに処理を依頼してください!」という挨拶はどこに書いてあるんだろう。
リクエストヘッダーのHostとかに色々パスとか情報が入ってて、docker80番はそれを元に判別しているんだろうか。
う~ん。。。dockerの仕組みが分かっていないって話なのか、そもそもWebサーバーへの理解が不足しているのか。
多分、docker80番で動いてるのはphpのビルトインサーバなのかな。