Comment créer un environnement [TypeScript + Vue + Express + MySQL] avec Docker ~ Sequelize ~

Contenu

Cette fois, nous utiliserons Sequelize, qui est l'ORM de Node.js, pour accéder à MySQL depuis le serveur Express, acquérir des données et répondre.

Puisque la création du serveur Express et de l'API simple a été complétée par l'article précédent, cette fois je me concentrerai sur l'introduction de Sequelize et la création de Model.

Contenu jusqu'à la dernière fois

Comment créer un environnement pour [TypeScript + Vue + Express + MySQL] avec Docker ~ Vue Edition ~ Comment créer un environnement de [TypeScript + Vue + Express + MySQL] avec Docker ~ MySQL edition ~ Comment créer un environnement de [TypeScript + Vue + Express + MySQL] avec Docker ~ Express ~

Procédure de travail

  1. Configurer un réseau entre les conteneurs
  2. Introduction de Sequelize
  3. Création de modèles
  4. Complétez l'API GetTests
  5. Appelez l'API avec Axios depuis l'avant
  6. Liez et restituer la réponse à Vuex

1. Configurer un réseau entre les conteneurs

docker-compose.yml

version: "3"
services:
  app:
    container_name: app_container
    build: ./docker/app
    ports:
      - 8080:8080
    volumes:
      - ./app:/app
    stdin_open: true
    tty: true
    environment:
      TZ: Asia/Tokyo
    command: yarn serve
    networks:                          #Ajouter un réseau
      - default

  api:
    container_name: api_container
    build: ./docker/api
    ports:
      - 3000:3000
    volumes:
      - ./api:/api
    tty: true
    environment:
      CHOKIDAR_USEPOLLING: 1
      TZ: Asia/Tokyo
    depends_on:
      - db
    command: yarn nodemon
    networks:                          #Ajouter un réseau
      - default

  db:
    container_name: db_container
    build: ./docker/db
    image: mysql:5.7
    ports:
      - 3306:3306
    volumes:
      - ./db/conf/my.cnf:/etc/mysql/conf.d/mysql.cnf
      - ./db/init_db:/docker-entrypoint-initdb.d
      - test_data:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - TZ="Asia/Tokyo"
    networks:                          #Ajouter un réseau
      - default

networks:                              #Ajouter un réseau
  default:

volumes:
  test_data:

En se connectant à un réseau commun, il est possible de communiquer entre chaque composant.

Démarrage du conteneur

$ docker-compose up -d

2. Introduction de Sequelize

De là, nous allons introduire Sequelize, qui est un ORM pour Node.js (qui acquiert et manipule les données d'une base de données relationnelle), et acquiert des données de la base de données.

Conteneur d'accès

$ docker exec -it api_container sh

Installez les bibliothèques requises

$ yarn add [email protected] sequelize-typescript reflect-metadata mysql2 log4js cors
$ yarn add --dev dotenv @types/validator @types/bluebird @types/cors @types/dotenv

* Une erreur peut survenir selon la version de sequelize, vous devez donc vérifier la version au moment de l'installation! </ font>

api/index.ts

import cors from 'cors' //ajouter à
import express from 'express'
import router from './routes/index'

const app = express()
const port = 3000

app.use(cors()) //ajouter à

app.use('/api', router)

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

3. Création de modèles

api/models/settings/.env

MYSQL_DATABASE=test_db
MYSQL_USER={Ce qui a été défini lors de la création du conteneur MySQL}
MYSQL_PASSWORD={Ce qui a été défini lors de la création du conteneur MySQL}
MYSQL_ROOT_PASSWORD={Ce qui a été défini lors de la création du conteneur MySQL}

Il s'agit du même paramètre que .env dans le répertoire racine.

api/models/settings/db_setting.ts

import dotenv from 'dotenv'

dotenv.config({ path: __dirname + '/.env' })

interface DatabaseTypes {
  database: string | undefined
  user: string | undefined
  password: string | undefined
}

export const dbSetting: DatabaseTypes = {
  database: process.env.MYSQL_DATABASE,
  user: process.env.MYSQL_USER,
  password: process.env.MYSQL_PASSWORD,
}

Définissez le mot de passe et la table pour Sequelize.

api/models/test.ts

import {
  Table,
  Model,
  Column,
  DataType,
  PrimaryKey,
  AutoIncrement,
} from 'sequelize-typescript'

@Table({
  modelName: 'test',
  tableName: 'test',
})
export class Test extends Model<Test> {
  @PrimaryKey
  @AutoIncrement
  @Column(DataType.INTEGER)
  readonly id!: number

  @Column(DataType.STRING)
  name!: string

  @Column(DataType.STRING)
  description!: string
}

Créez un modèle pour la table de test. Décrit sur une base de décorateur.

J'obtiens une erreur TypeScript, j'ai donc ajouté une règle.

api/tsconfig.json

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "include": ["./**/*"]
}

