28 天來,系統只跑在你自己的電腦上。朋友想試用,就得登入你的電腦,這行不通。今天要把系統部署到雲端,讓任何人用瀏覽器就能存取。
做法是先用 Docker 把應用打包成容器(像一個隨身攜帶所有依賴的盒子),再推到 Render。Render 是適合初學者的雲端平台,會自動偵測 GitHub 上的程式碼更新,並重新部署應用。
想像你要搬家到另一個城市。最簡單的方法是把所有東西放進一個行李箱,拎著行李箱上飛機。到了目的地,打開行李箱,東西都在,不用重新買。
Docker 容器就是這樣一個行李箱。你在行李箱裡放:
不管在誰的電腦上打開這個行李箱,裡面的內容都一樣。「在我的機器上能跑」這個問題就此解決。
本地開發
↓ git push
GitHub 倉庫
↓ Render 偵測到新 commit
Render 拉代碼,執行 Dockerfile
↓ 容器啟動
生產環境公開 URL 可訪問
Render 支援自動部署:每次 push 到 GitHub,它就會自動重新建置並部署。
下載 Docker Desktop,安裝並啟動。
驗證安裝:
docker --version
# Docker version 24.x.x
sudo apt-get install docker.io
sudo usermod -aG docker $USER # 無需 sudo 執行 docker
檔案位置: backend/Dockerfile
狀態: 新建檔案
用途: 定義如何把後端打包成容器
# 使用官方 Python 基礎映像
FROM python:3.11-slim
# 設定工作目錄
WORKDIR /app
# 安裝系統依賴(某些 Python 套件需要編譯工具)
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
# 複製 requirements.txt
COPY requirements.txt .
# 安裝 Python 依賴
RUN pip install --no-cache-dir -r requirements.txt
# 複製整個 backend 資料夾
COPY . .
# 暴露 8000 埠
EXPOSE 8000
# 啟動應用
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
檔案位置: docker-compose.yml(放在項目根目錄)
狀態: 新建檔案
用途: 用容器本地測試後端和前端
version: '3.8'
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8000:8000"
environment:
- SECRET_KEY=dev-secret-key-only-for-testing
- DATABASE_URL=sqlite:///./app.db
volumes:
- ./backend:/app # 開發模式下保持代碼同步
command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8000
depends_on:
- backend
檔案位置: frontend/Dockerfile
狀態: 新建檔案
用途: 把前端打包成容器
# Build stage - 編譯 Next.js
FROM node:18-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
# 建立環境變數
ARG NEXT_PUBLIC_API_URL=http://localhost:8000
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
RUN npm run build
# Production stage - 執行應用
FROM node:18-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["npm", "start"]
# 建立並啟動容器(第一次會下載基礎映像和依賴,較慢)
docker-compose up --build
# 檢查服務是否啟動
# 後端:http://localhost:8000/docs
# 前端:http://localhost:3000
如果看到後端的 Swagger 文件頁面,容器設定正確。
停止容器:
docker-compose down
在 Render dashboard:
點 「New +」 → 「Web Service」
連接你的 GitHub 倉庫
設定如下:
learning-coach-backend
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8000
backend(如果後端在 backend 資料夾)點 「Advanced」,設定環境變數:
SECRET_KEY = (生成一個隨機字串,見下方)
DATABASE_URL = sqlite:///./app.db
點 「Create Web Service」
Render 會自動:
https://learning-coach-backend.onrender.com)點 「New +」 → 「Web Service」
連接同一個 GitHub 倉庫
設定如下:
learning-coach-frontend
npm install && npm run build
npm start
frontend
點 「Advanced」,設定環境變數:
NEXT_PUBLIC_API_URL = https://learning-coach-backend.onrender.com
(用剛才部署的後端 URL)
點 「Create Web Service」
在終端執行:
# macOS / Linux
openssl rand -hex 32
# Windows PowerShell
[System.Convert]::ToBase64String((1..32 | ForEach-Object {Get-Random -Maximum 256})) | Select-Object -First 32
複製輸出的字串,貼到 Render 的環境變數 SECRET_KEY。
在 Render dashboard:
如果有錯誤,日誌會告訴你。
# 替換成你的 Render URL
BACKEND_URL="https://learning-coach-backend.onrender.com"
# 測試後端 health check
curl $BACKEND_URL/docs
# 註冊測試用戶
curl -X POST $BACKEND_URL/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"prod@example.com","password":"password123"}'
# 應該回傳 token
打開前端 URL(類似 https://learning-coach-frontend.onrender.com),應該會看到登入頁。
查看 Logs,通常是因為:
依賴安裝失敗
ModuleNotFoundError: No module named 'fastapi'
解決:確認 requirements.txt 在正確的位置(backend/requirements.txt)
環境變數缺少
KeyError: 'SECRET_KEY'
解決:在 Render 的環境變數中加上缺少的變數
Port 綁定失敗
Address already in use
解決:確認 Start Command 用的是 --port 8000(Render 預期 8000)
應用啟動了但收不到請求。通常是:
查看日誌,找出具體錯誤訊息。
前端收到 CORS 錯誤或超時。解決方法:
NEXT_PUBLIC_API_URL 是否設對from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 簡化版允許所有來源
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Render 上的容器重啟時,SQLite 資料庫檔案(app.db)會遺失。
暫時解決:改用 PostgreSQL(Render 提供免費版本,見延伸思考)
Render 有快取。解決方法:
應用成功容器化
docker-compose up,兩個服務都啟動,沒有錯誤部署到 Render 成功
公開 URL 可存取
後端 API 正常
curl https://xxx/docs 能看到 API 文件頁面認證流程在生產環境可用
/auth/me
查看日誌
前後端整合正常
Render dashboard → 你的服務 → 頁面頂部顯示狀態:
Render dashboard
↓
你的服務
↓
Logs 標籤
↓
看到所有應用輸出
如果應用出現異常:
Render 提供基本的 CPU、記憶體使用率圖表。免費層資源有限,如果看到經常 100%,可能需要升級。
每個 RUN 指令都會建立新層。壞的寫法:
RUN apt-get update
RUN apt-get install -y gcc
RUN apt-get install -y make
RUN rm -rf /var/lib/apt/lists/* # 這層前面的層已經存了 cache 檔案
改成:
RUN apt-get update && apt-get install -y gcc make && rm -rf /var/lib/apt/lists/*
映像檔會變得非常大,部署也會很慢。
解決:建立 .dockerignore 檔案(類似 .gitignore):
__pycache__
*.pyc
.git
.gitignore
.env
.DS_Store
node_modules
dist
build
只要有人看到 Dockerfile,密碼就等於外洩。
解決:所有敏感資訊都用環境變數,從 Render 設定注入。
解決:在後端 main.py 前面加上 CORS middleware(見上方「問題 3」)。
明天是最後一天。沒有新功能,只是把整個系統梳理一遍、寫完整的 README、錄一個演示影片、分享 30 天的心得。
部署後,系統正式上線。任何人用公開 URL 就能體驗個人化 AI 學習教練。