Section 1

D4 – 來吧!用 Docker 打造開發環境(Laravel + Nuxt + Nginx + MariaDB)

好了,到了這個階段,我們終於要進入 Docker 的世界了!前幾篇文章我們討論了系統規劃與需求,現在來到實作的部分,要為整個開發環境打好基礎。這篇文章將帶你一步步打造出一個基於 Docker 的開發環境,裡面包含了 Laravel(後端)、Nuxt(前端)、Nginx(伺服器),以及 MariaDB(資料庫)。這不僅能讓我們的開發流程更加順暢,也保證開發、測試和部署環境一致。

這次我們會用到以下目錄結構來組織專案:

→ .docker-env/
→→ api/
→→→ Dockerfile
→→ nginx/
→→→ api.conf
→→→ web.conf
→→ web/
→→→ Dockerfile
→ api/
→ web/
→ docker-compose.yml

https://ithelp.ithome.com.tw/upload/images/20240917/20103068YVQPNRzDO3.png
是不是很乾脆?接下來,讓我們逐步拆解,看看如何用 Docker 來輕鬆管理這些服務!

因為觀看這篇文章的朋友們,手頭上的環境都不太相同,要列出mac、linux、windows 各Docker安裝步驟會太冗長,在麻煩自行安裝囉

一、準備工作:docker-compose 的設定

首先,我們會在根目錄下建立 docker-compose.yml 檔案,這是 Docker Compose 的設定檔。它會管理我們的 Laravel、Nuxt、Nginx、MariaDB 四個服務,讓它們在同一個網路中彼此協作。以下是我們的 docker-compose.yml 設定檔:

YAML
version: '3.8'

services:
  # Laravel (backend)
  backend:
    build:
      dockerfile: ./.docker-env/api/Dockerfile
    container_name: laravel-app
    restart: on-failure
    volumes:
      - ./api:/var/www/html
    environment:
      - APP_ENV=local
      - APP_DEBUG=true
      - DB_CONNECTION=mysql
      - DB_HOST=db
      - DB_PORT=3306
      - DB_DATABASE=finance
      - DB_USERNAME=root
      - DB_PASSWORD=root
    command: bash -c "if [ ! -f composer.json ]; then composer create-project --prefer-dist laravel/laravel .; fi && composer install && php-fpm"
    depends_on:
      - db
    networks:
      - app-network

  # Nuxt.js (frontend)
  frontend:
    build:
      dockerfile: ./.docker-env/web/Dockerfile
    container_name: nuxt-app
    restart: unless-stopped
    volumes:
      - ./web:/app
    ports:
      - "3000:3000"
    command: sh -c "if [ ! -f package.json ]; then npx nuxi init .; fi && npm install && npm run dev"
    depends_on:
      - backend
    networks:
      - app-network

  # Nginx for serving Laravel and Nuxt
  nginx:
    image: nginx:alpine
    container_name: nginx
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - ./.docker-env/nginx/api.conf:/etc/nginx/conf.d/api.conf
      - ./.docker-env/nginx/web.conf:/etc/nginx/conf.d/web.conf
    depends_on:
      - backend
      - frontend
    networks:
      - app-network

  # MySQL (Database)
  db:
    image: mariadb:latest
    container_name: mariadb
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: finance
      MYSQL_USER: root
      MYSQL_PASSWORD: root
    volumes:
      - "./.docker-env/.db_data/mysql:/var/lib/mysql"
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

這個 docker-compose.yml 檔案會將所有的服務設定在一個橋接網路中,這樣每個服務都能輕鬆地互相通信。

二、Laravel 後端 Dockerfile 設定

現在來看看 Laravel 部分的 Dockerfile 設定。這個 Dockerfile 會幫我們設定一個 PHP 開發環境,並安裝 Laravel 所需的依賴。

Dockerfile
# 使用 PHP 基礎映像檔
FROM php:8.2-fpm

# 安裝相關依賴套件
RUN apt-get update > /dev/null && apt-get install -y \
   git \
   unzip \
   libjpeg-dev \
   libxpm-dev \
   libwebp-dev \
   libfreetype6-dev \
   libjpeg62-turbo-dev \
   libzip-dev \
   libpng-dev \
   zlib1g-dev \
   libicu-dev \
   jpegoptim \
   g++ \
   libxrender1 \
   libfontconfig

