Nous allons créer un conteneur de serveur API Express sur Docker et créer un environnement qui renvoie une réponse simple.
Jusqu'à l'article précédent, nous avons créé un conteneur d'application / conteneur de base de données, mais cette fois, nous allons créer un conteneur de serveur API qui les connecte et transmet en fait les données au front.
Puisque le côté serveur a beaucoup de volume, les articles sur la construction de base d'Express et l'introduction de Sequelize sont séparés.
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 ~
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
#Ajouter à partir d'ici
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
#Ajouter ici
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"
volumes:
test_data:
docker/api/Dockerfile
FROM node:12.13-alpine
ENV NODE_PATH /usr/local/lib/node_modules
WORKDIR /api
$ docker-compose up -d
$ docker ps
OK si api_container est démarré!
$ docker exec -it api_container sh
$ yarn init
$ yarn add --dev typescript ts-node prettier @types/node
.prettierrc
{
"singleQuote": true,
"semi": false
}
tsconfig init
$ ./node_modules/.bin/tsc --init
Puisque tsconfig.json est généré, nous allons créer une application basée sur cela.
tsconfig.json
"include": ["./**/*"] //Ajouter à la fin
package.json
"scripts": {
"ts-node": "ts-node index.ts"
},
Définissez le script afin que le fichier TypeScript puisse être exécuté sur ts-node.
api/index.ts
const message: string = 'tester'
console.log(message)
Créez un fichier principal pour exécuter TypeScript. Entrez un mannequin pour vérifier si ts-node fonctionne correctement.
tester
$ yarn ts-node
Si TypeScript est compilé et que le message ci-dessus est affiché, c'est OK!
Nous allons introduire une bibliothèque qui se construira automatiquement en cas de modification du fichier.
$ yarn add --dev nodemon
nodemon.json
{
"watch": ["api/**/*"],
"ext": "ts",
"exec": "ts-node ./index.ts"
}
Créez un fichier de configuration nodemon. Exécutez ts-node via nodemon et définissez tout directement sous le répertoire api à surveiller.
package.json
"scripts": {
"tsc": "tsc",
"ts-node": "ts-node index.ts",
"nodemon": "nodemon"
},
docker-compose.yml
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 #Ajouter ce gars
Ajoutez une commande pour démarrer automatiquement via nodemon au démarrage du conteneur.
Ceci termine l'exécution de TypeScript et les paramètres de construction automatique lors de la modification. À partir de là, nous allons créer Express, qui sera le véritable serveur d'API.
$ yarn add express
$ yarn add --dev @types/express
api/index.ts
import express from 'express'
const app = express()
const port = 3000
app.get('/', (req, res) => res.send('Test Express!'))
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
$ exit //Sortez du conteneur
$ docker-compose stop //Arrêtez le conteneur
$ docker-compose up -d //Redémarrage du conteneur
Si vous accédez à localhost: 3000 et que "Test Express!" S'affiche, la réponse est renvoyée sans aucun problème! Juste au cas où, modifiez un autre message dans "Test Express!" Dans index.ts et vérifiez si le message change lorsque vous accédez à nouveau à localhost: 3000. S'il change automatiquement, nodemon fonctionne correctement et la construction automatique est effectuée!
Actuellement, il n'est accessible qu'avec localhost: 3000, mais je souhaite appeler l'API en fonction de l'URL comme indiqué ci-dessous, je vais donc définir le routage.
Exemple)
api/routes/index.ts
import Express from 'express'
const router = Express.Router()
export default router
api/routes/tests/testsController.ts
import { Router } from 'express'
const router = Router()
export default router
C'est la fin du prétraitement, et nous allons en fait spécifier le routage. Cette fois, elle est modifiée pour être accessible avec "localhost: 3000 / api / tests"
api/routes/index.ts
import Express from 'express'
const router = Express.Router()
router.get('/', (req, res, next) => {
res.send('tester')
})
export default router
api/index.ts
import express from 'express'
import router from './routes/index'
const app = express()
const port = 3000
app.use('/api', router)
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
[App.use ('/ api', router)] défini ci-dessus Avec ce paramètre, lorsque localhost: 3000 / api est passé, il passera au routage de routes / index.ts. Vérifions en fait l'opération.
Accès avec localhost: 3000 / api Si ** test ** est affiché, c'est OK!
Dans une application réelle, il est nécessaire de brancher le point de terminaison lors de l'accès à plusieurs bases de données, définissez donc le routage pour qu'il se branche comme indiqué ci-dessous.
localhost: 3000 / api / ** {branche selon cette valeur} **
api/routes/tests/testsController.ts
import { Router } from 'express'
const router = Router()
router.get('/', (req, res, next) => {
res.send('Acheminement terminé!')
})
export default router
api/routes/index.ts
import Express from 'express'
import tests from './tests/testsController'
const router = Express.Router()
router.use('/tests', tests)
export default router
Accéder à localhost: 3000 / api / tests Si "Routage terminé!" S'affiche, c'est OK!
Ceci termine les paramètres de routage!
Ensuite, créez un gestionnaire qui bascule entre un modèle qui renvoie une réponse normale et une réponse lorsqu'une erreur se produit.
api/constants/error.ts
export type ErrorCode = {
status: number
type: string
message: string
}
/**
*Erreur si les paramètres sont incorrects
*/
export const PARAMETER_INVALID: ErrorCode = {
status: 400,
type: 'PARAMETER_INVALID',
message: 'The parameter is invalid.',
}
/**
*Erreur lorsque les données n'existent pas
*/
export const NO_DATA_EXISTS: ErrorCode = {
status: 400,
type: 'NO_DATA_EXISTS',
message: 'No data exists.',
}
Lorsque le nombre de modèles d'erreur augmente, nous augmenterons le code d'erreur ici.
api/core/handler.ts
import { Request, Response } from 'express'
import { ErrorCode } from '../constants/error'
/**
*Fonction pour gérer l'API
*/
export class Handler {
constructor(private req: Request, private res: Response) {}
/**
*Envoyer des données
*/
json<T>(data: T): void {
this.res.json({ data: data })
}
/**
*Envoyer une erreur
*/
error(error: ErrorCode): void {
this.res.status(error.status).send({ error: error })
}
}
Lorsqu'une erreur se produit dans l'API, elle se branche sur une sortie d'erreur, et si c'est normal, elle retourne au format json.
Créez un modèle d'API qui récupère toutes les données de la table de tests lors de l'accès à localhost: 3000 / api / test.
api/routes/tests/get_tests.ts
import { Request, Response } from 'express'
import { Handler } from '../../core/handler'
export class GetTests {
handler: Handler
constructor(req: Request, res: Response) {
this.handler = new Handler(req, res)
}
/**
*Traitement principal
*/
async main() {
const data = this.getTests()
return this.handler.json(data)
}
/**
*Renvoie un message
*/
getTests() {
const message = 'get_tests exécutés'
return message
}
}
C'est l'API qui s'appelle en fait
api/routes/tests/testsController.ts
import { Router } from 'express'
import { GetTests } from '../tests/get_tests' //Importez l'API ci-dessus
const router = Router()
router.get('/', (req, res, next) => {
new GetTests(req, res).main().catch(next) //Changement
})
export default router
localhost:3000/api/tests
Ce n'est pas grave s'il retourne au format JSON comme ça!
Je vous remercie pour votre travail acharné! À ce stade, vous disposez d'un conteneur d'application, d'un conteneur de base de données et d'un conteneur de serveur API. À partir de la prochaine fois, je connecterai chaque conteneur et passerai les données de la base de données au premier plan et les dessinerai!
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 ~ Comment créer un environnement de [TypeScript + Vue + Express + MySQL] avec Docker ~ Sequelize ~
Recommended Posts