けこのアプリ開発奮闘記

アプリ開発で得た知見を共有していきます。なるべく文章が堅くならないように意識しています。

【Docker】Vue + Nginxで作ったフロントエンド、Laravel + MySQLでバックエンドのコンテナ同士の連携

こんばんは、けこです。
今日はdocker composeを使った2つの環境の構築、そしてそれらの環境のネットワーク連携について調べました!
LaravelならフロントもDB接続もできるのにわざわざ環境を分ける必要があるのか?というところから解説していきたいと思います。

何故環境を分けるのか?
  1. Gitでのコード管理が容易

  2. スマホアプリを追加で作る際に転用できる

  3. 問題が起きた際に原因を特定しやすくなる

フロントエンドとバックエンドの環境を分けるメリットとして真っ先に上がるのはこれらの利点でしょうか、特に3の利点に関しては実運用で役立ちそうな予感がします。

Gitでのコード管理が容易

Laravelでフロントエンドとバックエンドを担当する場合、1つのリポジトリにフロントエンドとバックエンドが混在することになりどのコードを弄ったらいいかわからない...という状況が生まれることがあります。

もっとも、LaravelはMVCフレームワークなので他のフレームワークや言語を利用するという手もあります。APIだけの利用目的でもViewを返す代わりにJsonを返すプログラムを書くだけなのでとても簡単なのが嬉しいですね。

スマホアプリを追加で作る際に転用できる

最初にWebサービスを作ってから、軌道に乗ったらスマホアプリを作るというケースは少なからず存在します。
初めからAPIとしてバックエンドを独立させてSPAでフロントエンドを作っておけば、スマホアプリへの移行が簡単になります。

compose同士のネットワーク連携

本題に行きましょう、今回はVue+NginxのフロントエンドとLaravel+MySQLのバックエンドの連携にチャレンジしてみます。

2つのコンテナアプリケーションをdocker composeで立てて、それらを同じネットワークに配置できればいいわけですね。

composeを2つ用意

フロントエンド(参考:https://takake-blog.com/wsl-docker-vue-nginx/#Docker_compose

version: "3.8"

services:
  nginx:
    build: ./containers/nginx
    container_name: nginx
    ports:
      - '80:80'
    volumes:
      - ./vue_project:/var/www/html
      - ./containers/nginx/nginx.conf:/etc/nginx/nginx.conf

  vue-app:
    build: ./containers/vue_app
    container_name: vue-app
    ports:
      - '8080:8080'
    volumes:
      - ./vue_project:/app
    tty: true

バックエンド(参考:Laravel8公式)

# 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:
            - '3000:80'
        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:
            - '${FORWARD_DB_PORT:-3306}: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:
            - 'sailmysql:/var/lib/mysql'
        networks:
            - sail
        healthcheck:
            test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"]
            retries: 3
            timeout: 5s
networks:
    sail:
        driver: bridge
volumes:
    sailmysql:
        driver: local

よく見てみると、バックエンドのcomposeファイルにnetworksとの記述があります。同じようにフロントエンドにも記述してみましょう。

そしてnginxのコンテナにCLIで入ってcurl localhost:8080

f:id:keko5342:20211202032233p:plain
が...ダメ...!

networksを調べて再挑戦!

docs.docker.jp

fmfm...ネットワークを合わせる必要があって、コンテナ名でアクセスできると。
そういえばdocker compose up -dした際にネットワークが作られているような...?

composeファイルで指定したネットワークどおりにネットワークが生成されているとは限らない

docker network lsコマンドで調べたところ、フォルダ名_ + ネットワーク名でネットワークが生成されるみたいです!
つまりフロントエンドの方をバックエンドのネットワーク名に合わせてやれば...

f:id:keko5342:20211202040625p:plain
できました

今日の学び
  • networks を使う際は目的のネットワーク名を先に調べておくこと

  • networksで同じ名前を指定しても目的のネットワーク名で生成されるとは限らないということ

  • コンテナと通信する際はホスト名にコンテナ名を使えるということ

以上!やはり基本的な情報を得るためには公式情報を見に行くに限る...!これでAPIを作った時にも通信できますね!