我有一個 NestJS 應用程序,我想要對其進行 dockerize。我是docker的新手,我必須這麼做。在我的 NestJS 應用程式中,我使用帶有 Typeorm 的 mysql 資料庫。這個 mysql 本身來自 docker 映像,也就是我的電腦上沒有安裝 mysql。
我有這個 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:
我可以運行 docker-compose up -d 並使用我電腦上的資料庫。現在,我還有一個正在嘗試編寫的 Dockerfle。
在過去 5 個小時左右的時間裡我改變了很多事情,但總的來說,它是這樣的:
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"]
我在上面的Docekerfile中嘗試做的是在主機上建立一個ubuntu映像並分別安裝curl、node和mysql,以便該應用程式可以與mysql一起使用。 我可以透過 docker build -t my-app 建立此映像。
然後,我執行 image docker run my-app 並收到以下錯誤:
[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)
我不知道如何處理這個問題。
作為參考,這是我的 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(); } }
這個錯誤是怎麼回事?我要怎麼解決這個問題?感謝所有幫助。
乾杯
編輯:現在我想我已經對這個問題有了更多的了解,所以我正在嘗試編寫一個 docker-compose-yml 文件,該文件將同時啟動我的 NestJS 應用程式和 mysql 映像。首先,我將 dockerfile 更改為 =>
# 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" ]
然後寫了這個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
現在,當我在 bash 上執行 sudo docker-compose up 時(如果沒有 sudo,它會給出權限被拒絕的錯誤),我收到以下錯誤
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)
據我所知,它無法連接到資料庫。我究竟做錯了什麼?我該如何解決這個問題?
編輯2:根據評論,我做了更多修改。這些是我的發現:
DB_HOST 值似乎並不重要。
# 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:
我可以將此值更改為我想要的任何值,並且該腳本將在我的本機電腦上運行。
這又是我的 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(); } }
當我嘗試對這個應用程式進行 dockerize 以便它可以在僅安裝了 Docker 的電腦上運行時,我嘗試更改 docker-compose.yml 文件,例如 =>
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
這會導致兩個不同的行為:我無法再執行 docker-compose up,它給出以下錯誤 =>
=> [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
我使用的是Fish 終端,因此出於某種原因,我需要更改為bash 來運行sudo docker-compose up,這又會給出以下錯誤,表明連接到資料庫時出現問題=>
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
我真的被困住了。
P粉5417963222024-04-01 12:22:14
透過更改 docker-compose.yml 檔案解決了所有問題,如下所示 =>
version: '3.8' services: app: image: my-app build: . volumes: - .:/app command: npm run start:dev restart: always ports: - '3000:3000' environment: - DB_HOST=mysql - 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
這是我的 Dockerfile =>
# 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:dev" ]