Modifier les paramètres tsconfig ci-dessus

api/models/index.ts

import log4js from 'log4js'
import { Sequelize } from 'sequelize-typescript'
import { dbSetting } from './settings/db_setting'
import { Test } from './test'

const logger = log4js.getLogger('mysql')

export default new Sequelize({
  dialect: 'mysql',
  timezone: '+09:00',
  port: 3306,
  host: 'db',
  username: dbSetting['user'],
  password: dbSetting['password'],
  database: dbSetting['database'],
  logging: (sql: string) => {
    logger.info(sql)
  },
  define: { timestamps: false, underscored: true },
  pool: { max: 5, min: 0, idle: 10000, acquire: 30000 },
  models: [Test],
})

export { Test }

C'est le cœur de cette époque. Si vous obtenez une erreur, elle devrait être ici. Si la version de la bibliothèque est différente ou si les paramètres tsconfig ne sont pas corrects, une erreur se produira ici.

4. Complétez l'API GetTests

api/routes/tests/get_tests.ts

import { Request, Response } from 'express'
import { Handler } from '../../core/handler'
import { NO_DATA_EXISTS } from '../../constants/error'
import { Test } from '../../models/index'

export class GetTests {
  handler: Handler

  constructor(req: Request, res: Response) {
    this.handler = new Handler(req, res)
  }

  /**
   *Traitement principal
   */
  async main() {
    const data = await this.getTests()

    if (!data) {
      return this.handler.error(NO_DATA_EXISTS)
    }

    return this.handler.json(data)
  }

  /**
   *Obtenez toutes les données de test
   */
  getTests() {
    return Test.findAll({
      attributes: ['id', 'name', 'description'],
    })
  }
}

En tant que flux de traitement

  1. La fonction principale est instanciée et appelée
  2. La fonction getTests est appelée dans la fonction principale
  3. Obtenez des données de la table de test en exécutant la fonction findAll (obtenir toutes les données) sur le modèle de test dans getTests
  4. Si la valeur de retour de la fonction getTests n'existe pas, une erreur est renvoyée et, si elle existe, les données sont renvoyées au format json.

Confirmation!

Accédez à localhost: 3000 / api / tests! スクリーンショット 2020-09-22 2.35.05.png Ce n'est pas grave si les données réelles sont renvoyées en JSON!

Créez une API pour en obtenir une à partir de l'ID spécifié

api/routes/tests/get_test_by_id.ts

import { Request, Response } from 'express'
import { Handler } from '../../core/handler'
import { PARAMETER_INVALID, NO_DATA_EXISTS } from '../../constants/error'
import { Test } from '../../models/index'

type Params = {
  test_id: number
}

export class GetTestById {
  handler: Handler
  params: Params

  constructor(req: Request, res: Response) {
    this.handler = new Handler(req, res)

    this.params = {
      test_id: Number(req.params.test_id),
    }
  }

  /**
   *Traitement principal
   */
  async main() {
    if (!this.params.test_id) {
      return this.handler.error(PARAMETER_INVALID)
    }

    const data = await this.getTest()

    if (!data) {
      return this.handler.error(NO_DATA_EXISTS)
    }

    return this.handler.json(data)
  }

