docker-compose 完整实践
本文介绍docker-compose实践时的一些疑问与解决方案, 可能对新手略有帮助, 因此整理成文. 有不妥之处欢迎指摘!
Q1: docker-compose 如何安装?
A1: https://docs.docker.com/compose/install/#install-compose
Q2: 如何创建一个 mongodb docker-compose?
A2: 参照 https://gist.github.com/wesleybliss/29d4cce863f5964a3eb73c42501d99e4
version: "3"
services:
mongo:
build: mongo: 3.0
volumes:
- xtest-data:/data/db
ports:
- 27017:27017
command: mongod --smallfiles --logpath=/dev/null # --quiet
volumes:
xtest-data:
-
由于使用了ports参数建立mongodb端口的映射, 因此可以在其他mongo客户端访问容器数据库, 等同于docker run 的
-p
参数; -
使用volumes挂载数据卷到容器, 等同于 docker run 的
-v
参数; 需要注意的是, 当指定volumes挂载关系后, 需要在docker-compose 文件services
同级声明volumes(注意xtest-data后的":"冒号)
Q3: version: "3" 是什么?
A3: version指的是docker-compose的version, 详见https://docs.docker.com/compose/compose-file/#reference-and-guidelines
Q4: 如何在mongo数据库自动创建用户?
A4: 可以写一个初始化mongo的shell脚本, 并将该脚本写入mongo镜像中, 在初始化时执行该脚本.
具体操作:
- 创建mongo目录, 并在该目录创建Dockerfile-mongo
FROM mongo:3.0
COPY init_mongo.sh init_mongo.sh
COPY mongodb.conf mongodb.conf
COPY mongo-fork.conf mongo-fork.conf
COPY start_mongo.sh start_mongo.sh
CMD ["./start_mongo.sh"]
EXPOSE 27017
其中几个文件分别为:
mongodb.conf: mongodb配置文件, 前台运行
mongo-fork.conf: mongodb配置文件, 后台运行
init_mongo.sh: 调用mongo-fork.conf, 后台启动mongod; 连接并创建mongodb用户
start_mongo.sh: 调用mongodb.conf, 前台启动mongod
- 创建一个初始化mongodb的docker-compose.yml
version: "3"
services:
mongo:
build:
context: mongo
dockerfile: Dockerfile-mongo
volumes:
- xtest-data:/data/db
command: ./init_mongo.sh
volumes:
xtest-data:
build下, context表示路径, dockerfile表示Dockerfile文件名
- 启动该docker-compose.yml即可调用容器内的初始化脚本, 完成创建用户.
Q5: 其他容器如何连接mongodb?
A5: 要考虑的几个问题: 一是host, 二是port;
由于port可以通过ports映射到宿主机, 所以port容易解决. 考虑到安全问题, 只将端口开放给同一个docker-compose的其他容器访问, 因此用 expose
参数开放 27017
端口;
参考https://docs.docker.com/compose/compose-file/#links, 其他容器使用links
可以将mongo容器的ip记录到该容器中, 再通过连接 mongo:27017
可以访问数据库.
version: "3"
services:
backend:
build:
context: backend
dockerfile: Dockerfile-backend
ports:
- "8099:8099"
- "8009:8009"
links:
- mongo
depends_on:
- mongo
mongo:
build:
context: mongo
dockerfile: Dockerfile-mongo
volumes:
- xtest-data:/data/db
expose:
- "27017"
# uncommand to able host visit mongo
#ports:
# - "27017:27017"
command: ./start_mongo.sh
volumes:
xtest-data:
通过depends_on
来标记依赖关系, 当mongo
服务启动完成后, 才会启动backend
服务;
由于后端代码只考虑到mongodb与后端服务部署在同一台宿主机情况下, mongo的host始终为127.0.0.1
, 因此需要修改后端代码, 判断为容器时host=mongo
, 不为容器时host=127.0.0.1
.
Q6: 如何在Python代码中判断当前环境是否为容器?
A6: 一个简单的方法是为该容器添加一个环境变量, 在Python代码中判断有该变量时为容器, 没有时为普通环境.
在后端镜像的Dockerfile中添加:
ENV DOCKER 1
在Python代码中添加:
try:
docker_flag = os.environ.get('DOCKER', "")
if docker_flag == '1':
mongo_host = 'mongo'
print('Run in docker!')
else:
mongo_host = '127.0.0.1'
except:
print("Unexpected error:", sys.exc_info()[0])
raise
以上完成对mongo host的设置切换.
Q7: 如何分离前后端, 使得前端代码修改时无需将所有环境都重新构建?
A7: 单独创建一个前端镜像, 挂载一个前端数据卷到该容器中进行编译, 编译完成后, 在启动后端服务时直接挂载前端数据卷即可, 无需再启动该镜像. 即: 该前端镜像只是用于编译前端文件!
version: "3"
services:
node:
build:
context: node
dockerfile: Dockerfile-node
volumes:
- xtest-front:/www/xtest-web/dist
volumes:
xtest-front:
下载源码与编译的过程在Dockerfile中, docker-compose的工作主要是挂载xtest-front数据卷到容器中, 使得编译后的前端文件能够持久化到该数据卷中用于与后端交互.
总结
以上是在将 x-utest 系统 Docker 化过程中的经验收获, 完整的项目在 https://github.com/x-utest/xtest-docker-compose , 欢迎学习, 也欢迎使用 x-utest 测试系统并提出意见与建议!
关于 x-utest
官方文档: http://xtest.readthedocs.io/zh/latest/
参考
[1] Compose file version 3 reference, https://docs.docker.com/compose/compose-file/
[2] Docker Compose 项目, https://yeasy.gitbooks.io/docker_practice/content/compose/