本地next.js專案打包上傳至vps伺服器虛擬主機

文、意如

先將專案打包(壓縮)

tar -czvf .\my-website.tar.gz my-website

上傳至vps伺服器方式1(使用spc上傳)

scp -r .\my-website.tar.gz root@ip:/opt

有時候會因檔案太大,上傳到一半會斷線

第二種方式,使用SFTP

下載客戶端filezilla

 

在根目錄建立一個opt資料夾存放專案

/opt 

用途: 用於存放非系統級別的、獨立的應用程式軟體包。通常是由第三方開發者安裝的軟體。

優點: 非常適合存放像您這樣自包含的應用程式專案。它與系統軟體分離,方便管理和升級。

 

將本地專案複製進入/opt資料夾

 

連上ssh,解壓縮資料夾

tar -xzvf my-website.tar.gz

 

VPS 預設通常不會安裝 Docker。您需要根據您的 Linux 發行版來安裝。

常見的發行版有 Ubuntu、CentOS 等。戰國策的 VPS 通常是 CentOS 或 Ubuntu。

可以使用 cat /etc/os-release 命令來確認您的發行版。

Docker 安裝步驟 (適用於 AlmaLinux 8.9)

請按照以下步驟在你的 AlmaLinux 8.9 VPS 上安裝 Docker:

卸載舊版本 Docker (如果有的話): (通常新系統不會有,但執行一下無妨,以防萬一)

sudo yum remove docker \
                docker-client \
                docker-client-latest \
                docker-common \
                docker-latest \
                docker-latest-logrotate \
                docker-logrotate \
                docker-engine

 

安裝 yum-utils

yum-utils 提供了 yum-config-manager,用於管理儲存庫。

sudo yum install -y yum-utils

設置 Docker 儲存庫:

 這會添加 Docker 官方的 Yum 儲存庫到你的系統。

sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

安裝 Docker Engine, containerd, and Docker Compose

安裝 Docker 核心組件和 Docker Compose Plugin 的命令。

sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

啟動 Docker 服務並設置開機自啟動

sudo systemctl start docker
sudo systemctl enable docker

測試 Docker 安裝

sudo docker run hello-world

 Docker 已經在 AlmaLinux 8.9 VPS 上成功安裝並正常工作了!

sudo docker run hello-world 的輸出清楚地表明:

Docker 客戶端與 Docker 守護進程(daemon)進行了通信。

Docker 從 Docker Hub 下載了 hello-world 映像檔。

Docker 從該映像檔創建並運行了一個容器。

容器輸出了 "Hello from Docker!"。

現在可以開始部署 my-website 專案了。

 


切換到 my-website目錄

 

執行新的 Docker Compose 命令:

docker compose up -d --build

接下來,針對伺服器上的專案做些微的調整

本機端常常執行沒問題,但打包到 VPS 就問題,這個問題很常見!請耐心修正

檔案:Dockerfile

# 使用 Node 環境
FROM node:18-alpine

# 設定容器內的工作目錄為你的 Next.js 應用程式實際所在的目錄
WORKDIR /app

# 複製 package.json 和 package-lock.json 到工作目錄
COPY app/package*.json ./

# 安裝 Next.js 應用程式的相依套件
RUN npm install --unsafe-perm

# 複製其他應用程式程式碼到工作目錄
COPY app/. .

# 在構建階段使用 root 用戶執行 build
USER root

# Explicitly add node_modules/.bin to PATH for the build step (保留,以防萬一)
ENV PATH="/app/node_modules/.bin:${PATH}"

# IMPORTANT: 手動為 'next' 和 'prisma' 可執行文件添加執行權限
RUN chmod +x /app/node_modules/.bin/next || true \
 && chmod +x /app/node_modules/.bin/prisma || true

RUN npx prisma generate

# 編譯 Next.js 專案
RUN npx next build

# 創建用於圖片上傳的目錄並設置權限
RUN mkdir -p /app/public/uploads/news && chown -R node:node /app/public/uploads && chmod -R 755 /app/public/uploads

# 在運行時切換到非特權用戶,這是生產環境的最佳實踐
USER node

# 開放 3000 port
EXPOSE 3000

# 啟動應用程式
CMD ["npm", "start"]

docker-compose.yml


services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=mysql://root:root@db:3306/mywebsite
    # 修改 depends_on,添加 condition: service_healthy
    depends_on:
      db:
        condition: service_healthy
    command: sh -c "npx prisma migrate deploy && npm start"

  db:
    image: mysql:latest
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mywebsite
    volumes:
      - db_data:/var/lib/mysql
    # 添加 healthcheck
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"] # 使用 root/root 測試連接
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s # 給予 MySQL 30 秒的啟動時間

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    ports:
      - "8080:80"
    environment:
      PMA_HOST: db
      MYSQL_ROOT_PASSWORD: root
    depends_on:
      db:
        condition: service_healthy # 也可以為 phpmyadmin 添加此條件
volumes:
  db_data:
  
 



有問題,或是有變更要記得重啟,重啟後資料庫的內容會刪除並重新建立,如果有資料記得要備份,

關閉

docker compose down --volumes

重啟

 docker compose up -d --build

查看logs

docker compose logs app

此時發生登入後(帳號密碼正確但無法跳轉到首頁)

檢查 Secure Cookie 屬性,在 src/app/api/admin/login/route.ts 中,

暫時將 res.cookies.setsecure 屬性改為 false

res.cookies.set("admin_token", token, {
  httpOnly: true,
  // secure: process.env.NODE_ENV === "production", // 暫時註釋或改為 false
  secure: false, // <-- 改成 false
  path: "/",
  maxAge: 60 * 60 * 2,
  sameSite: "lax",
});

重新構建並啟動 Docker 容器

docker compose down
docker compose build --no-cache
docker compose up -d

 

Yiru@Studio - 關於我 - 意如