为什么我的Docker卷无法在远程构建盒中工作?

时间:2017-11-28 23:19:33

标签: docker docker-compose circleci docker-volume

我正在尝试将一个卷添加到Docker容器中,该容器将在托管构建服务(CircleCI)上的Docker Compose系统中构建和运行。它在本地工作正常,但不是远程。 CircleCI提供了一个SSH工具,我可以用它来调试容器没有按预期运行的原因。

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

好的,现在是遥控器。我开始构建,它失败了因为Mongo无法启动,所以我使用SSH工具在构建失败后保持盒子活着。

我首先破解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脚本来启动所有容器,然后检查有问题的框:docker inspect integration_missive-mongo_1

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

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

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 / Compose配置中卷的可靠性一直是典范。

理论

目前我的主要版本是Docker和Docker Compose的不同版本可能与它有关。所以我会列出我的内容:

  • 本地
    • 主持人:Linux Mint
    • Docker版本1.13.1,构建092cba3
    • docker-compose版本1.8.0,构建未知
  • 远程
    • 主持人:我怀疑它是Alpine(它使用apk进行安装)
    • 我使用的是CircleCI提供的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,虽然我对打破其他事情很谨慎。

虽然是理想的,但是我可以使用某种高级Docker命令来调试为什么卷似乎已注册但未在容器内公开。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

CircleCI runs docker-compose remotely from the Docker daemon所以本地绑定挂载不起作用。

named volume将默认为local驱动程序,并且可以在CircleCI的Compose设置中运行,该卷将存在于容器运行的任何位置。

通常应将记录留给每个容器设置的单个进程中的stdout和stderr。然后,您可以使用logging driver plugin运送到中央收集器。 MongoDB默认在前台运行时记录到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:

这有点像黑客攻击,因为日志记录端点通常是外部的,而不是同一组中的容器。这就是日志记录使用外部地址和端口映射来访问syslog服务器的原因。此连接位于docker守护程序和日志服务器之间,而不是容器到容器之间。

答案 1 :(得分:2)

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

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

然而,在我的新案例中,这个问题导致Mongo失败。原因是我使用<ActionBar title="Groceries"> <!-- On iOS devices, <ActionItem>s are placed from left to right in sequence; you can override that (as the code above does) by providing an ios.position attribute. --> <ActionItem text="Share" (tap)="share()" android.systemIcon="ic_menu_share_holo_dark" ios.systemIcon="9" ios.position="right"></ActionItem> </ActionBar> <GridLayout rows="auto, *"> <!-- add-bar necessary since we moved the page up 20 over the status bar on iOS--> <GridLayout row="0" columns="*, auto" class="add-bar"> <TextField #groceryTextField [(ngModel)]="grocery" hint="Enter a grocery item" (returnPress)="add()" col="0"></TextField> <Image src="res://add" (tap)="add()" col="1"></Image> </GridLayout>... 来阻止Mongo在启动时执行自己的日志轮换,并且此开关要求--logappend中指定的路径存在。由于它存在于主机上,但是卷创建失败,容器无法看到日志文件。

要解决此问题,我已修改我的Mongo服务条目以调用--logpath部分中的脚本:

command

脚本看起来像这样:

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

在两个可能的用例中,这将按如下方式执行:

  • 如果mount工作(dev,live),它只会触摸一个文件(如果存在),如果没有则创建它(例如一个全新的环境),
  • 如果挂载不起作用(CircleCI),它将创建文件。

无论哪种方式,这都是一个很好的安全功能,可以防止Mongo爆炸。