  /**
   *Obtenez toutes les données de test
   */
  getTest() {
    return Test.findOne({
      attributes: ['id', 'name', 'description'],
      where: {
        id: this.params.test_id,
      },
    })
  }
}

Cette fois, dans la fonction findOne (obtenir une donnée correspondante), recherchez par la clause where pour obtenir les données avec l'ID correspondant.

testsController.ts

import { Router } from 'express'
import { GetTests } from '../tests/get_tests'
import { GetTestById } from '../tests/get_test_by_id' //ajouter à

const router = Router()

router.get('/', (req, res, next) => {
  new GetTests(req, res).main().catch(next)
})

router.get('/:test_id', (req, res, next) => {   //ajouter à
  new GetTestById(req, res).main().catch(next)  //ajouter à
})                                              //ajouter à

export default router

L'ID à rechercher est passé à la classe GetTestById en tant que requête de l'URL.

Confirmation!

Accédez à localhost: 3000 / api / tests / 1 スクリーンショット 2020-09-22 2.39.56.png

Si les données de / tests / ** {ID spécifié ici} ** sont renvoyées, c'est réussi! Veuillez vérifier avec d'autres identifiants à titre d'essai.

5. Appelez l'API avec Axios depuis l'avant

À ce stade, le côté serveur est terminé. À partir de là, nous allons définir les paramètres pour appeler l'API créée depuis l'avant.

Sortez du conteneur

$ exit

Accéder au conteneur d'applications

$ docker exec -it app_container sh

Présentation d'Axios

$ yarn add axios

app/src/utils/axios.ts

import axios from 'axios'

export const api = axios.create({
  baseURL: 'http://localhost:3000/api',
})

Définissez un module pour les contre-mesures cors et la conversion d'URL par défaut. Lors d'un appel, il est possible d'appeler avec api.get ou api.post.

app/src/store/modules/test.ts

import {
  getModule,
  Module,
  VuexModule,
  Mutation,
  Action,
} from 'vuex-module-decorators'
import store from '../index'
import { api } from '../../utils/axios'

type TestType = {
  id: number
  name: string
  description: string
}

type TestState = {
  apiTests: TestType[]
}

@Module({ store, dynamic: true, namespaced: true, name: 'Test' })
class TestModule extends VuexModule implements TestState {
  apiTests: TestType[] = []

  @Mutation
  SET_API_TESTS(payload: TestType[]) {
    this.apiTests = payload
  }
  @Action
  async getTests() {
    const response = await api.get('/tests')

    if (response.data.data) {
      this.SET_API_TESTS(response.data.data)
    }
  }
}

export const testModule = getModule(TestModule)

Créez un magasin de test Vuex et stockez les données obtenues en appelant l'API créée dans GetTests of Action dans l'état apiTests.

app/src/pages/Test.vue


<template>
  <div class="test">
    <v-data-table :headers="headers" :items="tests"> </v-data-table>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import { testModule } from '../store/modules/test'

@Component
export default class Test extends Vue {
  tests = []

  headers = [
    { text: 'ID', align: 'center', value: 'id' },
    { text: 'Nom', align: 'center', value: 'name' },
    { text: 'Détails', align: 'center', value: 'description' },
  ]

  async created() {
    await testModule.getTests()

    this.tests = testModule.apiTests
  }
}
</script>

Lorsque Vue est créée, exécutez l'action getTests dans le magasin de test pour obtenir les données et liez les données apiTests pour référencer les données dans Vue. Passez les données à la v-table-table de Vuetify et vous avez terminé.

Confirmation!

localhost:8080

スクリーンショット 2020-09-22 2.49.52.png

Jusqu'à présent, j'ai pu appeler l'API sur la face avant, obtenir les données de la base de données, stocker les données renvoyées dans Vuex et les rendre. Maintenant que vous avez une base, vous pouvez l'étendre en ajoutant des API et des pages de la même manière.

