【问题标题】:How to create a Mongo Docker Image with default collections and data?如何使用默认集合和数据创建 Mongo Docker 映像?
【发布时间】:2015-11-06 02:32:33
【问题描述】:

我在这里需要支持来构建我自己的 mongo docker 映像。

我有一个脚本列表,用于创建数据并将数据插入 MongoDB,这些脚本应在我的 Dockerfile 中调用,以提供具有默认集合和数据的 docker 映像。

这是我的 Dockerfile 目前的样子:

FROM mongo:latest

RUN mkdir -p /data/scripts

COPY . /data/scripts

RUN mongod --fork --logpath /var/log/mongodb.log --dbpath /data/db/

RUN FILES=scripts/*-create.js
RUN for f in $FILES; do mongo mydb $f; done

RUN FILES=scripts/*-insert.js
RUN for f in $FILES; do mongo mydb $f; done

RUN mongod --shutdown

我尝试了不同的选项来启动和停止 mongod,但总是有一个失败,当前脚本引发以下错误:

There doesn't seem to be a server running with dbpath: /data/db

更新

@Matt 回答后,我可以成功运行命令链,但仍然看不到我的数据库(称为 my-db)、集合和数据。

当前的 Dockerfile:

FROM mongo:latest

RUN mkdir -p /data/db/scripts

COPY . /data/db

RUN mongod --fork --logpath /var/log/mongodb.log --dbpath /data/db \
    && CREATE_FILES=/data/db/scripts/*-create.js \
    && for f in $CREATE_FILES; do mongo 127.0.0.1:27017 $f; done \
    && INSERT_FILES=/data/db/scripts/*-insert.js \
    && for f in $INSERT_FILES; do mongo 127.0.0.1:27017 $f; done \
    && mongod --shutdown 

docker build 命令的输出:

Sending build context to Docker daemon 10.24 kB
Step 1 : FROM mongo:latest
 ---> c08c92f4cb13
Step 2 : RUN mkdir -p /data/db/scripts
 ---> Running in a7088943bb57
 ---> 373c7319927d
Removing intermediate container a7088943bb57
Step 3 : COPY . /data/db
 ---> 8fa84884edb7
Removing intermediate container ae43e2c24fee
Step 4 : RUN mongod --fork --logpath /var/log/mongodb.log --dbpath /data/db     && CREATE_FILES=/data/db/scripts/*-create.js    && for f in $CREATE_FILES; do mongo 127.0.0.1:27017 $f; done    && INSERT_FILES=/data/db/scripts/*-insert.js    && for f in $INSERT_FILES; do mongo 127.0.0.1:27017 $f; done    && mongod --shutdown
 ---> Running in 33970b6865ee
about to fork child process, waiting until server is ready for connections.
forked process: 10
child process started successfully, parent exiting
MongoDB shell version: 3.0.7
connecting to: 127.0.0.1:27017/test
MongoDB shell version: 3.0.7
connecting to: 127.0.0.1:27017/test
killing process with pid: 10
 ---> 8451e43b7749
Removing intermediate container 33970b6865ee
Successfully built 8451e43b7749

但正如我所说,我仍然无法使用 mongo shell 查看数据库、集合和数据库中的数据。 我还连接到正在运行的容器并获得了 mongodb.log:

2015-11-06T16:15:14.562+0000 I JOURNAL  [initandlisten] journal dir=/data/db/journal
2015-11-06T16:15:14.562+0000 I JOURNAL  [initandlisten] recover : no journal files present, no recovery needed
2015-11-06T16:15:14.698+0000 I JOURNAL  [initandlisten] preallocateIsFaster=true 2.36
2015-11-06T16:15:14.746+0000 I JOURNAL  [durability] Durability thread started
2015-11-06T16:15:14.746+0000 I JOURNAL  [journal writer] Journal writer thread started
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] MongoDB starting : pid=10 port=27017 dbpath=/data/db 64-bit host=9c05d483673a
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] 
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] 
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] 
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] 
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] db version v3.0.7
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] git version: 6ce7cbe8c6b899552dadd907604559806aa2e9bd
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] build info: Linux ip-10-183-78-195 3.2.0-4-amd64 #1 SMP Debian 3.2.46-1 x86_64 BOOST_LIB_VERSION=1_49
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] allocator: tcmalloc
2015-11-06T16:15:14.747+0000 I CONTROL  [initandlisten] options: { processManagement: { fork: true }, storage: { dbPath: "/data/db" }, systemLog: { destination: "file", path: "/var/log/mongodb.log" } }
2015-11-06T16:15:14.748+0000 I INDEX    [initandlisten] allocating new ns file /data/db/local.ns, filling with zeroes...
2015-11-06T16:15:14.802+0000 I STORAGE  [FileAllocator] allocating new datafile /data/db/local.0, filling with zeroes...
2015-11-06T16:15:14.802+0000 I STORAGE  [FileAllocator] creating directory /data/db/_tmp
2015-11-06T16:15:14.804+0000 I STORAGE  [FileAllocator] done allocating datafile /data/db/local.0, size: 64MB,  took 0 secs
2015-11-06T16:15:14.807+0000 I NETWORK  [initandlisten] waiting for connections on port 27017
2015-11-06T16:15:14.830+0000 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:49641 #1 (1 connection now open)
2015-11-06T16:15:14.832+0000 I INDEX    [conn1] allocating new ns file /data/db/my-db.ns, filling with zeroes...
2015-11-06T16:15:14.897+0000 I STORAGE  [FileAllocator] allocating new datafile /data/db/my-db.0, filling with zeroes...
2015-11-06T16:15:14.898+0000 I STORAGE  [FileAllocator] done allocating datafile /data/db/my-db.0, size: 64MB,  took 0 secs
2015-11-06T16:15:14.904+0000 I NETWORK  [conn1] end connection 127.0.0.1:49641 (0 connections now open)
2015-11-06T16:15:14.945+0000 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:49642 #2 (1 connection now open)
2015-11-06T16:15:14.958+0000 I NETWORK  [conn2] end connection 127.0.0.1:49642 (0 connections now open)
2015-11-06T16:15:14.982+0000 I CONTROL  [signalProcessingThread] got signal 15 (Terminated), will terminate after current cmd ends
2015-11-06T16:15:14.982+0000 I CONTROL  [signalProcessingThread] now exiting
2015-11-06T16:15:14.982+0000 I NETWORK  [signalProcessingThread] shutdown: going to close listening sockets...
2015-11-06T16:15:14.982+0000 I NETWORK  [signalProcessingThread] closing listening socket: 6
2015-11-06T16:15:14.982+0000 I NETWORK  [signalProcessingThread] closing listening socket: 7
2015-11-06T16:15:14.982+0000 I NETWORK  [signalProcessingThread] removing socket file: /tmp/mongodb-27017.sock
2015-11-06T16:15:14.982+0000 I NETWORK  [signalProcessingThread] shutdown: going to flush diaglog...
2015-11-06T16:15:14.982+0000 I NETWORK  [signalProcessingThread] shutdown: going to close sockets...
2015-11-06T16:15:14.982+0000 I STORAGE  [signalProcessingThread] shutdown: waiting for fs preallocator...
2015-11-06T16:15:14.982+0000 I STORAGE  [signalProcessingThread] shutdown: final commit...
2015-11-06T16:15:15.008+0000 I JOURNAL  [signalProcessingThread] journalCleanup...
2015-11-06T16:15:15.008+0000 I JOURNAL  [signalProcessingThread] removeJournalFiles
2015-11-06T16:15:15.009+0000 I JOURNAL  [signalProcessingThread] Terminating durability thread ...
2015-11-06T16:15:15.088+0000 I JOURNAL  [journal writer] Journal writer thread stopped
2015-11-06T16:15:15.088+0000 I JOURNAL  [durability] Durability thread stopped
2015-11-06T16:15:15.088+0000 I STORAGE  [signalProcessingThread] shutdown: closing all files...
2015-11-06T16:15:15.090+0000 I STORAGE  [signalProcessingThread] closeAllFiles() finished
2015-11-06T16:15:15.090+0000 I STORAGE  [signalProcessingThread] shutdown: removing fs lock...
2015-11-06T16:15:15.090+0000 I CONTROL  [signalProcessingThread] dbexit:  rc: 0

我还检查了文件夹 /data/db 的内容:

root@fbaf17233182:/data/db# ls -al
total 16
drwxr-xr-x 3 mongodb mongodb 4096 Nov  6 16:15 .
drwxr-xr-x 4 root    root    4096 Nov  6 16:15 ..
drwxr-xr-x 2 root    root    4096 Nov  5 18:55 scripts

可能会有所帮助:

【问题讨论】:

    标签: mongodb docker dockerfile


    【解决方案1】:

    问题是信息无法保存在/db/data,所以我创建了一个解决方案来创建我自己的数据目录。

    # Parent Dockerfile https://github.com/docker-library/mongo/blob/982328582c74dd2f0a9c8c77b84006f291f974c3/3.0/Dockerfile
    FROM mongo:latest
    
    # Modify child mongo to use /data/db2 as dbpath (because /data/db wont persist the build)
    RUN mkdir -p /data/db2 \
        && echo "dbpath = /data/db2" > /etc/mongodb.conf \
        && chown -R mongodb:mongodb /data/db2
    
    COPY . /data/db2
    
    RUN mongod --fork --logpath /var/log/mongodb.log --dbpath /data/db2 --smallfiles \
        && CREATE_FILES=/data/db2/scripts/*-create.js \
        && for f in $CREATE_FILES; do mongo 127.0.0.1:27017 $f; done \
        && INSERT_FILES=/data/db2/scripts/*-insert.js \
        && for f in $INSERT_FILES; do mongo 127.0.0.1:27017 $f; done \
        && mongod --dbpath /data/db2 --shutdown \
        && chown -R mongodb /data/db2
    
    # Make the new dir a VOLUME to persists it 
    VOLUME /data/db2
    
    CMD ["mongod", "--config", "/etc/mongodb.conf", "--smallfiles"]
    

    感谢来自docker-library/mongo Github 项目的@yosifkit 指出该卷会将数据存储在结果图像中。我在文档中错过了这一点。

    【讨论】:

    • 我自己一直在尝试解决这个问题。为什么数据不持久?
    • @Sergio 数据不会保留在 VOLUME 中,因为它是在创建 VOLUME 之后添加的,因此它将保持该状态,直到基于映像创建容器。如果您在创建卷之前在目录中添加数据,它将被持久化。
    • 这真的很重要。确保在修改数据后指定 VOLUME。运行 mkdir -p /data/db 添加种子MongoDB.js 。 RUN $MONGOD_START && mongo tembowms-dev --quiet seedMongoDB.js && mongod --shutdown VOLUME /data/db
    【解决方案2】:

    在 docker 镜像构建期间,每个构建命令(如 RUN)都会在其自己的 docker 容器中启动,然后在命令完成时将数据作为镜像提交。如果您在构建时运行dockviz images --tree,您就会明白这一点。

    在您的情况下,mongod 在您需要它之前很久就已经开始和停止了。您需要在一个 RUN 步骤中启动 mongo 并运行所有脚本。您可以通过使用启动 mongod 并插入数据的 shell 脚本来实现。

    您的Dockerfile 将运行:

    RUN mongo_create_insert.sh
    

    然后mongo_create_insert.sh 包含所有依赖于 mongo 的步骤:

    #!/usr/bin/env bash
    
    mongod --fork --logpath /var/log/mongodb.log --dbpath /data/db/
    
    FILES=scripts/*-create.js
    for f in $FILES; do mongo mydb $f; done
    
    FILES=scripts/*-insert.js
    for f in $FILES; do mongo mydb $f; done
    
    mongod --shutdown
    

    作为旁注,我倾向于在我的基础镜像中安装 Ansible,并使用它在单个 RUN 命令中配置 Docker 镜像,而不是在 Dockerfile 中执行大量 shell RUN 步骤(这只是结束)。您失去了一些构建缓存的好处,但出于某种原因,我们已经不再使用 shell 脚本进行配置。

    【讨论】:

    • 感谢@Matt,这是一个非常好的解释,现在我可以运行脚本了。虽然它运行成功,但我仍然看不到在我正在运行的容器中创建的数据库。如果我在正在运行的容器上运行相同的命令,我会得到按预期创建的 db 和集合,但我无法创建具有默认数据库、集合和数据的 docker 映像。我会用新的细节更新答案。
    • 这个脚本不应该也等mongodb启动吗?
    • mongod 在准备好接受连接之前不会分叉。
    【解决方案3】:

    根据DockerHub上对镜像的描述,有一个更简洁更简单的解决方案。

    当一个容器第一次启动时,它会执行文件 带有扩展名 .sh 和 .js 在 /docker-entrypoint-initdb.d。文件将按字母顺序执行 命令。 .js 文件将由 mongo 使用数据库执行 由 MONGO_INITDB_DATABASE 变量指定(如果存在),或 否则测试。您也可以在 .js 脚本中切换数据库。

    首先,Dockerfile很简单

    FROM mongo:4
    COPY setup.sh /docker-entrypoint-initdb.d/
    COPY scripts /
    

    然后,在setup.sh 中,添加您的用户/集合创建脚本,例如

    mongo=( mongo --host 127.0.0.1 --port 27017 --quiet )
    mongo+=(
        --username="$MONGO_INITDB_ROOT_USERNAME"
        --password="$MONGO_INITDB_ROOT_PASSWORD"
        --authenticationDatabase="$rootAuthDatabase"
    )
    
    CREATE_FILES=/scripts/*-create.js 
    for f in $CREATE_FILES; do "${mongo[@]}" "$MONGO_INITDB_DATABASE" $f; done 
    
    INSERT_FILES=/scripts/*-insert.js 
    for f in $INSERT_FILES; do "${mongo[@]}" "$MONGO_INITDB_DATABASE" $f; done
    

    【讨论】:

      猜你喜欢
      • 2018-02-04
      • 2019-05-19
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 2015-08-03
      • 2015-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多