Как создать образ Mongo Docker с коллекциями и данными по умолчанию?

Мне нужна поддержка для создания моего собственного образа докера mongo.

У меня есть список сценариев для создания и вставки данных в MongoDB, которые должны вызываться в моем Dockerfile для доставки образа докера с коллекциями и данными по умолчанию.

Вот как сейчас выглядит мой 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. Также я подключился к работающему контейнеру и получил 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

Может помочь:


person Felipe Plets    schedule 06.11.2015    source источник


Ответы (3)


Проблема заключалась в том, что информацию нельзя было сохранить на /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"]

Спасибо @yosifkit из docker-library / mongo Github проект для указания того, что объем будет хранить данные в результирующем изображении. Я пропустил это в документации.

person Felipe Plets    schedule 09.11.2015
comment
Я сам пытался в этом разобраться. Почему данные не сохраняются? - person Sergio; 19.11.2015
comment
Данные @Sergio не сохраняются в VOLUME, потому что они были добавлены после создания VOLUME, и поэтому они будут оставаться в этом состоянии до тех пор, пока контейнер не будет создан на основе изображения. Если вы добавите данные в каталог до создания тома, они будут сохранены. - person Felipe Plets; 19.11.2015
comment
Это было действительно важно. Убедитесь, что после изменения данных укажите ГРОМКОСТЬ. ЗАПУСТИТЬ mkdir -p / data / db ДОБАВИТЬ seedMongoDB.js. RUN $ MONGOD_START && mongo tembowms-dev --quiet seedMongoDB.js && mongod --shutdown VOLUME / data / db - person swateek; 18.02.2016

Во время сборки образа докера каждая команда сборки, такая как RUN, запускается в собственном контейнере докера, а затем, когда команда завершает работу, данные фиксируются как образ. Если вы запустите dockviz images --tree во время сборки, вы поймете идею.

В вашем случае mongod запустился и остановился задолго до того, как он вам понадобится. Вам нужно запустить mongo и все свои скрипты за один RUN шаг. Вы можете добиться этого, используя сценарий оболочки, который запускает mongod и вставляет ваши данные.

Ваш Dockerfile будет работать:

RUN mongo_create_insert.sh

Тогда mongo_create_insert.sh содержит все ваши шаги, зависящие от монго:

#!/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 в свой базовый образ и использую его для подготовки образов Docker с помощью одной команды RUN, вместо того, чтобы выполнять множество шагов RUN оболочки в файле Dockerfile (который в конечном итоге является просто прославленным сценарием оболочки). Вы теряете часть удобства кэширования сборки, но мы не зря перешли от подготовки с помощью сценариев оболочки.

person Matt    schedule 06.11.2015
comment
Спасибо @Matt, это было очень хорошее объяснение, и теперь я могу запустить скрипт. Несмотря на то, что он работает успешно, я все еще не вижу базу данных, созданную в моем работающем контейнере. Если я запускаю те же команды в работающем контейнере, я получаю базу данных и коллекции, созданные должным образом, но я не могу создать образ докера с базой данных, коллекциями и данными по умолчанию. Я дополню ответ новыми подробностями. - person Felipe Plets; 06.11.2015
comment
не должен ли этот сценарий также ждать запуска mongodb? - person matanster; 28.02.2016
comment
mongod не разветвляется, пока не будет готов принимать соединения. - person Matt; 02.03.2016

Согласно описанию образа на 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
person Siyu    schedule 07.02.2019