Maintenant que le modèle est terminé, je vais créer une application qui vous permettra d'effectuer des opérations CLUD simples la prochaine fois!

la prochaine fois

  • Créer séparément

référence

Comment créer un environnement pour [TypeScript + Vue + Express + MySQL] avec Docker ~ Vue Edition ~ Comment créer un environnement de [TypeScript + Vue + Express + MySQL] avec Docker ~ MySQL edition ~ Comment créer un environnement de [TypeScript + Vue + Express + MySQL] avec Docker ~ Express ~

Recommended Posts

Comment créer un environnement [TypeScript + Vue + Express + MySQL] avec Docker ~ Sequelize ~
Comment créer un environnement [TypeScript + Vue + Express + MySQL] avec Docker ~ Express ~
Comment créer un environnement [TypeScript + Vue + Express + MySQL] avec Docker ~ MySQL ~
Comment créer un environnement [TypeScript + Vue + Express + MySQL] avec Docker ~ Vue ~
Comment créer un environnement Rails + Vue + MySQL avec Docker [dernière version 2020/09]
Comment créer un environnement Rails 6 avec Docker
[Rails] Comment créer un environnement avec Docker
[Road_node.js_1-1] La voie de la création de l'environnement Node.js Express MySQL à l'aide de Docker
Comment créer un environnement Docker avec Gradle pour IntelliJ
Comment créer un environnement de développement Ruby on Rails avec Docker (Rails 6.x)
Comment créer un environnement de développement Ruby on Rails avec Docker (Rails 5.x)
[Environnement Docker] Comment gérer ActiveSupport :: MessageEncryptor :: InvalidMessage
Environnement Build Rails (API) x MySQL x Nuxt.js avec Docker
[Rails] [Docker] Le copier-coller est OK! Comment créer un environnement de développement Rails avec Docker
Comment quitter Docker pour Mac et créer un environnement de développement Docker avec Ubuntu + Vagrant
Créez un environnement Vue3 avec Docker!
Créer un environnement local Couchbase avec Docker
Créer un environnement Node.js avec Docker
[Construction de l'environnement avec Docker] Rails 6 et MySQL 8
Mettre à jour MySQL de 5.7 à 8.0 avec Docker
Créez un environnement Docker + Laravel avec Laradock
Comment créer CloudStack à l'aide de Docker
Comment démarrer Camunda avec Docker
J'ai essayé de créer un environnement de serveur UML Plant avec Docker
Comment installer Pry après avoir créé un environnement de développement Rails avec Docker
Créer un environnement de développement pour Django + MySQL + nginx avec Docker Compose
Comment partager des fichiers avec Docker Toolbox
Créer un environnement de développement PureScript avec Docker
Construire un environnement Rails 6 + MySQL avec Docker compose
Déployer sur heroku avec Docker (Rails 6, MySQL)
Modifier Mysql avec des commandes dans l'environnement Docker
[Docker] Créez un environnement Node.js + express + webpack avec Docker
Construire un environnement pour Laravel + MySQL + phpMyadmin avec Docker
Créer un environnement de développement Wordpress avec Docker
Créer un environnement Nuxt TypeScript + Vuetify avec docker-compose
[Docker] Construisez l'environnement d'exécution de Jupyter Lab avec Docker
Créer un environnement avec Docker sur AWS
Créer un environnement de vérification des opérations TensorFlow avec Docker
Comment exécuter Blazor (C #) avec Docker
Comment exécuter avec des commandes de langage de développement normales dans l'environnement de développement Docker
01. J'ai essayé de créer un environnement avec SpringBoot + IntelliJ + MySQL (MyBatis) (Windows 10)
Quand j'ai essayé de créer un environnement pour PHP7.4 + Apache + MySQL avec Docker, je suis resté bloqué [Windows & Mac]
Comment lier Rails6 Vue (à partir de la construction de l'environnement)
Créer un environnement Laravel / Docker avec VSCode devcontainer
Comment donner votre image à quelqu'un avec Docker
Essayez de créer Express + PostgreSQL + Sequelize avec Docker [Partie 1]