使用 Nodejs、Express、Sequelize、Postgres、Docker 和 Docker Compose 的 JavaScript CRUD Rest API 简介分步指南 Docker 部分构建 Docker 镜像并运行 Docker 容器结论

2025-05-24

使用 Nodejs、Express、Sequelize、Postgres、Docker 和 Docker Compose 的 JavaScript CRUD Rest API

简介

分步指南

Docker 部分

构建 Docker 镜像并运行 Docker 容器

结论

让我们用 JavaScript 创建一个 CRUD rest API,使用:

  • Node.js
  • 表达
  • 续集
  • Postgres
  • Docker
  • Docker Compose

所有代码均可在 GitHub 存储库中找到(链接在视频描述中):https://youtube.com/live/Uv-jMWV29rU


简介

以下是我们要创建的应用程序架构图:

对 Node.js 应用和 Postgres 服务进行 crud、read、update、delete 操作,并通过 docker compose 连接。使用 POstman 和 tableplus 进行测试

我们将为基本的 CRUD 操作创建 5 个端点:

  • 创造
  • 阅读全部
  • 阅读一篇
  • 更新
  • 删除

我们将使用以下内容创建一个 Node.js 应用程序:

  • Express 作为框架
  • Sequelize 作为 ORM
  1. 我们将 Docker 化 Node.js 应用程序

  2. 我们将有一个 Postgres 实例,我们将使用 Tableplus 对其进行测试

  3. 我们将创建一个 docker compose 文件来运行这两个服务

  4. 我们将使用 Postman 测试 API


分步指南

以下是分步指南。

创建新文件夹



mkdir node-crud-api


Enter fullscreen mode Exit fullscreen mode

踏入其中



cd node-crud-api


Enter fullscreen mode Exit fullscreen mode

初始化一个新的 npm 项目



npm init -y


Enter fullscreen mode Exit fullscreen mode

安装依赖项



npm i express pg sequelize


Enter fullscreen mode Exit fullscreen mode
  • express 是 Node.js 框架
  • pg 是与 Postgres db 连接的驱动程序
  • sequelize 是 ORM,因此我们避免输入 SQL 查询

创建 4 个文件夹



mkdir controllers routes util models


Enter fullscreen mode Exit fullscreen mode

使用你喜欢的 IDE 打开文件夹。如果你有 Visual Studio Code,可以在终端中输入以下命令:



code .


Enter fullscreen mode Exit fullscreen mode

您现在应该有一个类似于此的文件夹:

controller、routes、model、util 文件夹、node_modules 和 package.json 文件、package-lock.json 文件

现在让我们开始编码。

数据库连接

在“util”文件夹中创建一个名为“database.js”的文件。

该文件将包含内部配置,以允许 Node.js 应用程序和正在运行的 Postgres 实例之间的连接。

填充 util/database.js 文件



const Sequelize = require('sequelize');

const sequelize = new Sequelize(
    process.env.PG_DB,
    process.env.PG_USER,
    process.env.PG_PASSWORD,
    {
        host: process.env.PG_HOST,
        dialect: 'postgres',
    }
);

module.exports = sequelize;


Enter fullscreen mode Exit fullscreen mode

用户模型

在“models”文件夹中创建一个名为“user.js”的文件。

该文件将包含模型,在本例中为具有自动递增 ID、姓名和电子邮件的用户。

填充 models/user.js 文件:



const Sequelize = require('sequelize');
const db = require('../util/database');

const User = db.define('user', {
    id: {
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true
    },
    name: Sequelize.STRING,
    email: Sequelize.STRING
});

module.exports = User;


Enter fullscreen mode Exit fullscreen mode

控制器

该文件包含与数据库交互所需执行的所有函数,并具有 4 个基本功能:

在“controllers”文件夹中创建一个名为“users.js”的文件

填充 controllers/users.js 文件



const User = require('../models/user');

// CRUD Controllers

//get all users
exports.getUsers = (req, res, next) => {
    User.findAll()
        .then(users => {
            res.status(200).json({ users: users });
        })
        .catch(err => console.log(err));
}

//get user by id
exports.getUser = (req, res, next) => {
    const userId = req.params.userId;
    User.findByPk(userId)
        .then(user => {
            if (!user) {
                return res.status(404).json({ message: 'User not found!' });
            }
            res.status(200).json({ user: user });
        })
        .catch(err => console.log(err));
}

//create user
exports.createUser = (req, res, next) => {
  const name = req.body.name;
  const email = req.body.email;
  User.create({
    name: name,
    email: email
  })
    .then(result => {
      console.log('Created User');
      res.status(201).json({
        message: 'User created successfully!',
        user: result
      });
    })
    .catch(err => {
      console.log(err);
    }); 
}

//update user
exports.updateUser = (req, res, next) => {
  const userId = req.params.userId;
  const updatedName = req.body.name;
  const updatedEmail = req.body.email;
  User.findByPk(userId)
    .then(user => {
      if (!user) {
        return res.status(404).json({ message: 'User not found!' });
      }
      user.name = updatedName;
      user.email = updatedEmail;
      return user.save();
    })
    .then(result => {
      res.status(200).json({message: 'User updated!', user: result});
    })
    .catch(err => console.log(err));
}

//delete user
exports.deleteUser = (req, res, next) => {
  const userId = req.params.userId;
  User.findByPk(userId)
    .then(user => {
      if (!user) {
        return res.status(404).json({ message: 'User not found!' });
      }
      return User.destroy({
        where: {
          id: userId
        }
      });
    })
    .then(result => {
      res.status(200).json({ message: 'User deleted!' });
    })
    .catch(err => console.log(err));
}


Enter fullscreen mode Exit fullscreen mode

路线

在“routes”文件夹中创建一个名为“users.js”的文件。

