Як заробити базу даних mongo за допомогою docker-compose?


79

Я намагаюся розповсюдити набір підключених програм, що працюють у декількох пов'язаних контейнерах, що включає базу даних mongo, яка потрібна для:

  • бути розподіленим, що містить деякі дані про насіння;
  • дозволити користувачам додавати додаткові дані.

В ідеалі дані також зберігатимуться у зв’язаному контейнері обсягу даних.

Я можу отримати дані в mongoконтейнер, використовуючи mongoбазовий екземпляр, який не монтує жодних томів (образ dockerhub: psychemedia/mongo_nomount- це, по суті, базовий файл mongo Dockerfile без VOLUME /data/dbоператора) та Dockerfileконфігурацію за рядками:

ADD . /files
WORKDIR /files
RUN mkdir -p /data/db && mongod --fork --logpath=/tmp/mongodb.log && sleep 20 && \
mongoimport  --db testdb --collection testcoll  --type csv --headerline --file ./testdata.csv  #&& mongod --shutdown

де ./testdata.csvзнаходиться в тому ж каталозі ( ./mongo-with-data), що і файл Docker.

Мій файл конфігурації docker-compose містить наступне:

mongo:
  #image: mongo
  build: ./mongo-with-data
  ports:
    - "27017:27017"
  #Ideally we should be able to mount this against a host directory
  #volumes:
  #  - ./db/mongo/:/data/db
  #volumes_from:
  #  - devmongodata

#devmongodata:
#    command: echo created
#    image: busybox
#    volumes: 
#       - /data/db

Кожного разу, коли я намагаюся встановити VOLUME, здається, що оригінальні насіннєві дані - які зберігаються /data/db- видаляються. Я думаю, коли підключений до /data/dbнього том замінює все, що є на даний момент.

Тим не менше, посібник користувача докера пропонує: Томи ініціалізуються при створенні контейнера. Якщо базове зображення контейнера містить дані в зазначеній точці монтування, чи наявні дані копіюються в новий том при ініціалізації тома ? Тож я очікував, що дані збережуться, якщо я розміщу команду VOLUME після команди висіву RUN?

То що я роблю не так?

Довгий погляд полягає в тому, що я хочу автоматизувати збірку декількох пов'язаних контейнерів, а потім розповсюдити Vagrantfileфайл YAML / docker-compose, який запускатиме набір пов'язаних програм, що включає попередньо засіяну mongoбазу даних із (частково заповненою ) постійний контейнер даних.


Я думаю, що я хочу зробити на етапі збірки, це встановити контейнер db на новий контейнер обсягу даних, щоб дані в каталозі db контейнера були поміщені в обсяг даних, а не змонтувати контейнер обсягу даних на контейнер db, який замінює дані, які я щойно імпортував.
psychemedia

Встановивши контейнер обсягу даних із початково засіяними даними, я можу знищити оригінальний контейнер бази даних, а потім просто підключити простий контейнер mongodb до контейнера обсягу даних для використання кінцевим користувачем. Суть оригінального запитання зараз полягає в наступному: який найпростіший спосіб створити та заповнити контейнер обсягу даних, до якого міг би підключитися контейнер mongod?
psychemedia

With Railsi usedocker-compose run container_name rake db:seed
albttx

Якщо використання docker-compose не є вимогою, ви можете створити похідне зображення mongo, яке конфігурує db, включаючи дані затравок, при ініціалізації. Це рішення добре працює для мене.
Стів Тарвер,

Відповіді:


107

Я роблю це за допомогою іншого контейнера докера, єдиною метою якого є засівання mongo, а потім вихід. Я підозрюю, що це та сама ідея, що і ebaxt , але коли я шукав відповідь на це, я просто хотів побачити швидкий і брудний, але прямий приклад. Тож ось мій:

docker-compose.yml

mongodb:
  image: mongo
  ports:
    - "27017:27017"

mongo-seed:
  build: ./mongo-seed
  links:
    - mongodb

# my webserver which uses mongo (not shown in example)
webserver:
  build: ./webserver
  ports:
    - "80:80"
  links:
    - mongodb

mongo-seed / Dockerfile

FROM mongo

