Fastify, Postgres 및 Docker가 있는 CRUD API

여보세요, 프란시스코입니다.트위터에서 저를 찾을 수 있어요.
공개 작성 내용
이 모든 내용은 2개의 라이브 스트리밍 기간에 처음부터 만들어졌습니다.
만약 내가 어떻게 이 내용을 만들었는지 보고 싶다면, 여기에 링크가 있다. (심지어 이 글 자체도 내용의 일부분이다.)

제1부


제2부분


이 문서에서는 다음과 같은 몇 가지 CRUD API를 설정합니다.
  • 노드js(JavaScript 런타임 엔진)
  • Fastfy(Node.js의 빠른 저비용 웹 프레임워크에 사용)
  • Postgres(PostgreSQL)는 무료 소스 오픈 관계 데이터베이스로 매우 유행하고 안정적이다
  • Docker(용기를 사용하여 응용 프로그램을 배치하는 플랫폼)
  • GitHub 저장소: https://github.com/FrancescoXX/study-with-me-fastify-docker

    노트



    Node는 백엔드 JavaScript 런타임 환경으로, 컴퓨터에서 JavaScript 코드(예: 컴퓨터나 Node를 설치한 컴퓨터)를 실행할 수 있습니다.좋습니다. Docker를 사용하면 실제적으로 설치할 필요가 없습니다. 노드 이미지를 사용할 것이기 때문에 제 기계에 설치된 노드 버전과 버전 사이의 버전 제어를 피할 수 있습니다.

    금식하다



    Fastify는 성능에 전념하는 웹 프레임워크입니다.그것의 영감은 Hapi와 Express에서 왔다. 그것은 틀림없이 시내에서 가장 빠른 웹 프레임워크 중의 하나일 것이다.

    박사후



    Postgres(PostgreSQL)는 무료 소스 관계 데이터베이스로 매우 유행하고 안정적이다

    부두 노동자



    Docker는 용기 사상을 이용하여 응용 프로그램을 실행하고 공유하는 플랫폼을 구축한다.만약 당신이 간단한 소개를 원한다면, 여기에 간단한 영상이 하나 있다

    차근차근

  • fastify postgres docker라는 폴더를 만들고 입력하십시오.
  • mkdir fastify-postgres-docker && cd fastify-postgres-docker
    
  • npm로 노드 응용 프로그램 초기화
  • npm init -y
    
  • 설치 종속성
  • npm install fastify fastify-postgres pg
    
  • 애플리케이션 폴더 생성 및 입력
  • mkdir app && cd app
    
    src 폴더에서 서버를 만듭니다.js 파일과 루트입니다.js 파일
    폴더 구조는 다음과 같아야 한다

    서버를 작성합시다.js 파일
    const fastify = require('fastify')({ logger: true });
    fastify.register(require('fastify-postgres'), {
      connectionString: `postgres://${process.env.POSTGRES_USER}:${process.env.POSTGRES_PASSWORD}@${process.env.POSTGRES_SERVICE}:${process.env.POSTGRES_PORT}/${process.env.POSTGRES_DB}`,
    });
    fastify.register(require('./routes'));
    
    // Run the server
    const start = () => {
      fastify.listen(3000, '0.0.0.0', (err, address) => {
        if (err) {
          fastify.log.error(err);
          process.exit(1);
        }
      });
    };
    start();
    
    Fastify 플러그인 개념을 사용하면 더 많은 정보를 볼 수 있습니다
    https://www.fastify.io/docs/master/Plugins/
    노선의 첫 부분을 쓰자.js 파일
    async function routes(fastify, options) {
      // Testing route
      fastify.get('/', async (request, reply) => {
        return { hello: 'world' };
      });
    }
    
    module.exports = routes;
    

    부두 노동자



    지금은 부두 일꾼 부분이야!
    홈 폴더에 세 개의 파일을 만듭니다.
  • Dockerfile
  • docker compose.yml
  • .dockerignore(점으로 시작)
  • 이거.dockerignore 파일:
    node_modules
    .gitignore
    .env
    
    Dockerfile:
    FROM node:14
    
    EXPOSE 3000
    
    # Use latest version of npm
    RUN npm install npm@latest -g
    
    COPY package.json package-lock.json* ./
    
    RUN npm install --no-optional && npm cache clean --force
    
    # copy in our source code last, as it changes the most
    WORKDIR /usr
    
    COPY . .
    
    CMD [ "node", "app/server.js"]
    
    부두 일꾼이 작곡하다.yml 파일:
    version: '3.8'
    services:
      fastify_backend:
        container_name: fastify_backend
        image: francescoxx/fastify_backend:0.0.1
        build:
          context: .
        ports:
          - '3000:3000'
        env_file: .env
        depends_on: 
          - postgres
    
      postgres:
        container_name: postgres
        hostname: postgres
        image: 'postgres:13'
        ports:
          - '5432:5432'
        restart: always
        env_file: .env
        volumes:
          - fastify_volume:/var/lib/postgres/data
    
    volumes:
      fastify_volume: {}
    
    이미지 "francescoxx/fastify backend:0.0.1"을 선택한 이미지 이름으로 바꿉니다!
    Google 서비스를 실행하기 전에, Google은 하나를 만들어야 합니다.env 파일은 환경 변수를 저장하고 우리가 필요로 하는 모든 환경 변수로 채웁니다.
    POSTGRES_USER=francesco
    POSTGRES_PASSWORD=dbpassword
    POSTGRES_DB=fastifydb
    POSTGRES_SERVICE=postgres
    POSTGRES_PORT=5432
    
    종료 파일은 다음과 같습니다.

    당신은 자신의 필요에 따라 상응하는 변경을 할 수 있습니다!
    Postgres 서비스를 시작하겠습니다.
    docker-compose up -d postgres
    
    Postgres DB를 시작하고 실행해야 합니다!
    데이터베이스의 내용을 살펴보겠습니다.
    다른 터미널에서 입력
    docker exec -it postgres psql -U francesco fastifydb
    
    일단 저희가 용기에 들어가면...
    (postgres=#terminal을 검사하여 이 점을 검증할 수 있습니다)
    fastifydb 데이터베이스에 연결
    \c fastifydb
    
    이것은postgres가 시작할 때 전달하는 환경 변수를 사용하여 "fastifydb"라는 데이터베이스를 만들었다는 것을 의미한다
    다음:
    \dt
    
    너는 반드시 이런 정보를 얻어야 한다.
    아무 관계도 발견되지 않았다"고 덧붙였다.

    이것은 우리가 이미 환경 변수를 사용하여 데이터베이스를 만들었지만, 아직 어떤 표나 관계도 만들지 않았기 때문이다
    이 터미널을 종료하려면 "exit"를 입력하십시오
    exit
    
    너는 또 종착역에 도착했다
    우리 이미지를 세울 때가 됐어!
    docker에서 작성한 폴더에서yml 파일을 찾은 후 실행
    docker-compose build
    

    이제 저희 노드 프로그램을 실행할 때가 됐어요.
    docker-compose up -d fastify_backend
    
    "docker ps-a"명령을 사용하여 이 두 용기가 모두 실행 중인지 확인할 수 있습니다

    데이터베이스에 단점을 추가합시다.(이것은 다른 더 좋은 방식으로 실현할 수 있다!)
    길에서요.js 파일은 users 테이블을 만들기 위해 간단한 단점을 추가합니다.
    // INIT TABLE. Launch just once to create the table
      fastify.get('/initDB', (req, reply) => {
        fastify.pg.connect(onConnect);
        function onConnect(err, client, release) {
          if (err) return reply.send(err);
          client.query(
            'CREATE TABLE IF NOT EXISTS "users" ("id" SERIAL PRIMARY KEY,"name" varchar(30),"description" varchar(30),"tweets" integer);',
            function onResult(err, result) {
              release();
              reply.send(err || result);
            }
          );
        }
      });
    

    API 끝점 추가


    5개의 추가 끝점을 추가합니다.

    모든 사용자의 끝점을 가져오려면 다음과 같이 하십시오.


      //GET AL USERS
      fastify.route({
        method: 'GET',
        url: '/users',
        handler: async function (request, reply) {
          fastify.pg.connect(onConnect);
          function onConnect(err, client, release) {
            if (err) return reply.send(err);
            client.query('SELECT * from users', function onResult(err, result) {
              release();
              reply.send(err || result.rows);
            });
          }
        },
      });
    
    

    엔드포인트에서 사용자 가져오기


      //GET ONE USER if exists
      fastify.route({
        method: 'GET',
        url: '/users/:id',
        handler: async function (request, reply) {
          fastify.pg.connect(onConnect);
          function onConnect(err, client, release) {
            if (err) return reply.send(err);
            client.query(`SELECT * from users where id=${request.params.id}`, function onResult(err, result) {
              release();
              reply.send(err || result.rows[0]);
            });
          }
        },
      });
    

    끝점에서 사용자 만들기


      //UPDATE ONE USER fields
      fastify.route({
        method: 'PUT',
        url: '/users/:id',
        handler: async function (request, reply) {
          fastify.pg.connect(onConnect);
          async function onConnect(err, client, release) {
            if (err) return reply.send(err);
            const oldUserReq = await client.query(`SELECT * from users where id=${request.params.id}`);
            const oldUser = oldUserReq.rows[0];
            client.query(
              `UPDATE users SET(name,description,tweets) = ('${request.body.name}', '${request.body.description || oldUser.description}', ${
                request.body.tweets || oldUser.tweets
              })
          WHERE id=${request.params.id}`,
              function onResult(err, result) {
                release();
                reply.send(err || `Updated: ${request.params.id}`);
              }
            );
          }
        },
      });
    

    사용자의 끝점을 삭제하려면 다음과 같이 하십시오.


      //DELETE ONE USER if exists
      fastify.route({
        method: 'DELETE',
        url: '/users/:id',
        handler: async function (request, reply) {
          fastify.pg.connect(onConnect);
          function onConnect(err, client, release) {
            if (err) return reply.send(err);
            client.query(`DELETE FROM users WHERE id=${request.params.id}`, function onResult(err, result) {
              release();
              reply.send(err || `Deleted: ${request.params.id}`);
            });
          }
        },
      });
    
    최후의 노선.js 파일은 다음과 같습니다.
    async function routes(fastify, options) {
      // Testing route
      fastify.get('/', async (request, reply) => {
        return { hello: 'world' };
      });
    
      // INIT TABLE. Launch just once to create the table
      fastify.get('/initDB', (req, reply) => {
        fastify.pg.connect(onConnect);
        function onConnect(err, client, release) {
          if (err) return reply.send(err);
          client.query(
            'CREATE TABLE IF NOT EXISTS "users" ("id" SERIAL PRIMARY KEY,"name" varchar(30),"description" varchar(30),"tweets" integer);',
            function onResult(err, result) {
              release();
              reply.send(err || result);
            }
          );
        }
      });
    
      //GET AL USERS
      fastify.route({
        method: 'GET',
        url: '/users',
        handler: async function (request, reply) {
          fastify.pg.connect(onConnect);
          function onConnect(err, client, release) {
            if (err) return reply.send(err);
            client.query('SELECT * from users', function onResult(err, result) {
              release();
              reply.send(err || result.rows);
            });
          }
        },
      });
    
      //GET ONE USER if exists
      fastify.route({
        method: 'GET',
        url: '/users/:id',
        handler: async function (request, reply) {
          fastify.pg.connect(onConnect);
          function onConnect(err, client, release) {
            if (err) return reply.send(err);
            client.query(`SELECT * from users where id=${request.params.id}`, function onResult(err, result) {
              release();
              reply.send(err || result.rows[0]);
            });
          }
        },
      });
    
      //Create users
      fastify.route({
        method: 'POST',
        url: '/users',
        handler: function (request, reply) {
          fastify.pg.connect(onConnect);
          function onConnect(err, client, release) {
            if (err) return reply.send(err);
            const newUser = request.body;
            client.query(
              `INSERT into users (name,description,tweets) VALUES('${newUser.name}','${newUser.description}',${newUser.tweets})`,
              function onResult(err, result) {
                release();
                reply.send(err || result);
              }
            );
          }
        },
      });
    
      //UPDATE ONE USER fields
      fastify.route({
        method: 'PUT',
        url: '/users/:id',
        handler: async function (request, reply) {
          fastify.pg.connect(onConnect);
          async function onConnect(err, client, release) {
            if (err) return reply.send(err);
            const oldUserReq = await client.query(`SELECT * from users where id=${request.params.id}`);
            const oldUser = oldUserReq.rows[0];
            client.query(
              `UPDATE users SET(name,description,tweets) = ('${request.body.name}', '${request.body.description || oldUser.description}', ${
                request.body.tweets || oldUser.tweets
              })
          WHERE id=${request.params.id}`,
              function onResult(err, result) {
                release();
                reply.send(err || `Updated: ${request.params.id}`);
              }
            );
          }
        },
      });
    
      //DELETE ONE USER if exists
      fastify.route({
        method: 'DELETE',
        url: '/users/:id',
        handler: async function (request, reply) {
          fastify.pg.connect(onConnect);
          function onConnect(err, client, release) {
            if (err) return reply.send(err);
            client.query(`DELETE FROM users WHERE id=${request.params.id}`, function onResult(err, result) {
              release();
              reply.send(err || `Deleted: ${request.params.id}`);
            });
          }
        },
      });
    }
    
    module.exports = routes;
    
    이제 이 API를 테스트해 보겠습니다!

    우체부


    중요!URL의 첫 번째 부분에 127.0.0.1이 아니라localhost를 지정해야 합니다. 그렇지 않으면 작동하지 않습니다.

    우리는 우체부를 사용할 것이지만, 너는 언제든지 도구를 사용할 수 있다
    우선, 우리는 사용자 테이블을 만들어야 한다.GET this URL을 클릭하여 트리거합니다.
    GET http://localhost:3000/initDB
    

    만약 우리가 이 답을 얻게 된다면, 이것은 우리의 '사용자' 표가 이미 만들어졌다는 것을 의미한다.
    이제 다른 GET를 사용하여 모든 사용자를 검사합니다.
    GET http://localhost:3000/users
    

    만약 우리가 얻은 것이 공수조 답안[]이라면 이것은 우리가 실제로 데이터베이스에users표가 있지만 사용자가 없다는 것을 의미한다.이거 너무 좋아요!
    사용자를 만듭니다.우리는 같은 단점에서 POST 요청을 보내서 json에 값을 추가함으로써 이 점을 실현할 것이다
    예:
    {
        "name":"Adrian",
        "description":"Kangaroo Fighter",
        "tweets":12000
    }
    

    새 사용자마다 자동으로 증가하기 때문에 "id"를 추가할 필요가 없습니다.
    하나 더 해달래요.

    그리고 하나

    이제 모든 사용자를 다시 한 번 살펴보겠습니다.

    저희가 이번에 봤는데 세 명의 사용자가 있어요!
    우리는 이전 URL 경로의 끝에 사용자 id를 추가해서 사용자를 얻을 수 있습니다.예컨대
    GET http://localhost:3000/users/2
    
    ID 2의 사용자 가져오기

    사용자를 삭제하려면 사용자를 가져오는 데 사용되는 동일한 끝점에서 삭제 요청을 보낼 수 있습니다.
    DELETE http://localhost:3000/users/2
    

    마지막으로 사용자를 업데이트하려면 json에서 새 값을 전달하기 위해 PUT 요청을 보내야 한다. 아래와 같다.
    {
        "name":"Adrian2",
        "description":"SuperKANGAROO"
    }
    
    url 요청에서 업데이트할 사용자 id를 전달해야 합니다. 아래와 같습니다.
    PUT http://localhost:3000/users/3
    

    사용자가 실제로 업데이트되었는지 확인하려면 다른 GET 요청을 실행할 수 있습니다.

    보시다시피 사용자의 이름과 설명은 바뀌었지만 트윗은 바뀌지 않았습니다.

    결론


    만약 당신이 본문을 읽어 본 적이 있다면, 나는 당신이 어떤 문제에 부딪혔는지 알고 싶습니다.감사합니다!
    GitHub 저장소:
    https://github.com/FrancescoXX/study-with-me-fastify-docker

    좋은 웹페이지 즐겨찾기