通过一个配置文件,就可以让你的系统一键启动所有的运行环境: nodejs mysql mongodb redis

软件设计和开发,有单一职责原则。Docker也一样,每个容器都只负责一个服务
如果开发环境需要多个服务(nodejs mysql mongodb redis),就需要启动多个Docker容器。
要连同这多个Docker容器,就需要Docker-compose 。

配置示例

在项目根目录添加docker-compose.yml文件。

注意事项请预先 docker pull 用到的镜像,否则 Docker-compose 初次启动会很慢 node:14,redismysqlmongo

Docker-compose 配置 Redis

  • services:每个service都是一个docker容器

    1. version: '3'
    2. services:
    3. editor-server: # service name
    4. build:
    5. context: . # 当前目录
    6. dockerfile: Dockerfile # 基于 Dockerfile 构建
    7. image: editor-server # 依赖于当前 Dockerfile 创建出来的镜像
    8. container_name: editor-server
    9. ports:
    10. - 8081:3000 # 宿主机通过 8081 访问
    11. editor-redis: # service name,重要!
    12. image: redis # 引用官网 redis 镜像
    13. container_name: editor-redis
    14. ports:
    15. # 宿主机,可以用 127.0.0.1:6378 即可连接容器中的数据库 `redis-cli -h 127.0.0.1 -p 6378`
    16. # 但是,其他 docker 容器不能,因为此时 127.0.0.1 是 docker 容器本身,而不是宿主机
    17. - 6378:6379
    18. environment:
    19. - TZ=Asia/Shanghai # 设置时区
  • redis容器的端口:本地的redis默认端口是6379,为了redis容器的redis端口不跟本地的redis服务端口冲突,用本机的6378对应容器的6379端口

在电脑127.0.0.1:6378访问的是redis容器里面的6379端口
在电脑127.0.0.1:6379访问的是电脑redis服务的端口
Docker-compose - 图1

  • 注意容器里redis连接的host不再是127.0.0.1了,而是redis容器的容器名称,需要改一下redis配置 ```shell const devConf = require(‘./dev’)

Object.assign(devConf.redisConf, { host: ‘editor-redis’, })

  1. <a name="C3zDC"></a>
  2. ## 命令
  3. - 构建镜像`docker-compose build <service-name>`
  4. - 启动所有服务器 `docker-compose up -d` ,创建并后台启动所有容器。
  5. - 停止所有服务 `docker-compose down`
  6. - 查看服务 `docker-compose ps`
  7. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/282427/1664371939063-24009b34-2171-4ebb-9f77-7c2328d944c2.png#clientId=ub5478a82-88c2-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown%20error&from=paste&height=184&id=ude972954&margin=%5Bobject%20Object%5D&name=image.png&originHeight=368&originWidth=1616&originalType=binary&ratio=1&rotation=0&showTitle=false&size=101241&status=error&style=none&taskId=u67cea476-f1b4-4004-97f8-ce8dbc44a46&title=&width=808)
  8. <a name="ujUib"></a>
  9. ## Docker-compose 配置 Mysql
  10. > redis无数据库,而mysql和mongodb 需要创建数据库,redis是缓存,无需数据持久化,而mysql和mongodb 需要
  11. 1、修改 `docker-compose.yml` ,代码如下
  12. ```shell
  13. editor-mysql:
  14. image: mysql # 引用官网 mysql 镜像
  15. container_name: editor-mysql
  16. restart: always # 出错则重启
  17. privileged: true # 高权限,执行下面的 mysql/init
  18. command: --default-authentication-plugin=mysql_native_password # 远程访问
  19. ports:
  20. - 3305:3306 # 宿主机可以用 127.0.0.1:3305 即可连接容器中的数据库,和 redis 一样
  21. volumes:
  22. - .docker-volumes/mysql/log:/var/log/mysql # 记录日志
  23. - .docker-volumes/mysql/data:/var/lib/mysql # 数据持久化
  24. - ./mysql/init:/docker-entrypoint-initdb.d/ # 初始化 sql
  25. environment:
  26. - MYSQL_DATABASE=imooc_lego_course # 初始化容器时创建数据库
  27. - MYSQL_ROOT_PASSWORD=xx你的密码
  28. - TZ=Asia/Shanghai # 设置时区
  29. editor-mongo:
  30. image: mongo # 引用官网 mongo 镜像
  31. container_name: editor-mongo
  32. restart: always #容器出错,重启
  33. volumes:
  34. - '.docker-volumes/mongo/data:/data/db' # 数据持久化
  35. environment:
  36. - MONGO_INITDB_DATABASE=xx要设置
  37. - TZ=Asia/Shanghai # 设置时区
  38. ports:
  39. - '27016:27017' # 宿主机可以用 127.0.0.1:27016 即可连接容器中的数据库
  • 数据持久化:把本机的数据库文件夹的内容映射到容器数据库文件夹,这样就能保存数据到本机的文件夹,每次数据库重启,防止之前数据丢失。
  • 日志持久化
  • 初始化sql:注意密码和数据库名称。实践我最初密码和数据库设错了,后面改正过来重新构建镜像还是不行。解决办法:详见。首先得删除数据库持久化的内容,重新初始化数据库。 ```shell

    查看容器得到容器Id

    docker ps -a

    进入容器

    docker exec -it 49419cb9980a bash

    检查数据库密码是否正确

    echo $MYSQL_ROOT_PASSWORD

    尝试登录mysql

    mysql -u root -p
  1. 2、增加 `mysql/init/init.sql`,初始化 mysql
  2. ```shell
  3. -- docker-compose 启动 mysql 时的初始化代码
  4. select "init start...";
  5. -- 设置 root 用户可外网访问
  6. use mysql;
  7. SET SQL_SAFE_UPDATES=0; -- 解除安全模式,测试环境,没关系
  8. update user set host='%' where user='root';
  9. flush privileges;
  10. ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'xx你的密码'; -- 密码参考 docker-compose.yml
  11. flush privileges;
  12. select "init end...";

