资讯专栏INFORMATION COLUMN

mongo EOF(二)

dreambei / 3086人阅读

摘要:容器访问以为例,在原始的文件中,如下上面的配置,本地主机是无法访问容器的,我们至少需要暴露出一个端口。查看,的默认端口其实是,而这里写成也是有原因的。

任何事情的成功都需要掐准时间

上一节mongo EOF中,关于容器的配置,只是粗略的使用了Docker-Compose-MongoDB-Replica-Set项目提供好的docker-compose.yml文件。在使用过程中,我发现这个文件本身一些不如意的地方。首先,services中的creator服务,entrypoint指令太长了,不美;其次,所有的service都没有给容器外部暴露端口,导致外部无法访问容器;再次,直接使用mongo repliSet的连接串进行访问,无法正常访问mongo服务。

在上一篇文章的基础上,这篇文章对docker-compse.yml做了一些调整,并且也包含了docker使用的入门介绍。更新后的docker-compose.yml请访问githubsi。

depends_on
However, for startup Compose does not wait until a container is “ready” (whatever that means for your particular application) - only until it’s running. There’s a good reason for this.

creator service中使用了该指令, 但是,实际中creator不会等到mongo1mongo2mongo3容器ready后再启动,而是等到它们启动就开始启动。这也是我在setup脚本中执行sleep操作的原因。

creator:
    build:
      context: .
      dockerfile: dockerfile
    entrypoint: ["/data/conf/setup.sh"]
    depends_on:
      - mongo1
      - mongo2
      - mongo3
entrypoint
Entrypoint sets the command and parameters that will be executed first when a container is run.

entrypoint设置了容器启动时执行的命令和参数,传递给docker run 的参数都将追加到entrypoint命令之后,并且会覆盖CMD命令。比如,docker run bash 将会追加bashentrypoint命令末尾。

命令的语法格式:

ENTRYPOINT ["executable" "param1" "param2"]

在修改后的docker-compose.yml中,entrypoint指令用于执行shell脚本。按照规范来说,可执行文件名称中需要包含entrypoint字段,也就是将下列指令中的setup.sh重命名为setup-entrypoint.sh。但是,重命名之后的文件,容器执行会报错,所以,这里也并没有使用这个规范。

entrypoint: ["/data/conf/setup.sh"]
调整creator中的entrypoint指令

原始的文件如下所示,entrypoint指令的参数非常难看:

creator:
    build: creator
    entrypoint: ["mongo","--host","mongo1","--port","27017","--eval", "rs.initiate( { _id : "rs0",members: [{ _id: 0, host: "mongo1:27017" },{ _id: 1, host: "mongo2:27017" },{ _id: 2, host: "mongo3:27017" }   ]})"]
    depends_on:
      - mongo1
      - mongo2
      - mongo3

如果将entrypoint的执行命令提取到一个多带带的的脚本中,会让整个页面看起来更加简洁。所以,新建一个setup.sh文件。其中的replicaSet.js用于执行rs.initiate操作,详情可以查看github项目。其中的sleep指令只是为了保证:在执行initiatemongo的3个服务都启动了。

#! /bin/bash

echo "******************************"
echo Start the replica set
echo `date`
echo "******************************"

sleep 20 | echo Sleeping
echo `date`

mongo mongodb://mongo1:37017 replicaSet.js

相应的,我们需要调整creatordockerfile文件,因为此时的容器内,并没有我们需要的相关文件。我们需要在创建镜像的时候,拷贝本地文件到容器。调整后的文件如下:

FROM mongo:4.0.4

MAINTAINER Yowko Tsai 

WORKDIR /data/conf

COPY ./setup.sh /data/conf/setup.sh
COPY ./replicaSet.js /data/conf/replicaSet.js

CMD ["./setup.sh"]

在项目的目录下,我们多带带编译creatordockerfile文件,已保证调整是有效的。

docker build .
docker run 
容器访问

mongo1为例,在原始的文件中,docker-compose.yml如下:

mongo1:
    container_name: mongo1
    image: mongo:4-xenial
    expose:
      - 27017
    restart: always
    entrypoint: [ "mongod", "--bind_ip_all", "--replSet", "rs0" ]

上面的配置,本地主机是无法访问容器的,我们至少需要暴露出一个端口。下面通过添加ports来指定容器外到容器内的端口映射。在上一篇中已经介绍过portsexpose的相关内容,感兴趣的可以去查看。之后,我们就可以通过37017端口来访问容器内的mongo1服务了。

mongo1:
    container_name: mongo1
    image: mongo:4.0.4
    expose:
      - 37017
    ports:
      - "37017:37017"
    restart: always
    entrypoint: [ "mongod", "--port", "37017", "--bind_ip_all", "--replSet", "rs0" ]

查看Default MongoDB Port,mongod的默认端口其实是27017,而这里写成37017也是有原因的。未修改之前mongod的端口映射,如下所示。每个容器中的mongo服务都使用默认的27017端口,通过暴露不通的宿主主机端口来达到区分容器服务的目的。

mongo1:
    container_name: mongo1
    image: mongo:4.0.4
    expose:
      - 27017
    ports:
      - "27017:27017"
    restart: always
    entrypoint: [ "mongod", "--bind_ip_all", "--replSet", "rs0" ]
  mongo2:
    container_name: mongo2
    image: mongo:4.0.4
    expose:
      - 27017
    ports:
      - "27018:27017"
    restart: always
    entrypoint: [ "mongod", "--bind_ip_all", "--replSet", "rs0" ]
  mongo3:
    container_name: mongo3
    image: mongo:4.0.4
    expose:
      - 27017
    ports:
      - "27019:27017"
    restart: always
    entrypoint: [ "mongod", "--bind_ip_all", "--replSet", "rs0" ]

