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

How do I seed a mongo database using docker-compose?

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

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

我可以使用不装载任何卷的 mongo 基本实例将数据放入 mongo 容器(docker 集线器映像: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

其中 ./testdata.csv 与 Dockerfile 位于同一目录 (./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

每当我尝试装载卷时,似乎原始种子数据(存储在 /data/db 中)已被删除。我想当一个卷安装到 /data/db 时,它会替换当前存在的任何内容。

也就是说,docker userguide 建议:卷在创建容器时初始化。如果容器的基础镜像包含指定挂载点的数据,那么现有数据会在卷初始化时复制到新卷中?因此,如果我在播种 RUN 命令之后放置 VOLUME 命令,我希望数据能够持续存在?

那我做错了什么?

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

回答我自己的问题:

  • 简单的 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 数据库容器。

我使用另一个 docker 容器执行此操作,其唯一目的是播种 mongo,然后退出。我怀疑这与 ebaxt 的想法相同,但是当我在寻找答案时,我只是想看一个简单明了的示例。所以这是我的:

docker-compose.yml

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

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

# my webserver which uses mongo (not shown in example)
webserver:
  build: ./webserver
  ports:
    - "80:80"
  depends_on:
    - 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
  }
]

您可以使用这个 image 为许多作业(导入、导出、转储)提供 docker 容器

使用 docker-compose 查看 example

您可以使用 Mongo Seeding Docker image.

为什么?

  • 您已准备好 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

免责声明:我是这个库的作者。

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

文件结构

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

Every File location mentioned in Dockerfile/docker-compose.yml, is relative to location of 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 can be used for creating different users and mongodb administration related stuffs, just create an alphabetical ordered named js-script to createUser etc...

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

此外,最好保护您的密码和用户名免受 Public、不要将凭据推送到 public git,而是使用 Docker Secrets. Also read this Tutorial on Secrets

Do note, it is not necessary to go into docker-swarm mode to use secrets. Compose Files supports secrets as well. Check this

秘密也可以用在MongoDB Docker Services

当前答案基于@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

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

这是工作数据库种子 mongodb docker 使用下面的命令来为数据库做种子 Dockerfile

FROM mongo:3.6.21

COPY init.json /init.json

CMD mongoimport --uri mongodb://mongodb:27017/testdb --collection users --type json --file /init.json --jsonArray

docker-compose.yml

 version: "3.7"
 services:  
    mongodb:
        container_name: mongodb
        image: mongo:3.6.21
        environment: 
          - MONGO_INITDB_DATABASE=testdb
        volumes:
          - ./data:/data/db
        ports:
          - "27017:27017"
    
      mongo_seed:
        build: ./db
        depends_on:
          - mongodb