填充 routes/users.js 文件



const controller = require('../controllers/users');
const router = require('express').Router();

// CRUD Routes /users
router.get('/', controller.getUsers); // /users
router.get('/:userId', controller.getUser); // /users/:userId
router.post('/', controller.createUser); // /users
router.put('/:userId', controller.updateUser); // /users/:userId
router.delete('/:userId', controller.deleteUser); // /users/:userId

module.exports = router;


Enter fullscreen mode Exit fullscreen mode

索引文件

要运行我们的应用程序,我们需要在根级别创建更多文件。这是将由 docker 容器执行的文件。

在根文件夹中,创建一个名为 index.js 的文件

填充“index.js 文件”:



const express = require('express');
const bodyparser = require('body-parser');
const sequelize = require('./util/database');
const User = require('./models/user');

const app = express();

app.use(bodyparser.json());
app.use(bodyparser.urlencoded({ extended: false }));

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  next();
});

//test route
app.get('/', (req, res, next) => {
  res.send('Hello World');
});

//CRUD routes
app.use('/users', require('./routes/users'));

//error handling
app.use((error, req, res, next) => {
  console.log(error);
  const status = error.statusCode || 500;
  const message = error.message;
  res.status(status).json({ message: message });
});

//sync database
sequelize
  .sync()
  .then(result => {
    console.log("Database connected");
    app.listen(3000);
  })
  .catch(err => console.log(err));


Enter fullscreen mode Exit fullscreen mode

Docker 部分

让我们在根级别创建另外 3 个文件:

  • .dockerignore(以点开头)
  • Dockerfile(大写 D)
  • docker-compose.yml

结构看起来应该是这样的:

图片描述

.dockerignore 将包含一行:



node_modules


Enter fullscreen mode Exit fullscreen mode

.dockerignore 文件包含一行:node_modules


Dockerfile

要创建 Docker 镜像,我们需要一个简单但功能强大的文件。它叫做“Dockerfile”(大写 D)。我们可能会使用其他名称,但目前我们先简单介绍一下。



FROM node:14

# Create app directory
WORKDIR /app

COPY package*.json ./

RUN npm install

# Bundle app source
COPY . .

EXPOSE 3000

CMD [ "node", "index.js" ]


Enter fullscreen mode Exit fullscreen mode

Docker 撰写文件

要运行多个服务,一个简单的方法是创建一个名为“docker-compose.yml”的文件

docker-compose.yml 文件:



version: "3.9"

services:
  node_app:
    container_name: node_app
    build: .
    image: francescoxx/node_live_app
    ports:
      - "3000:3000"
    environment:
      - PG_DB=node_live_db
      - PG_USER=francesco
      - PG_PASSWORD=12345
      - PG_HOST=node_db
    depends_on:
      - node_db

  node_db:
    container_name: node_db
    image: postgres:12
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=node_live_db
      - POSTGRES_USER=francesco
      - POSTGRES_PASSWORD=12345
    volumes:
      - node_db_data:/var/lib/postgresql/data

volumes:
  node_db_data: {}


Enter fullscreen mode Exit fullscreen mode

构建 Docker 镜像并运行 Docker 容器

在容器中运行 Postgres

首先,让我们运行 postgres 容器:



docker compose up -d node_db


Enter fullscreen mode Exit fullscreen mode

要检查日志,我们可以输入:



docker compose logs


Enter fullscreen mode Exit fullscreen mode

您应该得到类似这样的输出:

..... 2023-02-12 13:07:41.342 UTC [1] LOG: 数据库系统已准备好接受连接

如果我们看到“数据库系统已准备好接受连接”,那么我们就可以开始了!

让我们使用 TablePlus 来测试它。

单击 + 创建新连接

图片描述

从 docker-compose.yml 文件复制值。(如果保留原值,则密码为 12345)

图片描述

构建并运行 Docker 服务

其次,让我们构建我们的 Docker 图像:



docker compose build


Enter fullscreen mode Exit fullscreen mode

图片描述

最后,让我们启动服务:



docker compose up node_app


Enter fullscreen mode Exit fullscreen mode

这应该是终端上的输出

图片描述

使用 Postman 测试应用程序

让我们使用 Postman 测试该应用程序。

向 localhost:3000 发出 GET 请求

图片描述

向 localhost:3000/users 发出 GET 请求

我们应该有一个空数组作为响应

图片描述

让我们创建 3 个用户:aaa、bbb 和 ccc

图片描述

图片描述

图片描述

让我们再次检查所有用户:

向 localhost:3000/users 发出 GET 请求

我们应该看到 3 个用户:

图片描述

让我们获取一个用户,例如用户 2

向 localhost:3000/users/2 发出 GET 请求

图片描述

让我们更新一个现有的用户,例如同一个用户 2

使用不同的主体向 localhost:3000/users/2 发出 PUT 请求

图片描述

最后,我们删除3号用户

向 localhost:3000/users/3 发出 DELETE 请求

图片描述

我们还可以使用 TablePlus 检查值

图片描述

结论

这是如何使用 Node.js、Express、Sequelize、Postres、Docker 和 Docker Compose 构建 CRUD rest API 的基本示例。

所有代码均可在 GitHub 存储库中找到(链接在视频描述中):https://youtube.com/live/Uv-jMWV29rU

就这样。
如果您有任何疑问,请在下面发表评论。

弗朗西斯科

文章来源:https://dev.to/francescoxx/build-a-crud-rest-api-in-javascript-using-nodejs-express-postgres-docker-jkb
PREV
TypeScript CRUD Rest API,使用 Nest.js、TypeORM、Postgres、Docker 和 Docker Compose
NEXT
🧙‍​​♂️ CSS 技巧:从高度 0 过渡到自动!