J'ai une application NestJS que je souhaite dockeriser. Je suis nouveau sur Docker et je dois le faire. Dans mon application NestJS, j'utilise la base de données MySQL avec Typeorm. Ce mysql lui-même provient de l'image docker, c'est-à-dire que mysql n'est pas installé sur mon ordinateur.
J'ai ce fichier docker-compose.yml :
# docker-compose.yml version: '3.3' services: mysql: image: mysql:latest restart: always environment: - MYSQL_USER=myuser - MYSQL_PASSWORD=mypassword - MYSQL_DATABASE=db - MYSQL_ROOT_USER=myuser - MYSQL_ROOT_PASSWORD=root volumes: - mysql:/var/lib/mysql ports: - '3306:3306' volumes: mysql:
Je peux exécuter docker-compose up -d et utiliser la base de données sur mon ordinateur. En ce moment, j'ai aussi un Dockerfle que j'essaie d'écrire.
J'ai changé beaucoup de choses au cours des 5 dernières heures environ, mais en résumé, ça donne ceci :
FROM ubuntu:18.04 # Set the working directory to /usr/src/app WORKDIR /usr/src/app # Copy the package.json and package-lock.json files into the container COPY package*.json ./ RUN apt-get update RUN apt-get -y install curl RUN curl -sL https://deb.nodesource.com/setup_16.x | bash RUN apt install -y nodejs # Install the app dependencies RUN npm install # Copy the rest of the app files into the container COPY . . # Set environment variables for the MySQL connection ENV MYSQL_HOST=mysql ENV MYSQL_USER=myuser ENV MYSQL_PASSWORD=mypassword ENV MYSQL_DATABASE=db # Install the MySQL server RUN apt-get update -qq && apt-get install -y mysql-server # Expose the app's port EXPOSE 3000 # Start the app in development mode CMD ["npm", "run", "start:dev"]
Ce que j'essaie de faire dans le Docekerfile ci-dessus est de créer une image Ubuntu sur la machine hôte et d'installer respectivement curl, node et mysql afin que l'application puisse être utilisée avec mysql. Je peux créer cette image via docker build -t my-app.
Ensuite, j'ai exécuté image docker run my-app et j'ai obtenu l'erreur suivante :
[Nest] 29 - 04/02/2023, 7:37:26 PM ERROR [TypeOrmModule] Unable to connect to the database. Retrying (1)... Error: connect ECONNREFUSED 127.0.0.1:3306 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1494:16)
Je ne sais pas comment gérer ce problème.
Pour référence, voici mon fichier app.module.ts
import { Module, OnModuleInit } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UsersModule } from './users/users.module'; import { ArtworksModule } from './artworks/artworks.module'; import { User } from './users/entities/user.entity'; import { Artwork } from './artworks/entities/artwork.entity'; import { AuthModule } from './auth/auth.module'; import { ConfigModule } from '@nestjs/config'; import { SeedService } from './users/seedService/seedService'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3306, username: 'myuser', password: 'mypassword', database: 'db', entities: [User, Artwork], synchronize: false, autoLoadEntities: true, logging: true, }), ConfigModule.forRoot({ isGlobal: true, }), UsersModule, ArtworksModule, AuthModule, ], controllers: [AppController], providers: [AppService, SeedService], }) export class AppModule implements OnModuleInit { constructor(private seedService: SeedService) {} async onModuleInit() { await this.seedService.seedUsers(); } }
Que se passe-t-il avec cette erreur ? Comment puis-je résoudre ce problème? Merci pour votre aide.
Bravo
EDIT : Maintenant, je pense avoir un peu plus de compréhension du problème, j'essaie donc d'écrire un fichier docker-compose-yml qui lancera à la fois mon application NestJS et mon image mysql. J'ai d'abord changé le fichier docker en =>
# Use the official Node.js 14 image as the base image FROM node:14 # Create a working directory for the app WORKDIR /app # Copy the package.json and package-lock.json files into the container COPY package*.json ./ # Install app dependencies RUN npm install # Copy the rest of the app code into the container COPY . . # Expose port 3000 (the port that the app listens on) EXPOSE 3000 # Specify the command to run when the container starts CMD [ "npm", "run", "start:prod" ]
Puis j'ai écrit ce fichier docker-compose.yml =>
services: app: build: . command: npm run start:prod restart: always ports: - '3000:3000' environment: - DB_HOST=mysql - DB_PORT=3306 - DB_USER=myuser - DB_PASSWORD=mypassword - DB_NAME=db depends_on: - mysql mysql: image: mysql:latest restart: always environment: - MYSQL_USER=myuser - MYSQL_PASSWORD=mypassword - MYSQL_DATABASE=db - MYSQL_ROOT_USER=myuser - MYSQL_ROOT_PASSWORD=root volumes: - mysql:/var/lib/mysql volumes: mysql: networks: default: driver: bridge
Maintenant, lorsque j'exécute sudo docker-compose up sur bash (sans sudo, cela donne une erreur d'autorisation refusée), j'obtiens l'erreur suivante
my-app-1 | [Nest] 19 - 04/03/2023, 8:28:03 AM ERROR [TypeOrmModule] Unable to connect to the database. Retrying (1)... my-app-1 | Error: connect ECONNREFUSED 127.0.0.1:3306 my-app-1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) my-app-1 | [Nest] 19 - 04/03/2023, 8:28:06 AM ERROR [TypeOrmModule] Unable to connect to the database. Retrying (2)... my-app-1 | Error: connect ECONNREFUSED 127.0.0.1:3306 my-app-1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16)
Pour autant que je sache, il ne peut pas se connecter à la base de données. Qu'ai-je fait de mal? Comment puis-je résoudre ce problème?
Edit 2 : Sur la base des commentaires, j'ai apporté quelques modifications supplémentaires. Voici mes découvertes :
La valeur DB_HOST ne semble pas avoir d'importance.
# docker-compose.yml version: '3.3' services: mysql: image: mysql:latest restart: always environment: - DB_HOST=localhost - MYSQL_ROOT_USER=myuser - MYSQL_ROOT_PASSWORD=root volumes: - mysql:/var/lib/mysql ports: - '3306:3306' volumes: mysql:
Je peux modifier cette valeur comme je veux et le script s'exécutera sur ma machine locale.
Voici à nouveau mon fichier app.module.ts =>
import { Module, OnModuleInit } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { UsersModule } from './users/users.module'; import { ArtworksModule } from './artworks/artworks.module'; import { User } from './users/entities/user.entity'; import { Artwork } from './artworks/entities/artwork.entity'; import { AuthModule } from './auth/auth.module'; import { ConfigModule } from '@nestjs/config'; import { SeedService } from './users/seedService/seedService'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', host: process.env.DB_HOST, port: 3306, username: 'myuser', password: 'mypassword', database: 'db', entities: [User, Artwork], synchronize: false, autoLoadEntities: true, logging: true, }), ConfigModule.forRoot({ isGlobal: true, }), UsersModule, ArtworksModule, AuthModule, ], controllers: [AppController], providers: [AppService, SeedService], }) export class AppModule implements OnModuleInit { constructor(private seedService: SeedService) {} async onModuleInit() { await this.seedService.seedUsers(); } }
Lorsque j'essaie de dockeriser cette application pour qu'elle puisse s'exécuter sur une machine sur laquelle Docker est uniquement installé, j'essaie de modifier le fichier docker-compose.yml comme =>
version: '3.8' services: app: build: . command: npm run start:prod restart: always ports: - '3000:3000' environment: - DB_HOST=localhost - DB_PORT=3306 depends_on: - mysql mysql: image: mysql:latest restart: always environment: - MYSQL_ROOT_USER=myuser - MYSQL_ROOT_PASSWORD=root volumes: - mysql:/var/lib/mysql ports: - '3306:3306' volumes: mysql: networks: default: driver: bridge
Cela se traduit par deux comportements différents : je n'arrive plus à exécuter docker-compose up, cela donne l'erreur suivante =>
=> [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 32B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 34B 0.0s => [internal] load metadata for docker.io/library/node:14 1.4s => [1/5] FROM docker.io/library/node:14@sha256:a97048059988c65f974b37dfe25a44327069a0f4f81133624871de0063b98 0.0s => ERROR [internal] load build context 0.1s => => transferring context: 402.84kB 0.0s ------ > [internal] load build context: ------ failed to solve: error from sender: open /home/sirius/coding/my-app/mysql/#innodb_redo: permission denied
J'utilise le terminal Fish, donc pour une raison quelconque, je dois passer à bash pour exécuter sudo docker-compose up, ce qui à son tour donne l'erreur suivante indiquant un problème de connexion à la base de données =>
e dependencies initialized +0ms budapest-icf-recruitment-backend-app-1 | [Nest] 19 - 04/03/2023, 9:26:34 AM ERROR [TypeOrmModule] Unable to connect to the database. Retrying (1)... budapest-icf-recruitment-backend-app-1 | Error: connect ECONNREFUSED 127.0.0.1:3306 budapest-icf-recruitment-backend-app-1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) budapest-icf-recruitment-backend-app-1 | [Nest] 19 - 04/03/2023, 9:26:37 AM ERROR [TypeOrmModule] Unable to connect to the database. Retrying (2)... budapest-icf-recruitment-backend-app-1 | Error: connect ECONN
Je suis vraiment coincé.
Tous les problèmes ont été résolus en modifiant le fichier docker-compose.yml comme indiqué ci-dessous =>
Voici mon Dockerfile =>