COPY init.json /init.json
CMD mongoimport --host mongodb --db reach-engine --collection MyDummyCollection --type json --file /init.json --jsonArray

mongo-seed / init.json

[
  {
    "name": "Joe Smith",
    "email": "jsmith@gmail.com",
    "age": 40,
    "admin": false
  },
  {
    "name": "Jen Ford",
    "email": "jford@gmail.com",
    "age": 45,
    "admin": true
  }
]

1
Які плюси та мінуси використання зовнішнього докера для насіння?
Августин Рідінгер

4
Я вважаю за краще тримати речі окремо і просто, і я виявив, що зазвичай це надає мені найбільшу гнучкість ... Наприклад ... якщо я хочу щось змінити у своєму насіннєвому файлі, мені доведеться його створити знову. Якби моє насіння було таким самим зображенням, як мій запущений екземпляр mongo, я втратив би свої дані mongo через скидання. Очевидно, я міг би експортувати та імпортувати, але це більше роботи.
Джефф Фейрлі,

1
Чи траплялися вам випадки, коли ви кілька разів висівали свою БД на різні прогони?
Васиф

1
@Vasif, насправді я це бачив. Однак я так і не зрозумів, чому це відбувається. Мій насіннєвий файл навіть створює унікальне обмеження, яке повинно порушуватися внаслідок імпортування даних вдруге, але дані все одно надходять ... Це головний подряпин.
Джефф Фейрлі,

7
Каміло: Проблема може полягати в тому, що база даних у контейнері mongodb не запустилася повністю, коли запускається mongo-seed. Я б поставив "depend_on: mongodb" у конфігурації mongo-seed. Однак це буде чекати лише запуску контейнера mongodb, а не фактичної бази даних у ньому. Команда "restart: on-failure" у конфігурації mongo-seed дозволить спробувати ще раз, якщо база даних недоступна. Я бачив, як він намагався три-чотири рази, перш ніж база даних стане доступною.
k7n4n5t3w4rt

15

Я виявив корисним використовувати Docker Custom Images та використання томів, замість того, щоб створювати інший контейнер для висіву.

Структура файлу

.
├── docker-compose.yml
├── mongo
│   ├── data
│   ├── Dockerfile
│   └── init-db.d
│       └── seed.js

Кожне розташування файлу, згадане в Dockerfile/ docker-compose.yml, є відносно розташування файлуdocker-compose.yml

ДОКЕРФАЙЛ

FROM mongo:3.6

COPY ./init-db.d/seed.js /docker-entrypoint-initdb.d

docker-compose.yml

version: '3'

services:
  db:
    build: ./mongo
    restart: always
    volumes:
      - ./mongo/data:/data/db #Helps to store MongoDB data in `./mongo/data`
    environment:
      MONGO_INITDB_ROOT_USERNAME: {{USERNAME}}
      MONGO_INITDB_ROOT_PASSWORD: {{PWD}}
      MONGO_INITDB_DATABASE: {{DBNAME}}

seed.js

// Since Seeding in Mongo is done in alphabetical order... It's is important to keep
// file names alphabetically ordered, if multiple files are to be run.

db.test.drop();
db.test.insertMany([
  {
    _id: 1,
    name: 'Tensor',
    age: 6
  },
  {
    _id: 2,
    name: 'Flow',
    age: 10
  }
])

docker-entrypoint-initdb.dможна використовувати для створення різних користувачів та пов'язаних з адміністрацією mongodb матеріалів, просто створіть алфавітно впорядкований js-скриптcreateUser тощо.

Для отримання більш докладної інформації про те , як налаштувати службу MongoDB Docker, прочитайте це

Крім того, добре захищати свої паролі та імена користувачів від загальнодоступних, НЕ НАТИСНУЙТЕ облікові дані на загальнодоступному git , замість цього використовуйте Docker Secrets . Також прочитайте цей підручник із секретів

Зверніть увагу, для використання секретів не потрібно переходити в режим докер-рою . Композиція файлів також підтримує секрети. Перевірте це

Секрети також можна використовувати в службах MongoDB Docker


Чи не могли б ви уточнити , де ви берете dbв db.test.drop();?
while1 пройшов