# 安裝 PHP zip 擴展
RUN docker-php-ext-install intl > /dev/null \
   && docker-php-ext-install zip > /dev/null \
   && docker-php-ext-install bcmath > /dev/null \
   && docker-php-ext-install pdo pdo_mysql mysqli > /dev/null

# 安裝 Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# 設置工作目錄
WORKDIR /var/www/html

# 複製專案檔案
COPY ../../api .

# 設置正確的權限
RUN chown -R www-data:www-data /var/www/html

# Expose port 9000 and start PHP-FPM server
EXPOSE 9000
CMD ["php-fpm"]

這個 Dockerfile 會幫我們把 PHP 8.2 環境以及需要的擴展安裝好,同時設定好 Composer,讓我們的 Laravel 專案可以在 Docker 裡面順利運行。

三、Nuxt 前端 Dockerfile 設定

接下來是前端 Nuxt 的部分,我們會在 .docker-env/web/Dockerfile 中配置 Node.js 環境。這裡使用的是 Alpine 版本的 Node 20,它既輕量又高效,非常適合用來開發 Nuxt 應用。

Dockerfile
# 使用 Node.js 20 映像
FROM node:20-alpine

# 設置工作目錄
WORKDIR /app

# 複製 package.json 和 package-lock.json
COPY package*.json ./

# 不在這裡安裝依賴,等待容器啟動時處理

# 複製源代碼
COPY ../../web .

# 暴露端口
EXPOSE 3000

# 開發環境會延遲到容器啟動時才執行

這個 Dockerfile 設定完後,當我們啟動容器時,它會在第一次運行時自動安裝 Nuxt 所需的依賴並啟動開發伺服器。

四、Nginx 設定檔

為了讓 Laravel 和 Nuxt 都能透過 Nginx 提供服務,我們需要設置兩個 Nginx 配置檔:api.conf 和 web.conf。這些檔案會告訴 Nginx 如何代理請求給後端 Laravel 和前端 Nuxt。

Laravel 的 Nginx 設定 (api.conf)

Nginx
# Laravel API server
server {
    listen 80;
    server_name api.localhost;
    index index.php index.html;
    root /var/www/html/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass laravel-app:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location ~ /\.ht {
        deny all;
    }
}

Nuxt 的 Nginx 設定 (web.conf)

Nginx
# 代理 Nuxt 請求
server {
    listen 80;
    server_name web.localhost;

    root /usr/share/nginx/html;
    index index.html;

    location / {
        proxy_pass http://nuxt-app:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

這樣配置完後,我們的 Nginx 會處理來自 api.localhost 和 web.localhost 的請求,並將它們分別代理到 Laravel 和 Nuxt 的容器。

五、測試開發環境

現在,所有設定檔都完成了,接下來就是要讓它們跑起來!只需執行以下指令:

Bash
docker-compose up --build

當一切順利時,Laravel 和 Nuxt 都應該能透過 Nginx 正常運行。你可以透過 兩個設定好的Domain來訪問它們,後端會通過 api.localhost 提供 API,前端則會通過 web.localhost 提供頁面。

因為這兩組Domain是虛的!所以需要自行設定hosts,這樣才能看到相關的內容,並且要檢查每個服務是否能正確啟動!

下一步

到這裡,我們已經成功建立了一個基於 Docker 的開發環境,裡面包含了 Laravel、Nuxt、Nginx 和 MariaDB。這樣的架構讓我們能輕鬆管理多個服務,並保證開發環境與部署環境的一致性。接下來,讓我們進一步深入,了解 Nginx 如何作為反向代理,來協調前後端之間的溝通。
在下一篇文章《拆解 Docker 環境:快速理解 Nginx 反向代理 Nuxt 和 Laravel 的關係》中,我們將深入探討 Nginx 是如何在這個架構中,充當前端與後端的「守門員」,確保流量順暢進行。
你將會了解到:

  • Nginx 作為反向代理的角色:如何將來自客戶端的請求正確地轉發到 Nuxt 或 Laravel。
  • 為什麼需要反向代理?以及它在負載平衡、安全性和資源管理上的優勢。
  • 如何透過 Nginx 配置,精準控制前端 Nuxt 與後端 Laravel 的互動。
    準備好深入理解 Nginx 與 Docker 之間的魔法了嗎?讓我們繼續前進吧!