通过一个配置文件,就可以让你的系统一键启动所有的运行环境: nodejs mysql mongodb redis
软件设计和开发,有单一职责原则。Docker也一样,每个容器都只负责一个服务。
如果开发环境需要多个服务(nodejs mysql mongodb redis),就需要启动多个Docker容器。
要连同这多个Docker容器,就需要Docker-compose 。
配置示例
在项目根目录添加docker-compose.yml
文件。
注意事项请预先
docker pull
用到的镜像,否则Docker-compose
初次启动会很慢 node:14,redis,mysql,mongo
Docker-compose 配置 Redis
services:每个service都是一个docker容器
version: '3'
services:
editor-server: # service name
build:
context: . # 当前目录
dockerfile: Dockerfile # 基于 Dockerfile 构建
image: editor-server # 依赖于当前 Dockerfile 创建出来的镜像
container_name: editor-server
ports:
- 8081:3000 # 宿主机通过 8081 访问
editor-redis: # service name,重要!
image: redis # 引用官网 redis 镜像
container_name: editor-redis
ports:
# 宿主机,可以用 127.0.0.1:6378 即可连接容器中的数据库 `redis-cli -h 127.0.0.1 -p 6378`
# 但是,其他 docker 容器不能,因为此时 127.0.0.1 是 docker 容器本身,而不是宿主机
- 6378:6379
environment:
- TZ=Asia/Shanghai # 设置时区
redis容器的端口:本地的redis默认端口是6379,为了redis容器的redis端口不跟本地的redis服务端口冲突,用本机的6378对应容器的6379端口
在电脑127.0.0.1:6378
访问的是redis容器里面的6379端口
在电脑127.0.0.1:6379
访问的是电脑redis服务的端口
- 注意容器里redis连接的host不再是
127.0.0.1
了,而是redis容器的容器名称,需要改一下redis配置 ```shell const devConf = require(‘./dev’)
Object.assign(devConf.redisConf, { host: ‘editor-redis’, })
<a name="C3zDC"></a>
## 命令
- 构建镜像`docker-compose build <service-name>`
- 启动所有服务器 `docker-compose up -d` ,创建并后台启动所有容器。
- 停止所有服务 `docker-compose down`
- 查看服务 `docker-compose ps`
![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)
<a name="ujUib"></a>
## Docker-compose 配置 Mysql
> redis无数据库,而mysql和mongodb 需要创建数据库,redis是缓存,无需数据持久化,而mysql和mongodb 需要
1、修改 `docker-compose.yml` ,代码如下
```shell
editor-mysql:
image: mysql # 引用官网 mysql 镜像
container_name: editor-mysql
restart: always # 出错则重启
privileged: true # 高权限,执行下面的 mysql/init
command: --default-authentication-plugin=mysql_native_password # 远程访问
ports:
- 3305:3306 # 宿主机可以用 127.0.0.1:3305 即可连接容器中的数据库,和 redis 一样
volumes:
- .docker-volumes/mysql/log:/var/log/mysql # 记录日志
- .docker-volumes/mysql/data:/var/lib/mysql # 数据持久化
- ./mysql/init:/docker-entrypoint-initdb.d/ # 初始化 sql
environment:
- MYSQL_DATABASE=imooc_lego_course # 初始化容器时创建数据库
- MYSQL_ROOT_PASSWORD=xx你的密码
- TZ=Asia/Shanghai # 设置时区
editor-mongo:
image: mongo # 引用官网 mongo 镜像
container_name: editor-mongo
restart: always #容器出错,重启
volumes:
- '.docker-volumes/mongo/data:/data/db' # 数据持久化
environment:
- MONGO_INITDB_DATABASE=xx要设置
- TZ=Asia/Shanghai # 设置时区
ports:
- '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
2、增加 `mysql/init/init.sql`,初始化 mysql
```shell
-- docker-compose 启动 mysql 时的初始化代码
select "init start...";
-- 设置 root 用户可外网访问
use mysql;
SET SQL_SAFE_UPDATES=0; -- 解除安全模式,测试环境,没关系
update user set host='%' where user='root';
flush privileges;
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'xx你的密码'; -- 密码参考 docker-compose.yml
flush privileges;
select "init end...";
修改 config/envs/prd-dev.js
,增加 mysql 和 mongodb 的配置
Object.assign(devConf.mongodbConf, {
// redis容器的容器名称
host: 'editor-mongo',
})
Object.assign(devConf.mysqlConf, {
// redis容器的容器名称
host: 'editor-mysql',
})
修改 .gitignore
文件,增加一行 .docker-volumes/
,重要!
如何通过docker-host访问数据库
因为上面editor-server
服务和数据库都是在一个docker-compose.yml里面的,所以可以通过server name来访问对应docker的host。如果服务和数据库不再同一个docker-compose.yml里面,比如新建了一个h5-service。那么需要通过访问宿主机的ip 来访问数据库。
这里h5-service在Dockerfile
把docker-host
域名绑定到ip。
这样的话docker-host
加端口就能访问到对应数据库了。其实就相当于127.0.0.1:6378
# 启动(宿主机 ip 指向 docker-host ,以方便 docker 内部访问宿主机)
CMD /sbin/ip route|awk '/default/ { print $3,"\tdocker-host" }' >> /etc/hosts && npm run prd-dev && npx pm2 log
# 最终就是 "192.169.112.1 docker-host" 写入到文件/etc/hosts 里面
# 其实就是让域名绑定、。
const devConf = require('./dev')
// 修改 mongodb 连接配置
Object.assign(devConf.mongodbConf, {
port: '27016', // 依赖于 biz-editor-server 启动 docker-compose
host: 'docker-host', // docker 内部访问宿主机的 hostName, 配置在 Dockerfile
})
// 修改 redis 连接配置
Object.assign(devConf.redisConf, {
port: '6378', // 依赖于 biz-editor-server 启动 docker-compose
host: 'docker-host', // docker 内部访问宿主机的 hostName, 配置在 Dockerfile
})
// 修改 mysql 连接配置
Object.assign(devConf.mysqlConf, {
port: '3305', // 依赖于 biz-editor-server 启动 docker-compose
host: 'docker-host', // docker 内部访问宿主机的 hostName, 配置在 Dockerfile
})
Docker-compose 配置 Mongodb
类似Mysql。