如何使用docker-compose播种mongo数据库?


77

我正在尝试分发在几个链接的容器中运行的一组连接的应用程序,这些容器包括一个mongo数据库,该数据库需要:

  • 分发包含一些种子数据;
  • 允许用户添加其他数据。

理想情况下,数据还将保存在链接的数据卷容器中。

我可以mongo使用mongo不装载任何卷的基本实例(dockerhub映像:psychemedia/mongo_nomount-本质上是不带该VOLUME /data/db语句的基本mongo Dockerfile )和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

其中与Dockerfile./testdata.csv位于同一目录(./mongo-with-data)中。

我的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它上时,它会替换当前存在的任何东西。

也就是说,docker用户指南建议:创建容器时将初始化卷。如果容器的基本映像在指定的安装点包含数据,则在卷初始化时将现有数据复制到新卷中?因此,如果我将VOLUME命令放在种子RUN命令之后,我希望数据能够持久保存吗?

那我在做什么错?

从长远来看,我想自动化几个链接容器的构建,然后分发一个Vagrantfile/ docker-compose的YAML文件,该文件将启动一组链接应用程序,其中包括一个mongo带有(部分预先填充)持久数据容器。


我猜我在构建阶段要执行的操作是将db容器安装到新的数据卷容器上,以便将db容器目录中的数据放置到数据卷中,而不是将数据卷容器安装到db容器上,这会覆盖我刚刚导入的数据。
psychemedia

在建立具有初始种子数据的数据卷容器之后,我可以销毁原始数据库容器,然后将简单的mongodb容器连接到数据卷容器以供最终用户使用。最初问题的核心是:构建和填充mongod容器可以连接到的数据量容器的最简单方法是什么?
psychemedia

Rails我一起使用docker-compose run container_name rake db:seed
albttx

如果不需要使用docker-compose,则可以创建派生的mongo映像,该映像在初始化时配置数据库(包括种子数据)。该解决方案对我来说效果很好。
史蒂夫·塔弗

Answers:


107

我使用另一个docker容器执行此操作,该容器的唯一目的是播种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
使用外部Docker进行播种的利弊是什么?
奥古斯丁·里丁格

4
我更喜欢使事情分开和简单,而且我发现通常这给我带来最大的灵活性……例如……如果我想更改种子文件中的某些内容,则需要再次构建它。如果我的种子与正在运行的mongo实例相同,则由于重置,我的mongo数据将丢失。显然,我可以导出和导入,但这还需要更多工作。
杰夫·菲利

1
您是否碰巧遇到过在不同的运行中多次播种数据库的问题?
Vasif

1
@Vasif,实际上我已经看到了。我从来没有弄清楚为什么会这样。我的种子文件甚至创建了一个唯一的约束,第二次导入的数据应该违反该约束,但是数据仍在输入中……这是一个令人头疼的问题。
杰夫·费尔利

7
卡米洛:问题可能是当mongo-seed启动时,mongodb容器中的数据库尚未完全启动。我会在mongo-seed配置中放入一个“ depends_on:mongodb”。但是,这只会等待mongodb容器启动,而不会等待其中的实际数据库。如果数据库不可用,mongo-seed配置上的“ restart:on-failure”命令将使其重试。我已经看到它在数据库可用之前尝试了三到四次。
k7n4n5t3w4rt

15

我发现使用Docker自定义映像和使用卷很有用,而不是创建另一个种子容器。

档案结构

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

Dockerfile/中提到的每个文件位置docker-compose.yml都相对于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可以用于创建不同的用户以及与mongodb管理相关的东西,只需将按字母顺序排序的名为js脚本的脚本createUser创建etc ...

有关如何自定义MongoDB Docker服务的更多详细信息,请阅读

此外,最好确保您的密码和用户名不受Public的影响,不要在public git上推送凭据,而应使用Docker Secrets。另请阅读本秘密教程

请注意,不必进入docker-swarm模式即可使用机密。撰写文件也支持秘密。检查一下

秘密也可以在MongoDB Docker Services中使用


你能否澄清其中你需要dbdb.test.drop();
while1pass

1
@ while1pass请检查docs.mongodb.com/manual/tutorial/…。您可以创建自己的db连接,也可以使用脚本运行时提供的默认连接(我猜这里是初始化脚本的根用户)。
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

您可能需要重建当前图像。




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仅支持文档,但可以随时在GitHub问题中提出新功能:-)
pkosiec

0

您可以使用此图像为许多作业(import,export,dump)提供docker容器

查看使用docker-compose的示例


0

要回答我自己的问题:

  • 简单的YAML文件来创建链接到数据量容器的简单mongo容器,由Vagrant docker compose启动。
  • 在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

导入数据。

包装盒子。

分发盒子。

对于用户而言,一个简单的Vagrantfile即可加载该框并运行一个简单的docker-compose YAML脚本来启动容器,并将mongo db挂载到数据卷容器中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.