AI 生成的摘要
## 本地测试 本文提供了如何在本地环境中测试一个基于 Node.js 的项目的详细指南。通过 Dockerfile 构建镜像,设置数据库(MySQL)和缓存系统(Redis)。文章还介绍了如何配置 Docker Compose 并使用 GitHub Actions 部署代码到服务器。 目录展示了 Dockerfile 用于构建镜像的配置,deploy.sh 脚本用于应用程序的数据库迁移和启动服务。然后通过修改阿里云镜像加速 Docker 镜像下载。接下来,提供了 Docker Compose 文件配置并展示如何在服务运行后检查系统状态。 为了服务器部署,文章进行了 Docker 安装和 GitHub Actions 配置,以实现自动化部署。最后,更新了部署脚本和 GitHub Actions 工作流配置,确保在部署新代码后正确运行。 配置文件和脚本确保项目的依赖项以及环境变量正确无误,使部署过程更为简化和自动化。文章配有多个图示,帮助读者更好理解和配置。 本指南详细且实用,适用于任何希望将 Node.js 应用部署到 Docker 和云服务器的开发者。

本地测试

目录:

Dockerfile
FROM node:22-alpine as builder

WORKDIR /app
COPY . .

ENV CI=true

RUN npm install -g pnpm
RUN npm install -g pm2

RUN pnpm install

RUN cd apps/core && npx prisma generate

RUN pnpm run build

COPY ecosystem.config.js .

COPY script/deploy.sh .

RUN chmod +x deploy.sh

EXPOSE 2333

CMD ["./deploy.sh"]
deploy.sh
sh
#!/bin/sh

echo "Running database migrations..."
(cd apps/core && npx prisma migrate deploy)
echo "Starting application with PM2..."
pm2-runtime ecosystem.config.js
修改阿里云镜像
"registry-mirrors": [
    "https://registry.cn-hangzhou.aliyuncs.com"
]

构建镜像:

sh
sudo docker build -t nexo-admin .

报错:

sh
sudo docker build -t nexo-admin .
Password:
[+] Building 0.3s (2/3)                                                                               docker:desktop-linux
[+] Building 1.3s (2/3)                                                                               docker:desktop-linux
[+] Building 1.4s (3/3) FINISHED                                                                      docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                                  0.0s
 => => transferring dockerfile: 253B                                                                                  0.0s
 => [internal] load .dockerignore                                                                                     0.0s
 => => transferring context: 2B                                                                                       0.0s
 => ERROR [internal] load metadata for docker.io/library/node:20-alpine                                               1.3s
------
 > [internal] load metadata for docker.io/library/node:20-alpine:
------
Dockerfile:1
--------------------
   1 | >>> FROM node:20-alpine
   2 |     
   3 |     RUN npm install -g pnpm
--------------------
ERROR: failed to solve: node:20-alpine: error getting credentials - err: exit status 1, out: ``

pull node 镜像即可

sh
sudo docker pull node:22-alpine

这样就这个镜像就是正常的

配置 docker-compose

docker-compose.yml
yml
version: '1.0'
services:
  mysql:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: nexo-admin
      MYSQL_DATABASE: nexo
      MYSQL_USER: nexo
      MYSQL_PASSWORD: nexo-admin
    volumes:
      - mysql-data:/var/lib/mysql
    ports:
      - '3306:3306'

  redis:
    image: redis:5-alpine
    restart: always
    command: redis-server --requirepass nexo-admin
    volumes:
      - redis-data:/data
    ports:
      - '6379:6379'

  nexo-core:
    image: nexo-core:latest
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - '2333:2333'
    depends_on:
      - mysql
      - redis
    environment:
      - DATABASE_URL=mysql://root:nexo-admin@mysql:3306/nexo?schema=public
      - REDIS_HOST=redis
volumes:
  mysql-data:
    driver: local
  redis-data:
    driver: local

配置完成后,使用命令启动:

sh
docker-compose up -d

查看启动是否正常:

服务器部署

安装 docker link-favicon链接

使用github action上传代码

.github/workflows/deploy.yaml
yaml
name: Deploy to Server