1
@ while1pass Перевірте docs.mongodb.com/manual/tutorial/… . Ви можете створити власне dbпідключення або скористатися підключенням за замовчуванням, яке надається під час запуску сценарію (який, мабуть, є кореневим користувачем скрипту init тут).
phoenisx

5

Поточний відповідь , заснований на @Jeff Fairley відповідь і оновлюється в відповідно до нових Docker документи

docker-compose.yml

version: "3.5"

services:
  mongo:
    container_name: mongo_dev
    image: mongo:latest
    ports:
      - 27017:27017
    networks:
      - dev

  mongo_seed:
    container_name: mongo_seed
    build: .
    networks:
      - dev
    depends_on:
      - mongo

networks:
  dev:
    name: dev
    driver: bridge

Dockerfile

FROM mongo:latest
COPY elements.json /elements.json
CMD mongoimport --host mongo --db mendeleev --collection elements --drop --file /elements.json --jsonArray

Ймовірно, вам потрібно відновити поточні зображення.


2

Ось опис того, як ми використовуємо одноразові контейнери для очищення та насіння зображень https://blog.ardoq.com/dynamic-database-seeding-with-docker


2
Будь ласка, поділіться найрелевантнішими пунктами з публікації в блозі, а не просто розміщуйте посилання, це набагато корисніше.
Пер Лундберг

2

Варто подивитися на цю відповідь: https://stackoverflow.com/a/42917632/5209935

Основна ідея полягає в тому, що зображення stock mongo має спеціальну точку входу, яку ви можете перевантажити, щоб забезпечити сценарій, який створює базу даних.


1

Ви можете використовувати це зображення, яке забезпечує контейнер докера для багатьох завдань (імпорт, експорт, дамп)

Подивіться на приклад, використовуючи docker-compose


1

Ви можете використовувати зображення Mongo Seeding Docker .

Чому?

  • Зображення Docker готове до роботи
  • Ви не прив'язані до файлів JSON - також підтримуються файли JavaScript і TypeScript (включаючи додаткову перевірку моделі за допомогою TypeScript)

Приклад використання з Docker Compose:

version: '3'
services:
  database:
    image: 'mongo:3.4.10'
    ports:
    - '27017:27017'
  api:
    build: ./api/
    command: npm run dev
    volumes: 
    - ./api/src/:/app/src/
    ports:
    - '3000:3000'
    - '9229:9229'
    links:
    - database
    depends_on:
    - database
    - data_import
    environment: 
    - &dbName DB_NAME=dbname
    - &dbPort DB_PORT=27017 
    - &dbHost DB_HOST=database
  data_import:
    image: 'pkosiec/mongo-seeding:3.0.0'
    environment:
    - DROP_DATABASE=true
    - REPLACE_ID=true
    - *dbName
    - *dbPort
    - *dbHost
    volumes:
    - ./data-import/dev/:/data-import/dev/
    working_dir: /data-import/dev/data/
    links:
    - database
    depends_on:
    - database

Застереження: Я є автором цієї бібліотеки.


@psychemedia Я оновив приклад останньої версії Mongo Seeding. Щасливого посіву!
pkosiec

чи підтримує цей інструмент додавання індексів та інших функціональних можливостей чи лише документи? Я перевірив ваше репо та не побачив жодної згадки в документах чи прикладах цього.
PJH

@PJH Вибачте, я пропустив ваш коментар. Наразі
Mongo Seeding

0

Щоб відповісти на власне запитання:

  • простий файл YAML для створення простого монго-контейнера, пов'язаного з контейнером обсягу даних, запускається компонуванням докера Vagrant.
  • у Vagrantfile кодуйте за лініями:

config.vm.provision :shell, :inline => <<-SH docker exec -it -d vagrant_mongo_1 mongoimport --db a5 --collection roads --type csv --headerline --file /files/AADF-data-minor-roads.csv SH

імпортувати дані.

Упакуйте коробку.

Розподіліть коробку.

Для користувача - простий файл Vagrant для завантаження вікна та запуску простого скрипта YAML для складання докера, щоб запустити контейнери та встановити монго db на контейнер обсягу даних.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.