web-dev-qa-db-fra.com

Comment ensemencer une base de données mongo à l'aide de docker-compose?

J'essaie de distribuer un ensemble d'applications connectées s'exécutant dans plusieurs conteneurs liés, y compris une base de données mongo, nécessaire pour:

  • être distribué contenant des données de départ;
  • permettre aux utilisateurs d'ajouter des données supplémentaires.

Idéalement, les données seront également conservées dans un conteneur de volume de données lié.

Je peux obtenir les données dans le conteneur mongo à l'aide d'une instance de base mongo qui ne monte aucun volume (image dockerhub: psychemedia/mongo_nomount - il s'agit essentiellement du fichier Dockerfile de base sans instruction VOLUME /data/db) et d'une config Dockerfile suivant les lignes suivantes:

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 est dans le même répertoire (./mongo-with-data) que le fichier Docker.

Mon fichier de configuration docker-compose comprend les éléments suivants:

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

Chaque fois que j'essaie de monter un VOLUME, il semble que les données d'origine conservées - qui sont stockées dans /data/db - soient supprimées. J'imagine que lorsqu'un volume est monté sur /data/db, il remplace ce qui existe actuellement. 

Cela dit, le docker userguide suggère que: Les volumes sont initialisés lors de la création d’un conteneur. Si l’image de base du conteneur contient des données au point de montage spécifié, ces données existantes sont copiées dans le nouveau volume lors de l’initialisation du volume? Donc, je m'attendais à ce que les données persistent si je plaçais la commande VOLUME après la commande d'ensemencement RUN?

Alors qu'est-ce que je fais mal?

En résumé, je souhaite automatiser la création de plusieurs conteneurs liés, puis distribuer un fichier YAML Vagrantfile/docker-compose qui lancera un ensemble d’applications liées, qui inclut une base de données mongo préamorcée avec une -peuplé) conteneur de données persistantes.

47
psychemedia

Je le fais en utilisant un autre conteneur docker dont le seul but est de semer le mongo, puis de sortir. J'imagine que c'est la même idée que celle de ebaxt , mais lorsque je cherchais une réponse à cette question, je voulais simplement voir un exemple simple et rapide. Alors voici le mien:

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": "[email protected]",
    "age": 40,
    "admin": false
  },
  {
    "name": "Jen Ford",
    "email": "[email protected]",
    "age": 45,
    "admin": true
  }
]
73
Jeff Fairley

Voici un résumé de la façon dont nous utilisons des conteneurs jetables pour nettoyer et ensemencer des images https://ardoq.com/delightful-database-seeding-with-docker/

4
ebaxt

J'ai trouvé utile d'utiliser Docker Custom Images et d'utiliser des volumes, au lieu de créer un autre conteneur pour l'ensemencement.

Structure de fichier

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

Chaque emplacement de fichier mentionné dans Dockerfiledocker-compose.yml, EST RELATIF À L'EMPLACEMENT DE docker-compose.yml

_/_ DOCKERFILE

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 peut être utilisé pour créer différents utilisateurs et des éléments liés à l'administration mongodb, il suffit de créer un ordre alphabétique nommé js-script à createUser etc ...

Pour plus de détails sur la personnalisation du service MongoDB Docker, lisez this

En outre, il est bon de protéger vos mots de passe et noms d'utilisateur de Public, NE PAS envoyer les informations d'identification sur public git, utilisez plutôt Secrets de Docker . Lisez également ce tutoriel sur les secrets

Notez bien qu'il n'est pas nécessaire d'entrer en mode Docker-swarm pour utiliser des secrets. Compose Files supporte également les secrets. Vérifiez this

Les secrets peuvent également être utilisés dans MongoDB Docker Services

3
Subroto

Réponse actuelle basée sur @ Jeff Fairley answer et mise à jour en fonction des nouveaux documents 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

Besoin probable de reconstruire les images actuelles

1
while1pass

Vous pouvez utiliser image Mongo Seeding Docker .

Pourquoi?

  • Vous avez l'image de Docker prête à partir
  • Vous n'êtes pas lié aux fichiers JSON. Les fichiers JavaScript et TypeScript sont également pris en charge (y compris la validation de modèle facultative avec TypeScript).

Exemple d'utilisation avec 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

Disclaimer: Je suis l'auteur de cette bibliothèque.

1
pkosiec

Vous pouvez utiliser cette image qui fournit un conteneur de menu fixe pour de nombreux travaux (import, export, dump) 

Regardez l'exemple example using docker-compose 

0
bwnyasse

Pour répondre à ma propre question:

  • fichier YAML simple pour créer un conteneur mongo simple lié à un conteneur de volume de données, déclenché par docker Vagrant.
  • dans le fichier Vagrant, codez dans le sens suivant:

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

importer les données.

Emballez la boîte.

Distribuez la boîte.

Pour l'utilisateur, un simple fichier Vagrant pour charger la boîte et exécuter un simple script YAML à composition fixe pour démarrer les conteneurs et monter la base de données mongo sur le conteneur de volume de données.

0
psychemedia

Il convient de regarder cette réponse: https://stackoverflow.com/a/42917632/5209935

L'idée de base est que l'image stock mongo a un point d'entrée spécial que vous pouvez surcharger pour fournir un script qui initialise la base de données.

0
Matthew