on:
  push:
    branches:
      - master
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Deploy to server
        uses: appleboy/scp-action@master
        with:
          host: ${{ vars.SSH_HOST }}
          username: ${{ vars.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          source: ./
          target: ~/nexo-core/
          strip_components: 0
          timeout: 120s
          overwrite: true
          rm: true

服务器信息在代码仓库中设置

服务器中运行docker compose up -d 启动项目。可以在服务器单独配置一个.env文件放项目的环境变量

更新:

deploy.sh
sh
#!/bin/bash                                                                                                                               
set -e                                                                                                                                                         
# 颜色定义                                                                                                                                                      

GREEN='\033[0;32m'                                                                                                                                                

RED='\033[0;31m'                                                                                                                                                  

NC='\033[0m'                                                                                                                                                      

# 路径配置                                                                                                                                                        

ENV_SOURCE=~/env/core-env                                                                                                                                         

ENV_TARGET=~/nexo-core/apps/core/.env                                                                                                                             

PROJECT_DIR=~/nexo-core                                                                                                                                           

start_time=$(date +%s)                                                                                                                                            

echo -e "${GREEN}📁 开始部署 nexo-core${NC}"                                                                                                                      

# 检查文件                                                                                                                                                        

if [ ! -f "$ENV_SOURCE" ]; then                                                                                                                                   

  echo -e "${RED}❌ 环境变量文件不存在:$ENV_SOURCE${NC}"                                                                                                         

  exit 1                                                                                                                                                          

fi                                                                                                                                                                

if [ ! -d "$PROJECT_DIR" ]; then                                                                                                                                  

  echo -e "${RED}❌ 项目目录不存在:$PROJECT_DIR${NC}"                                                                                                            

  exit 1                                                                                                                                                          

fi                                                                                                                                                                

# 拷贝 .env                                                                                                                                                       

echo -e "${GREEN}✅ 拷贝环境文件...${NC}"                                                                                                                         

sudo cp "$ENV_SOURCE" "$ENV_TARGET"                                                                                                                               

# 构建镜像                                                                                                                                                        

cd "$PROJECT_DIR"                                                                                                                                                 

echo -e "${GREEN}🔨 构建镜像中...${NC}"                                                                                                                           

docker compose build --no-cache nexo-core || {                                                                                                                    

  echo -e "${RED}❌ 镜像构建失败!${NC}"                                                                                                                          

  exit 1                                                                                                                                                          

}                                                                                                                                                                 

# 启动服务                                                                                                                                                        

echo -e "${GREEN}🚀 启动服务...${NC}"                                                                                                                             

docker compose up -d nexo-core || {                                                                                                                               

  echo -e "${RED}❌ 服务启动失败!${NC}"                                                                                                                          

  exit 1                                                                                                                                                          

}                                                                                                                                                                 

# 删除 dangling 镜像                                                                                                                                              

echo -e "${GREEN}🧹 清理无用镜像...${NC}"                                                                                                                         

dangling_images=$(docker images -f "dangling=true" -q)                                                                                                            

if [ -n "$dangling_images" ]; then                                                                                                                                

  docker rmi $dangling_images                                                                                                                                     

  echo -e "${GREEN}✅ 已删除 dangling 镜像。${NC}"                                                                                                                

else                                                                                                                                                              

  echo -e "${GREEN}ℹ️ 无 dangling 镜像可清理。${NC}"                                                                                                               

fi                                                                                                                                                                

end_time=$(date +%s)                                                                                                                                              

echo -e "${GREEN}✅ 部署完成,用时 $((end_time - start_time)) 秒。${NC}"

修改github action

.github/workflows/deploy.yaml
yaml
name: Deploy to Server

on:
  push:
    branches:
      - master
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Deploy to server
        uses: appleboy/scp-action@master
        with:
          host: ${{ vars.SSH_HOST }}
          username: ${{ vars.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          source: ./
          target: ~/nexo-core/
          strip_components: 0
          timeout: 120s
          overwrite: true
          rm: true

      - name: Execute deployment script
        uses: appleboy/ssh-action@master
        with:
          host: ${{ vars.SSH_HOST }}
          username: ${{ vars.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            sh ~/deploy/nexo-core-deploy.sh