使用mysql和nodeJS建立一个docker

时间:2018-05-29 02:39:31

标签: mysql node.js docker

我正在构建一个使用nodeJS和后端以及mySQL作为后端的应用程序,目前,我启动应用程序(没有docker)的步骤是:

  1. 安装NodeJS
  2. 安装MYSQL
  3. 在端口3306上启动mysqld
  4. 手动创建专用于NodeJS后端的MYSQL用户。这个 用户应该只有我想要的架构的基本优势。
  5. 运行sequelize命令以执行数据迁移和种子设定 用户在4)中生成
  6. npm installnpm start在端口8080上启动NodeJS
  7. 现在我想把我的应用程序dokerize,我已经有了以下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
    

    我在./docker_db文件夹中放了一个init.sql文件,它执行以下操作:

    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;
    

    以及以下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
    

    我的./wait-for-db.sh执行以下操作:

    #!/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
    

    (顺便说一句,我确实想将3306暴露给主机,以便我可以使用工作台连接到我已成功连接的mysql服务器。)

    在我的sequelize配置文件中,我确实有:

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

    通过上述设置,我执行了docker-compose up,然后我得到了以下几行:

    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
    

    我现在面临的问题是:

    1)脚本的执行挂在Starting MySQL 5.7.22-1.1.5的最后一行,而不是去任何地方。

    2)在输出中,第3行和第4行显示有关exec用户进程导致“无此文件或目录”的错误。我不认为它是由wait-for-db.sh中的命令引起的,因为如果我在until命令后删除了行,问题仍然存在。实际上,我怀疑命令执行是否已经到达那些行,并且感觉它仍然在until命令中。

    我认为它与最终解决方案非常接近:)

2 个答案:

答案 0 :(得分:1)

使用数据库服务的名称mysql作为数据库主机。 Docker会将其解析为实际的IP。另外,为什么FROM mysql:5.7中有Dockerfile,我认为它没有任何用途。

<强>更新

好吧,似乎myapp在db准备好之前运行db脚本。请参阅此处了解解决方案https://docs.docker.com/compose/startup-order/

答案 1 :(得分:1)

问题可能与时间有关。两个容器将同时启动,你的node-app几乎会立即尝试连接到mysql,而MySQL服务器仍在启动。

docker-compose没有任何类型的结构,所以你必须在你的node-app中构建一个第一个等待mysql响应的入口点。

因此,在您的情况下,入口点将类似于

#!/bin/bash
until mysql -h mysql1 -uapp_user -ppassword -e'select 1'; do echo "still waiting for mysql"; sleep 1; done
exec npm start