Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

building a docker with mysql and nodeJS

I am building an application that uses nodeJS and backend and mySQL as backend, and currently, my steps to bring up the app (without docker) is by:

  1. Install NodeJS
  2. Install MYSQL
  3. Launch mysqld on port 3306
  4. Manually create a MYSQL user dedicated for the NodeJS backend. This user should have only basic previliges to only my desired schema.
  5. Run sequelize commands to perform data migration and seeding using the user generated in 4)
  6. npm install and npm start to launch NodeJS on port 8080

Now I want to dokerize my application, and I already have the following Dockerfile:

#node version: carbon
#app version: 1.0.0

FROM node:8.11.2

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 8080

I have put a init.sql file within ./docker_db folder which does the following:

CREATE USER 'app_user'@'%' IDENTIFIED BY 'password';

CREATE SCHEMA `myapp` DEFAULT CHARACTER SET utf8;

GRANT INSERT, CREATE, ALTER, UPDATE, SELECT, REFERENCES on myapp.*
TO 'app_user'@'%' IDENTIFIED BY 'password'
WITH GRANT OPTION;

and the following docker-compose.yaml:

version: '3.6'

services:
    mysql1:
        image: mysql/mysql-server:5.7
        environment:
            MYSQL_ROOT_PASSWORD: password
        ports:
            - "127.0.0.1:3306:3306"
        volumes:
            -   type: bind
                source: ./docker_db
                target: /docker-entrypoint-initdb.d
        expose:
            - "3306"
        networks:
            - app-network
    myapp:
        build:
            context: .
            dockerfile: Dockerfile
        command: npm start
        depends_on:
            - mysql1
        ports:
            - "127.0.0.1:8080:8080"
        expose:
            - "8080"
        links:
            - mysql1
        networks:
            - app-network
        command: ["./wait-for-db.sh"]

networks:
    app-network:
        driver: bridge

where my ./wait-for-db.sh does the following:

#!/bin/bash
until mysql -h mysql1 -u app_user -p password -e 'select 1'; do 
        echo "still waiting for mysql"; sleep 1; done

exec node ./db/scripts/generateSequelizeCLIConfig.js
exec node_modules/sequelize-cli/bin/sequelize db:migrate
exec node_modules/sequelize-cli/bin/sequelize db:seed:all
exec npm start

(BTW I do want to expose 3306 to host machine so that I can use workbench to connect to the mysql server, which I have successfully connected.)

In my sequelize config file I do have:

"username": "app_user",
"password": "password",
"database": "myapp",
"host": "mysql1",
"port": "3306"

With the above setting, I executed docker-compose up, and then I got the following lines:

mysql1_1  | [Entrypoint] MySQL Docker Image 5.7.22-1.1.5
mysql1_1  | [Entrypoint] Initializing database
myapp_1     | standard_init_linux.go:190: exec user process caused "no such file or directory"
myapp_myapp_1 exited with code 1
mysql1_1  | [Entrypoint] Database initialized
mysql1_1  | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
mysql1_1  | Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.
mysql1_1  | Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.
mysql1_1  | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
mysql1_1  | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
mysql1_1  |
mysql1_1  | [Entrypoint] running /docker-entrypoint-initdb.d/init.sql
mysql1_1  |
mysql1_1  |
mysql1_1  | [Entrypoint] Server shut down
mysql1_1  |
mysql1_1  | [Entrypoint] MySQL init process done. Ready for start up.
mysql1_1  |
mysql1_1  | [Entrypoint] Starting MySQL 5.7.22-1.1.5

The problems now I face are:

1) The script's execution is hanging on the last line of Starting MySQL 5.7.22-1.1.5 and not going anywhere.

2) In the output, the 3rd and 4th lines shows an error about exec user process caused "no such file or directory". I don't think it is caused by the commands in the wait-for-db.sh because if I removed the lines after the until command, the problem still persist. In fact, I doubt the command execution ever reaching those lines and it feels like it is still within the until command.

I think it's really close to the final solution though :)

like image 340
jamesdeath123 Avatar asked May 29 '18 02:05

jamesdeath123


1 Answers

The problem is probably related to timing. Both containers will start at the same time and your node-app will try to connect to mysql almost immediately, while the MySQL server is still starting.

docker-compose doesn't have any kind of structure for this so you will have to build an entrypoint in your node-app that first waits for mysql to respond.

So, in your case, the entrypoint would be something like

#!/bin/bash
until mysql -h mysql1 -uapp_user -ppassword -e'select 1'; do echo "still waiting for mysql"; sleep 1; done
exec npm start
like image 79
Andreas Wederbrand Avatar answered Oct 12 '22 16:10

Andreas Wederbrand