为什么我的Docker卷不能在远程构build箱中工作?

我正在尝试将一个卷添加到将在托pipe构build服务(CircleCI)上的Docker Compose系统中构build和运行的Docker容器。 它在本地工作正常,但不是远程。 CircleCI提供了一个SSH工具,我可以用它来debugging为什么一个容器的行为不像预期的那样。

Docker Compose文件的相关部分是这样的:

missive-mongo: image: missive-mongo command: mongod -v --logpath /var/log/mongodb/mongodb.log --logappend volumes: - ${MONGO_LOCAL}:/data/db - ${LOGS_LOCAL_PATH}/mongo:/var/log/mongodb networks: - storage_network 

在本地,如果我做docker inspect integration_missive-mongo_1 (即正在运行的容器名称,我会得到预期的卷:

  ... "HostConfig": { "Binds": [ "/tmp/missive-volumes/logs/mongo:/var/log/mongodb:rw", "/tmp/missive-volumes/mongo:/data/db:rw" ], ... 

在同一个容器上,我可以看到容量正常工作:

 docker exec -it integration_missive-mongo_1 sh / # tail /var/log/mongodb/mongodb.log 2017-11-28T22:50:14.452+0000 D STORAGE [initandlisten] admin.system.version: clearing plan cache - collection info cache reset 2017-11-28T22:50:14.452+0000 I INDEX [initandlisten] build index on: admin.system.version properties: { v: 2, key: { version: 1 }, name: "incompatible_with_version_32", ns: "admin.system.version" } 2017-11-28T22:50:14.452+0000 I INDEX [initandlisten] building index using bulk method; build may temporarily use up to 500 megabytes of RAM 2017-11-28T22:50:14.452+0000 D INDEX [initandlisten] bulk commit starting for index: incompatible_with_version_32 2017-11-28T22:50:14.452+0000 D INDEX [initandlisten] done building bottom layer, going to commit 2017-11-28T22:50:14.454+0000 I INDEX [initandlisten] build index done. scanned 0 total records. 0 secs 2017-11-28T22:50:14.455+0000 I COMMAND [initandlisten] setting featureCompatibilityVersion to 3.4 2017-11-28T22:50:14.455+0000 I NETWORK [thread1] waiting for connections on port 27017 2017-11-28T22:50:14.455+0000 D COMMAND [PeriodicTaskRunner] BackgroundJob starting: PeriodicTaskRunner 2017-11-28T22:50:14.455+0000 D COMMAND [ClientCursorMonitor] BackgroundJob starting: ClientCursorMonitor 

好的,现在是遥控器。 我开始构build,它失败了,因为Mongo不会启动,所以我使用SSH工具,在构build失败后保持活动状态。

我首先破解了DC文件,这样它就不会尝试启动Mongo,因为它会失败。 我只是让它睡觉,而不是:

  missive-mongo: image: missive-mongo command: sleep 1000 volumes: - ${MONGO_LOCAL}:/data/db - ${LOGS_LOCAL_PATH}/mongo:/var/log/mongodb networks: - storage_network 

然后,我运行docker-compose up脚本来启动所有容器,然后检查有问题的checkbox: docker inspect integration_missive-mongo_1

  "HostConfig": { "Binds": [ "/tmp/missive-volumes/logs/mongo:/var/log/mongodb:rw", "/tmp/missive-volumes/mongo:/data/db:rw" ], 

这看起来很好。 所以在主机上我创build一个虚拟日志文件,并列出来certificate它在那里:

 bash-4.3# ls /tmp/missive-volumes/logs/mongo mongodb.log 

所以我尝试炮击,再次docker exec -it integration_missive-mongo_1 sh 。 这次我发现该文件夹存在,但不是卷的内容:

 / # ls /var/log mongodb / # ls /var/log/mongodb/ / # 

这很奇怪,因为到目前为止,远程Docker / Composeconfiguration中卷的可靠性已经是模范。

理论

目前我的主要问题是,不同版本的Docker和Docker Compose可能与它有关。 所以我会列出我有什么:

  • 本地
    • 主持人:Linux Mint
    • Docker版本1.13.1,build 092cba3
    • docker构成版本1.8.0,build立未知
  • 远程
    • 主持人:我怀疑是Alpine(它使用apk安装)
    • 我正在使用docker:17.05.0-ce-git提供的docker:17.05.0-ce-git映像,版本显示为Docker version 17.05.0-ce, build 89658be
    • Docker Composer通过Pip安装,获取版本生成docker-compose version 1.13.0, build 1719ceb

所以,有一些版本差异。 作为黑暗中的一个镜头,我可以尝试碰撞Docker / Compose,尽pipe我对打破其他的东西感到警惕。

什么是理想的,但是我可以使用某种先进的Docker命令来debugging为什么卷似乎被注册,但不在容器内部暴露。 有任何想法吗?

CircleCI从Docker守护进程远程运行docker docker-compose ,所以本地绑定挂载不起作用。

一个命名的卷将默认为local驱动程序,并将在CircleCI的Compose设置中工作,该卷将存在于运行容器的地方。

通常应该在每个容器设置的单个进程中将日志logging保存到stdout和stderr。 然后,您可以使用日志驱动程序插件将其发送到中央收集器。 MongoDB默认在前台运行时logging到stdout / stderr。

结合卷和日志:

 version: "2.1" services: syslog: image: deployable/rsyslog ports: - '1514:1514/udp' - '1514:1514/tcp' mongo: image: mongo command: mongod -v volumes: - 'mongo_data:/data/db' depends_on: - syslog logging: options: tag: '{{.FullID}} {{.Name}}' syslog-address: "tcp://10.8.8.8:1514" driver: syslog volumes: mongo_data: 

由于日志logging端点通常是外部的,而不是同一个组中的容器,所以这有些黑客攻击。 这就是为什么日志logging使用外部地址和端口映射来访问系统日志服务器。 这个连接在docker守护进程和日志服务器之间,而不是容器到容器。

我想添加一个附加的答案,陪同接受的。 我在CircleCI上的用例是运行基于浏览器的集成testing,以检查整个堆栈是否正常工作。 正在使用的11个容器中的许多容器具有为各种事物定义的卷,如日志输出和原始数据库文件存储。

到目前为止我还没有意识到,由于Docker技术的限制,CircleCI的Docker执行程序中的卷不起作用。 由于这种失败,在以前的每种情况下,文件只是写入一个空的文件夹。

然而,在我的新案件中,这个问题正在导致Mongo失败。 原因是我正在使用--logappend来防止Mongo在启动时自行执行日志--logappend ,并且此开关需要在--logpath指定的path存在。 由于存在于主机上,但卷创build失败,容器看不到日志文件。

为了解决这个问题,我修改了我的Mongo服务条目,在command部分调用脚本:

  missive-mongo: image: missive-mongo command: sh /root/mongo-logging.sh 

脚本如下所示:

 #!/bin/sh # # The command sets up logging in Mongo. The touch is for the benefit of any # environment in which the logs do not already exist (eg Integration, since # CircleCI does not support volumes) touch /var/log/mongodb/mongodb.log \ && mongod -v --logpath /var/log/mongodb/mongodb.log --logappend 

在这两种可能的用例中,这将如下所示:

  • 在挂载工作(dev,live)的情况下,如果它存在,它将简单地触及一个文件,如果它不存在,就创build它(例如一个全新的环境),
  • 如果挂载不起作用(CircleCI),它将创build该文件。

无论哪种方式,这是一个很好的安全function,以防止Mongo炸毁。