Docker 记一次 docker-compose 完整实践

严北 · 2018年04月09日 · 2045 次阅读

本文介绍 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

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/

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册