在多带带连接mongo服务的时候,这样的配置是没有任何问题的。我们在命令行输入mongo,也会连接到其中任意一个mongo服务。如果恰好连接的不是PRIMARY节点,可以执行rs.slaveOk()来执行查询。

但当使用replicaSet连接串来访问mongo服务时,连接却会失败。看看这个连接串,感觉不出任何问题。

mongo mongodb://127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019/admin?replicaSet=rs0

看了报错信息,才明白:当执行连接的时候,mongo会拉取replica set 的配置信息,而通过host去访问的时候失败了。很明显:docker-compose容器内可以将server name当作host来相互访问,但在容器外通过server name是访问不通的。

changing hosts to rs0/mongo1:27017,mongo2:27017,mongo3:27017 from rs0/127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019

另外,你还可以在容器内部打开/etc/hosts文件,查看容器内映射的ip地址,容器外也是ping不通的。我们可以通过下面的指令进入容器查看:

docker exec -it  bash 
less /etc/hosts

解决的办法是,我们在本地主机上追加host。但这样的话,rs0其实只有一个节点,因为都映射到了127.0.0.1:27017这个容器上。

# file: /etc/hosts
127.0.0.1 mongo1, mongo2, mongo3

基于这个原因,我们修改了容器内外暴露的端口。同时,修改各个服务mongod启动时的默认端口以及replica set的配置信息:

mongo1:
    container_name: mongo1
    image: mongo:4.0.4
    expose:
      - 37017
    ports:
      - "37017:37017"
    restart: always
    entrypoint: [ "mongod", "--port", "37017", "--bind_ip_all", "--replSet", "rs0" ]
  mongo2:
    container_name: mongo2
    image: mongo:4.0.4
    expose:
      - 37018
    ports:
      - "37018:37018"
    restart: always
    entrypoint: [ "mongod", "--port", "37018", "--bind_ip_all", "--replSet", "rs0" ]
  mongo3:
    container_name: mongo3
    image: mongo:4.0.4
    expose:
      - 37019
    ports:
      - "37019:37019"
    restart: always
    entrypoint: [ "mongod", "--port", "37019", "--bind_ip_all", "--replSet", "rs0" ]
// file :replicaSet.js

rsconf = {
    _id: "rs0",
    members: [
        {_id: 0, host: "mongo1:37017"},
        {_id: 1, host: "mongo2:37018"},
        {_id: 2, host: "mongo3:37019"}
    ]
}

rs.initiate(rsconf);
rs.conf();

做了这些修改,我们就可以正常访问mongo服务了:

mongo mongodb://mongo1:37017,mongo2:37018,mongo3:37019/admin?replicaSet=rs0
启动服务

首先,我们看看镜像能不能顺利编译过去:

docker-compose -f docker-compose.yml build

其次,我们启动容器服务:

docker-compose -f docker-compose.yml up

最后,关闭容器服务。这个命令相当于依次执行docker container stopdocker-compose down,很方便。

docker-compose -f docker-compose.yml down
总结

执行上一篇的测试用例,然后中途关闭一个节点,来查看执行效果。

启动容器:

docker-compose -f docker-compose.yml down

查看容器的运行情况:

docker ps

关闭其中一个容器:

docker container stop 

服务短暂的输出.no reachable servers错误信息后,由恢复正常了!

备注

看到这里的人,必须关注公众号了

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/27842.html

相关文章

  • 深入解析 MongoDB Plan Cache

    摘要:所以在扫描次后,率先到达状态,那么此刻将停止扫描,进入到算分的阶段。除了这条引发故障的之外,其他的字段命中索引数量都非常小,有的甚至只有一条。那这里很明显在中只去根据中执行计划的相关索引来进行判断是不合理的。 前段时间笔者遇到一个MongoBD Plan Cache的bug,于是深究了下MongoDB优化器相关源码。在这里分享给大家,一方面让大家知道MongoDB优化器工作原理,一方面...

    Pluser 评论0 收藏0
  • 如何编写简单的parser(实践篇)

    摘要:负责读取和记录当前代码的位置,并把读取到的代码交给处理,其意义在于,当传递给的代码需要进行判读猜测时,能够记录当前读取的位置,并在接下来的操作汇总回滚到之前的读取位置,也能在发生语法错误时,准确指出错误发生在代码段的第几行第几个字符。 上一篇(《如何编写简单的parser(基础篇)》)中介绍了编写一个parser所需具备的基础知识,接下来,我们要动手实践一个简单的parser,既然是简...

    shaonbean 评论0 收藏0
  • 最简单的dockerfile使用教程 - 创建一个支持SSL的Nginx镜像

    摘要:为此我首先需要创建一个针对的配置文件。的作用是指定基准镜像。该以后面指定的镜像为基础,在其上进行定制。存在一个特殊的镜像,名为。它是一个虚拟的概念,表示一个空白的镜像。直接使用会让镜像体积更加小巧。 什么是dockerfile?简单的说就是一个文本格式的脚本文件,其内包含了一条条的指令(Instruction),每一条指令负责描述镜像的当前层(Layer)如何构建。 下面通过一个具体的...

    xiaolinbang 评论0 收藏0
  • Docker入门()在docker使用MongoDB

    摘要:本文将介绍如何在中使用。如果你是一名的初学者,那么你入门的第一件事就是安装,但是安装又不是一件简单的事情,还需要自己配置一些服务。这时候,就能帮上大忙,它能够让你不需要本地安装就能使用。下面让我们来看看这是怎么实现的。   本文将介绍如何在docker中使用MongoDB。  如果你是一名MongoDB的初学者,那么你入门MongoDB的第一件事就是安装MongoDB,但是安装Mong...

    gaomysion 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<