使用mysql和nodejs构建docker

von4xj4u  于 2021-06-23  发布在  Mysql
关注(0)|答案(2)|浏览(494)

我正在构建一个应用程序,它使用nodejs和backend以及mysql作为后端,目前,我启动这个应用程序(没有docker)的步骤是:
安装nodejs
安装mysql
在3306端口启动mysqld
手动创建nodejs后端专用的mysql用户。这个用户应该只对我想要的模式有基本的权限。
运行sequelize命令以使用在4)中生成的用户执行数据迁移和种子设定 npm install 以及 npm start 在端口8080上启动nodejs
现在我想对我的应用程序进行dokerize,我已经有了以下dockerfile:

  1. # node version: carbon
  2. # app version: 1.0.0
  3. FROM node:8.11.2
  4. WORKDIR /usr/src/app
  5. COPY package*.json ./
  6. RUN npm install
  7. COPY . .
  8. EXPOSE 8080

我在./docker\u db文件夹中放置了一个init.sql文件,它执行以下操作:

  1. CREATE USER 'app_user'@'%' IDENTIFIED BY 'password';
  2. CREATE SCHEMA `myapp` DEFAULT CHARACTER SET utf8;
  3. GRANT INSERT, CREATE, ALTER, UPDATE, SELECT, REFERENCES on myapp.*
  4. TO 'app_user'@'%' IDENTIFIED BY 'password'
  5. WITH GRANT OPTION;

以及以下docker-compose.yaml:

  1. version: '3.6'
  2. services:
  3. mysql1:
  4. image: mysql/mysql-server:5.7
  5. environment:
  6. MYSQL_ROOT_PASSWORD: password
  7. ports:
  8. - "127.0.0.1:3306:3306"
  9. volumes:
  10. - type: bind
  11. source: ./docker_db
  12. target: /docker-entrypoint-initdb.d
  13. expose:
  14. - "3306"
  15. networks:
  16. - app-network
  17. myapp:
  18. build:
  19. context: .
  20. dockerfile: Dockerfile
  21. command: npm start
  22. depends_on:
  23. - mysql1
  24. ports:
  25. - "127.0.0.1:8080:8080"
  26. expose:
  27. - "8080"
  28. links:
  29. - mysql1
  30. networks:
  31. - app-network
  32. command: ["./wait-for-db.sh"]
  33. networks:
  34. app-network:
  35. driver: bridge

其中my./wait-for-db.sh执行以下操作:

  1. # !/bin/bash
  2. until mysql -h mysql1 -u app_user -p password -e 'select 1'; do
  3. echo "still waiting for mysql"; sleep 1; done
  4. exec node ./db/scripts/generateSequelizeCLIConfig.js
  5. exec node_modules/sequelize-cli/bin/sequelize db:migrate
  6. exec node_modules/sequelize-cli/bin/sequelize db:seed:all
  7. exec npm start

(顺便说一句,我确实想将3306公开给主机,这样我就可以使用workbench连接到mysql服务器,我已经成功连接了它。)
在我的sequelize配置文件中,我有:

  1. "username": "app_user",
  2. "password": "password",
  3. "database": "myapp",
  4. "host": "mysql1",
  5. "port": "3306"

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

  1. mysql1_1 | [Entrypoint] MySQL Docker Image 5.7.22-1.1.5
  2. mysql1_1 | [Entrypoint] Initializing database
  3. myapp_1 | standard_init_linux.go:190: exec user process caused "no such file or directory"
  4. myapp_myapp_1 exited with code 1
  5. mysql1_1 | [Entrypoint] Database initialized
  6. mysql1_1 | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
  7. mysql1_1 | Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.
  8. mysql1_1 | Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.
  9. mysql1_1 | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
  10. mysql1_1 | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
  11. mysql1_1 |
  12. mysql1_1 | [Entrypoint] running /docker-entrypoint-initdb.d/init.sql
  13. mysql1_1 |
  14. mysql1_1 |
  15. mysql1_1 | [Entrypoint] Server shut down
  16. mysql1_1 |
  17. mysql1_1 | [Entrypoint] MySQL init process done. Ready for start up.
  18. mysql1_1 |
  19. 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 命令。
不过,我觉得这已经接近最终解决方案了:)

wnrlj8wa

wnrlj8wa1#

使用数据库服务的名称,即 mysql ,作为数据库主机。docker会将其解析为实际ip。为什么你有 FROM mysql:5.7 在你的 Dockerfile ,我觉得没什么用。
更新
好吧,好像 myapp 在数据库准备就绪之前运行数据库脚本。请参阅此处了解解决方案https://docs.docker.com/compose/startup-order/

2guxujil

2guxujil2#

问题可能与时间有关。这两个容器将同时启动,您的节点应用程序将几乎立即尝试连接到mysql,而mysql服务器仍在启动。
docker compose没有任何类型的结构,因此您必须在节点应用程序中构建一个入口点,首先等待mysql响应。
所以,在你的例子中,入口点应该是

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

相关问题