修改 config/envs/prd-dev.js ,增加 mysql 和 mongodb 的配置

  1. Object.assign(devConf.mongodbConf, {
  2. // redis容器的容器名称
  3. host: 'editor-mongo',
  4. })
  5. Object.assign(devConf.mysqlConf, {
  6. // redis容器的容器名称
  7. host: 'editor-mysql',
  8. })

修改 .gitignore 文件,增加一行 .docker-volumes/,重要!

如何通过docker-host访问数据库

因为上面editor-server服务和数据库都是在一个docker-compose.yml里面的,所以可以通过server name来访问对应docker的host。如果服务和数据库不再同一个docker-compose.yml里面,比如新建了一个h5-service。那么需要通过访问宿主机的ip 来访问数据库。
这里h5-service在Dockerfiledocker-host域名绑定到ip。
这样的话docker-host加端口就能访问到对应数据库了。其实就相当于127.0.0.1:6378
截屏2022-10-02 10.17.41.png

  1. # 启动(宿主机 ip 指向 docker-host ,以方便 docker 内部访问宿主机)
  2. CMD /sbin/ip route|awk '/default/ { print $3,"\tdocker-host" }' >> /etc/hosts && npm run prd-dev && npx pm2 log
  3. # 最终就是 "192.169.112.1 docker-host" 写入到文件/etc/hosts 里面
  4. # 其实就是让域名绑定、。
  1. const devConf = require('./dev')
  2. // 修改 mongodb 连接配置
  3. Object.assign(devConf.mongodbConf, {
  4. port: '27016', // 依赖于 biz-editor-server 启动 docker-compose
  5. host: 'docker-host', // docker 内部访问宿主机的 hostName, 配置在 Dockerfile
  6. })
  7. // 修改 redis 连接配置
  8. Object.assign(devConf.redisConf, {
  9. port: '6378', // 依赖于 biz-editor-server 启动 docker-compose
  10. host: 'docker-host', // docker 内部访问宿主机的 hostName, 配置在 Dockerfile
  11. })
  12. // 修改 mysql 连接配置
  13. Object.assign(devConf.mysqlConf, {
  14. port: '3305', // 依赖于 biz-editor-server 启动 docker-compose
  15. host: 'docker-host', // docker 内部访问宿主机的 hostName, 配置在 Dockerfile
  16. })

Docker-compose 配置 Mongodb

类似Mysql。