mysqlnode.jsdockerdocker-composesequelize.js

How to run Sequelize migrations inside Docker


I'm trying to docerize my NodeJS API together with a MySQL image. Before the initial run, I want to run Sequelize migrations and seeds to have the tables up and ready to be served.

Here's my docker-compose.yaml:

version: '3.8'
services: 
  mysqldb:
    image: mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_USER: myuser
      MYSQL_ROOT_PASSWORD: mypassword
      MYSQL_DATABASE: mydb
    ports:
      - '3306:3306'
    networks:
      - app-connect
    volumes: 
      - db-config:/etc/mysql
      - db-data:/var/lib/mysql
      - ./db/backup/files/:/data_backup/data
  app:
    build:
      context: .
      dockerfile: ./Dockerfile
    image: node-mysql-app
    depends_on:
      - mysqldb
    ports:
      - '3030:3030'
    networks:
      - app-connect
    stdin_open: true
    tty: true
volumes: 
  db-config:
  db-data:
networks:
  app-connect:
      driver: bridge

Here's my app's Dockerfile:

FROM node:lts-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3030
ENV PORT 3030
ENV NODE_ENV docker
RUN npm run db:migrate:up
RUN npm run db:seeds:up
CMD [ "npm", "start" ]

And here's my default.db.json that the Sequelize migration uses (shortened):

{
  "development": {
    
  },
  "production": {
    
  },
  "docker": {
    "username": "myuser",
    "password": "mypassword",
    "database": "mydb",
    "host": "mysqldb",
    "port": "3306",
    "dialect": "mysql"
  }
}

Upon running compose up the DB installs well, the image deploys, but when it reaches the RUN npm run db:migrate:up (which translates into npx sequelize-cli db:migrate) I get the error:

npx: installed 81 in 13.108s

Sequelize CLI [Node: 14.17.0, CLI: 6.2.0, ORM: 6.6.2]

Loaded configuration file "default.db.json".
Using environment "docker".


ERROR: getaddrinfo EAI_AGAIN mysqldb
npm ERR! code ELIFECYCLE
npm ERR! errno 1

If I change the "host" in the default.db.json to "127.0.0.1", I get ERROR: connect ECONNREFUSED 127.0.0.1:3306 in place of the ERROR: getaddrinfo EAI_AGAIN mysqldb.

What am i doing wrong, and what host should I specify so the app can see the MySQL container? Should I remove the network? Should I change ports? (I tried combinations of both to no avail, so far).


Solution

  • I solved my issue by using Docker Compose Wait. Essentially, it adds a wait loop that samples the DB container, and only when it's up, runs migrations and seeds the DB.

    My next problem was: those seeds ran every time the container was run - I solved that by instead running a script that runs the seeds, and touchs a semaphore file. If the file exists already, it skips the seeds.