docker-compose mongo 启动mongo容器后如何执行脚本创建用户数据库问题
系统版本:
Docker version 20.10.7, build f0df350 docker-compose version 1.29.2, build 5becea4c
1.docker-compose文件和start.sh
环境变量:Linux下必须export声明两个环境变量,注意这个账户同时也是创建的数据库的连接用户密码
export MONGO_INITDB_ROOT_USERNAME=<用户名>
export MONGO_INITDB_ROOT_PASSWORD=<密码>
目录:/home/user/docker-compose.yml
镜像:mongo:6.0.10
容器名:mongobss
挂载卷:data/db数据目录 start.sh后创建用户和库的脚本
环境变量:定义初始的mongo root角色用户
privileged:给予容器高权限
version: '3' services: mongodb: image: mongo:6.0.10 container_name: mongobss ports: - 27017:27017 privileged: true volumes: - "./data/db:data/db" - "./start.sh:/docker-entrypoint-initdb.d/start.sh" #这里是关键点涉及到mongo官方打包镜像时定义的sh启动文件在3中讲解 environment: - MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME} - MONGO_INITDB_ROOT_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD} tty: true
目录:/home/user/start.sh
set -e:遇到错误shell不退出
mongosh:mongo高版本的命令行工具替代了原有的mongo,该脚本使用mongosh创建了初始的用户和库
#!/bin/bash set -e echo "Creating database: <库名>" mongosh --username ${MONGO_INITDB_ROOT_USERNAME} --password ${MONGO_INITDB_ROOT_PASSWORD} <<EOF use admin use <库名> db.createUser({ user: "${MONGO_INITDB_ROOT_USERNAME}", pwd: "${MONGO_INITDB_ROOT_PASSWORD}", roles: [{ role: "readWrite", db: "<库名>" }] }) EOF
2.启动容器:
目录:/home/user
命令:
cd /home/user export 用户变量 export 密码变量 //能联网 docker pull mongo:6.0.10 //内网环境 //需要mongo 6.0.10的镜像tar, 一半网上找不到,可以在vmware中pull一个下来执行 docker save -o mongo.tar <镜像ID> 可以保存为tar包再上传到内网服务器 docker load -i mongo.tar docker-compose up -d
//查看容器运行状态,测试中初始化的时长大概在40秒左右完成脚本执行,其他服务才能连上mongo,如果有其他服务连接mongo建议发起一个sleep等待这个时间
docker ps
dcoker logs -f monogobss
//成功的日志输出
{"t":{"$date":"2023-12-16T04:42:41.548+00:00"},"s":"I", "c":"STORAGE", "id":22262, "ctx":"initandlisten","msg":"Timestamp monitor starting"}
{"t":{"$date":"2023-12-16T04:42:41.550+00:00"},"s":"I", "c":"NETWORK", "id":23015, "ctx":"listener","msg":"Listening on","attr":{"address":"/tmp/mongodb-27017.sock"} }
{"t":{"$date":"2023-12-16T04:42:41.550+00:00"},"s":"I", "c":"NETWORK", "id":23015, "ctx":"listener","msg":"Listening on","attr":{"address":"0.0.0.0"}}
{"t":{"$date":"2023-12-16T04:42:41.550+00:00"},"s":"I", "c":"NETWORK", "id":23016, "ctx":"listener","msg":"Waiting for connections","attr":{"port":27017,"ssl":"off"}}
{"t":{"$date":"2023-12-16T04:42:44.816+00:00"},"s":"I", "c":"NETWORK", "id":22943, "ctx":"listener","msg":"Connection accepted","attr":{"remote":"192.168.208.3:51104","uuid":"66225b3a-525e-450c-9d2b-a97d3bf173c9","connectionId":1,"connectionCount":1}}
3.docker-entrypoint-initdb.d作用:
mongo官方ENTRYPOINT容器入口文件:
https://github.com/docker-library/mongo/blob/master/docker-entrypoint.sh
这是在mongo官方文档查到的他们在构建镜像时 ENTRYPOINT 指定的容器启动端口文件docker-entrypoint.sh,当docker启动mongo容器时mongo首先会执行该这个脚本。
b70ce161a9f4 mongo:6.0.10 "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:27017->27017/tcp, :::27017->27017/tcp mongobss
该脚本一共420行大多部分都是启动mongo进程的准备,主要关注的是最后几行,for循环读取/docker-entrypoint-initdb.d/ 该文件下的.sh .js格式脚本去执行,如果按照常规方法使用docker-compose的command字段会替换掉ENTRYPOINT 指定的启动文件也就无法启动mongo进程,但是采用 1 中volume挂载方式将脚本放入for指定的目录下,就会自动执行。
export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" echo for f in /docker-entrypoint-initdb.d/*; do case "$f" in *.sh) echo "$0: running $f"; . "$f" ;; *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; *) echo "$0: ignoring $f" ;; esac echo done
4.外部程序使用mongo:
java -jar启动jar包为例:
假设你的配置文件引用的是环境变量,要注意因为mongo容器启动时间较长我们主程序要等待mongo容器初始化完成在发起链接请求mongo,可以在服务的启动文件sleep 45秒左右
[root@ config]# vi application.properties
spring.data.mongodb.uri=${SPRING_DATA_MONGODB_URI}
这是docker-compose启动服务容器时环境变量的写法:要注意这个compose文件有两个容器 1 mongo的container_name=mongodb 2 jar包的应用程序,根据docker网络的特性可以直接使用hostname引用mongo
environment: - SPRING_DATA_MONGODB_URI=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongodb:27017/BSStructure