起動時にMongoDBコンテナ用のDBを作成するにはどうすればよいですか?


87

私はDockerを使用しており、PHP、MySQL、Apache、Redisのスタックがあります。今すぐMongoDBを追加する必要があるため、Dockerfileで最新バージョンとMongoDB Dockerhubのdocker-entrypoint.shファイルを確認していましたが、デフォルトのDB、管理者ユーザー/パスワード、場合によっては認証を設定する方法が見つかりませんでした。docker-compose.ymlファイルからのコンテナのメソッド。

MySQLでは、たとえば次のようにいくつかのENV変数を設定できます。

db:
    image: mysql:5.7
    env_file: .env
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}

これにより、DBとユーザー/パスワードがパスワードとして設定されrootます。

MongoDBで同じことを達成する方法はありますか?誰かが何らかの経験や回避策を持っていますか?


mysqlに基づいてコンテナーを作成し、必要に応じてセットアップして使用できますか?
バレンティン

@Valentinもちろんできますが、あなたのポイントは何ですか?
ReynierPM 2017年

私のポイントは、変数を使用してdockerfileにデフォルトのDB、管理者ユーザー/パスワード、場合によってはauthメソッドを設定し、それらを作成ファイルに渡すことができるということです
Valentin

注:mongo-initスクリプトを使用するソリューションのいずれかを使用する場合は、mongoに依存するコンテナーに対してrestart:unless-stopped(またはno以外の何か)を設定してください。これは、これらのコンテナーが初期化中に最初にmongoに接続できないためです(depends_onフラグを使用している場合でも)。詳細については、このスレッドを参照してくださいstackoverflow.com/questions/31746182/...
のjava-addict301

回答:


98

公式mongoイメージはしていた機能含めるようにPRを合併し、起動時にユーザーとデータベースを作成するために。

データベースの初期化は、/data/dbディレクトリに何も入力されていないときに実行されます。

管理者ユーザー設定

「root」ユーザー設定を制御するための環境変数は次のとおりです。

  • MONGO_INITDB_ROOT_USERNAME
  • MONGO_INITDB_ROOT_PASSWORD

docker run -d \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=password \
  mongod

--authdocker entrypoint.shスクリプトは環境変数が存在する場合にこれを追加するため、コマンドラインで使用する必要はありません/使用できません。

データベースの初期化

このイメージは、データベースの初期化時に1回実行される/docker-entrypoint-initdb.d/カスタムスクリプト.jsまたは.shセットアップスクリプトを展開するためのパスも提供します。.jsスクリプトはtest、デフォルトで、またはMONGO_INITDB_DATABASE環境で定義されている場合に実行されます。

COPY mysetup.sh /docker-entrypoint-initdb.d/

または

COPY mysetup.js /docker-entrypoint-initdb.d/

データを使用したコレクションのセットアップ、ロギング、およびエラーで終了する方法(結果チェック用)を示す単純な初期化mongoシェルjavascriptファイルcontainer

let error = true

let res = [
  db.container.drop(),
  db.container.createIndex({ myfield: 1 }, { unique: true }),
  db.container.createIndex({ thatfield: 1 }),
  db.container.createIndex({ thatfield: 1 }),
  db.container.insert({ myfield: 'hello', thatfield: 'testing' }),
  db.container.insert({ myfield: 'hello2', thatfield: 'testing' }),
  db.container.insert({ myfield: 'hello3', thatfield: 'testing' }),
  db.container.insert({ myfield: 'hello3', thatfield: 'testing' }),
  db.other.
]

printjson(res)

if (error) {
  print('Error, exiting')
  quit(1)
}

これは素晴らしいです。MySQLの例と同じアプローチを使用できるように、定義から変数を読み取るようにset -e指示していると思います。あなたの答えに加えて、私はこのPRを見つけました。明らかに、誰かがあなたの提案に似た何かに取り組んでおり、別の観点から来ていますentrypoint.shENV
ReynierPM 2017年

デフォルトで取得する環境変数。set -eコマンドが失敗するとスクリプト全体が終了するため、スクリプトがサイレントに失敗してmongoを起動することはできません。
マット

&&どこでも使用されているすべてのDockerfileビルドスクリプトと同様です。
マット

そのmongoPRは、はるかに徹底的な実装です。そしてdocker-entrypoint-initdb.dディレクトリはそれを拡張可能にします。getが合併することを願っています
Matt

統合されました(ここを参照)
ReynierPM 2017年

99

ここではdocker-compose、とjsスクリプトを使用した別のよりクリーンなソリューションを紹介します。

この例では、両方のファイル(docker-compose.ymlとmongo-init.js)が同じフォルダーにあることを前提としています。

docker-compose.yml

version: '3.7'

services:
    mongodb:
        image: mongo:latest
        container_name: mongodb
        restart: always
        environment:
            MONGO_INITDB_ROOT_USERNAME: <admin-user>
            MONGO_INITDB_ROOT_PASSWORD: <admin-password>
            MONGO_INITDB_DATABASE: <database to create>
        ports:
            - 27017:27017
        volumes:
            - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro

mongo-init.js

db.createUser(
        {
            user: "<user for database which shall be created>",
            pwd: "<password of user>",
            roles: [
                {
                    role: "readWrite",
                    db: "<database to create>"
                }
            ]
        }
);

次に、次のdocker-composeコマンドを実行してサービスを開始します。

docker-compose up --build -d mongodb 

:docker-entrypoint-init.dフォルダー内のコードは、データベースが以前に初期化されたことがない場合にのみ実行されます。


スニペット内のすべての<>値を設定に置き換える必要があります。
PaulWasilewski19年

6
mongo-init.js:roとは何ですか?
HerilMuratovic19年

11
@HerilMuratovic、volumesエントリ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:roはローカルファイル./mongo-init.js/docker-entrypoint-initdb.d/mongo-init.js読み取り専用としてコンテナパスにリンクしていますro。あなたは、使用する方法についての詳細を見つけることができますボリュームを:ここdocs.docker.com/storage/volumes
ポールWasilewski

2
@GustavoSilva私はそれが機能していると絶対に確信しています。dockercomposeファイルとjsスクリプトが同じフォルダーにないようです。それとも、Windowsで作業していますか?次に、volumesオプションを調整して、mongo-init.jsたとえばファイルに絶対パスを追加してくださいc:\docker\mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
PaulWasilewski19年

1
dbとは何ですか?コードは私には不完全に見えます、それはマングースの接続ですか?
andrevenancio

55

これadmin-userは、パスワード、追加のデータベース(test-database)、およびtest-userそのデータベースでユーザーを作成する実用的なソリューションです。

Dockerfile:

FROM mongo:4.0.3

ENV MONGO_INITDB_ROOT_USERNAME admin-user
ENV MONGO_INITDB_ROOT_PASSWORD admin-password
ENV MONGO_INITDB_DATABASE admin

ADD mongo-init.js /docker-entrypoint-initdb.d/

mongo-init.js:

db.auth('admin-user', 'admin-password')

db = db.getSiblingDB('test-database')

db.createUser({
  user: 'test-user',
  pwd: 'test-password',
  roles: [
    {
      role: 'root',
      db: 'test-database',
    },
  ],
});

トリッキーな部分は、*。jsファイルが認証されずに実行されたことを理解することでした。このソリューションは、スクリプトをデータベースadmin-user内のとして認証しadminます。MONGO_INITDB_DATABASE adminが不可欠です。そうでない場合、スクリプトはtestデータベースに対して実行されます。docker-entrypoint.shのソースコードを確認してください。


1
役割にタイプミスはありますか?dbはテストデータベースである必要がありますか?
ウィンスター

getSiblingDBがある2行目の2つのコメント。まず、この行がなくても、すべてが私のテストで機能しました。次に、db変数をこのように上書きするのは悪い形式のようです。これは、グローバルオブジェクトと見なされ、上書きするとすべてのコンテキストが変更されるためです。
Lazor

50

UPD今日、私はDocker Swarm、シークレット、および構成を避けています。私はそれを実行しdocker-compose.envファイルでます。自動スケーリングが必要ない限り。もしそうなら、私はおそらくk8sを選ぶでしょう。そして、データベースのパスワード、rootアカウントかどうか...外の世界に接続されていないコンテナで単一のデータベースを実行している場合、それらは本当に重要ですか?..あなたがそれについてどう思うか知りたいのですが、Stack Overflowこの種の通信にはおそらくあまり適していません。

MongoイメージはMONGO_INITDB_DATABASE 変数の影響を受ける可能性がありますが、データベースは作成されません。この変数は、/docker-entrypoint-initdb.d/* スクリプトの実行時に現在のデータベースを決定します。あなたがいるのでできませんモンゴで実行されるスクリプト内の環境変数を使用して、私は、シェルスクリプトと一緒に行きました:

docker-swarm.yml

version: '3.1'

secrets:
  mongo-root-passwd:
    file: mongo-root-passwd
  mongo-user-passwd:
    file: mongo-user-passwd

services:
  mongo:
    image: mongo:3.2
    environment:
      MONGO_INITDB_ROOT_USERNAME: $MONGO_ROOT_USER
      MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo-root-passwd
      MONGO_INITDB_USERNAME: $MONGO_USER
      MONGO_INITDB_PASSWORD_FILE: /run/secrets/mongo-user-passwd
      MONGO_INITDB_DATABASE: $MONGO_DB
    volumes:
      - ./init-mongo.sh:/docker-entrypoint-initdb.d/init-mongo.sh
    secrets:
      - mongo-root-passwd
      - mongo-user-passwd

init-mongo.sh

mongo -- "$MONGO_INITDB_DATABASE" <<EOF
    var rootUser = '$MONGO_INITDB_ROOT_USERNAME';
    var rootPassword = '$MONGO_INITDB_ROOT_PASSWORD';
    var admin = db.getSiblingDB('admin');
    admin.auth(rootUser, rootPassword);

    var user = '$MONGO_INITDB_USERNAME';
    var passwd = '$(cat "$MONGO_INITDB_PASSWORD_FILE")';
    db.createUser({user: user, pwd: passwd, roles: ["readWrite"]});
EOF

または、init-mongo.shconfigs(docker config create)に保存して、次のコマンドでマウントすることもできます。

configs:
    init-mongo.sh:
        external: true
...
services:
    mongo:
        ...
        configs:
            - source: init-mongo.sh
              target: /docker-entrypoint-initdb.d/init-mongo.sh

また、シークレットをファイルに保存することはできません。

この問題に関するいくつか要点


11
最初に自分のデータベースを作成する方法を探すのに3時間かかりました。ドキュメントには、.jsまたは.shファイル内で認証する必要があるとは記載されていません。インターネット上の例はまったく完全ではありません。あなたは文字通り彼らの.shスクリプトを掘り下げて、このようなものを書く方法を結論付ける必要があります。コンテナの起動時に「空のデータベースを作成する」方法。これを簡素化するには、PRを作成する必要があります。あなたが私に尋ねれば少しクレイジー。
クールな

1
私はこの問題の解決策を探すのに何時間も費やしました。これは私を救った。ありがとうございました。
NaijaProgrammer

$(cat "$MONGO_INITDB_ROOT_PASSWORD_FILE")$MONGO_INITDB_ROOT_PASSWORDMongoイメージはすでに私たちの秘密を扱っているので、最近に置き換える必要があります。hub.docker.com/_/mongo
FlippingBinary

3.2でもそうだった。私はおそらく気づかなかったでしょう。
X-ゆり

@ x-yuriファイルをdocker-entrypoint-initdb.dにコピーしてそこで自動的に実行させるのではなく、init-mongo.shの構成を使用する利点は何ですか?
Lazor

13

を使用した認証でMongoDBを構成する方法を探している人のためにdocker-compose、環境変数を使用した構成例を次に示します。

version: "3.3"

services:

  db:
      image: mongo
      environment:
        - MONGO_INITDB_ROOT_USERNAME=admin
        - MONGO_INITDB_ROOT_PASSWORD=<YOUR_PASSWORD>
      ports:
        - "27017:27017"

実行している場合はdocker-compose up認証を有効にしてごMongoのインスタンスが自動的に実行されます。指定されたパスワードの管理データベースが作成されます。


3
mongo --username admin --password password --host localhost --port 27017ログにユーザーが表示され、dbが正常に作成されたため、接続できません。エラー:$ mongo --username admin --password password --host localhost --port 27017 MongoDB shell version v3.4.10 connecting to: mongodb://localhost:27017/ MongoDB server version: 3.6.5 WARNING: shell and server versions do not match 2018-06-07T13:05:09.022+0000 E QUERY [thread1] Error: Authentication failed. : DB.prototype._authOrThrow@src/mongo/shell/db.js:1461:20 @(auth):6:1 @(auth):1:2 exception: login failed
Tara Prasad Gurung 2018年

1
mongo admin --username ADMIN --password PASSWORTmongoインスタンスに接続する必要があります。
フィリップスキームル2018年

1
これを機能させることができません。「ユーザーadmin @ adminが見つかりませんでした」。ユーザーが自動的に作成されないようですか?
batjko

mongodb://root:example@localhost/my-db?authSource=admin
FDISK

@TaraPrasadGurungこの問題が発生しました。データベース用にすでにボリュームが作成されていることに気付きました。新しいユーザーを作成するには、コンテナー用にこのボリュームを削除する必要があります。
ダニエル

5

docker-compose.ymlからユーザー名とパスワードを削除したい場合は、Dockerシークレットを使用できます。これが私がアプローチした方法です。

version: '3.6'

services:
  db:
    image: mongo:3
    container_name: mycontainer
  secrets:
    - MONGO_INITDB_ROOT_USERNAME
    - MONGO_INITDB_ROOT_PASSWORD
  environment:
    - MONGO_INITDB_ROOT_USERNAME_FILE=/var/run/secrets/MONGO_INITDB_ROOT_USERNAME
    - MONGO_INITDB_ROOT_PASSWORD_FILE=/var/run/secrets/MONGO_INITDB_ROOT_PASSWORD
secrets:
  MONGO_INITDB_ROOT_USERNAME:
    file:  secrets/${NODE_ENV}_mongo_root_username.txt
  MONGO_INITDB_ROOT_PASSWORD:
    file:  secrets/${NODE_ENV}_mongo_root_password.txt

私が使用しています。ファイル、あなたも使用することができますが、私の秘密のためのオプションが外部:そして群れに秘密を使用しています。

シークレットは、/ var / run / secretsにあるコンテナ内のすべてのスクリプトで利用できます。

Dockerのドキュメントには、機密データの保存について書かれています...

https://docs.docker.com/engine/swarm/secrets/

シークレットを使用して、コンテナが実行時に必要とする機密データを管理できますが、次のように、イメージまたはソース管理に保存する必要はありません。

ユーザー名とパスワードTLS証明書とキーSSHキーデータベースや内部サーバーの名前などの他の重要なデータ一般的な文字列またはバイナリコンテンツ(最大500 kbのサイズ)


4

この.envファイルを考えると:

DB_NAME=foo
DB_USER=bar
DB_PASSWORD=baz

そしてこのmongo-init.shファイル:

mongo --eval "db.auth('$MONGO_INITDB_ROOT_USERNAME', '$MONGO_INITDB_ROOT_PASSWORD'); db = db.getSiblingDB('$DB_NAME'); db.createUser({ user: '$DB_USER', pwd: '$DB_PASSWORD', roles: [{ role: 'readWrite', db: '$DB_NAME' }] });"

これdocker-compose.ymlにより、adminデータベースとadminユーザーが作成され、adminユーザーとして認証されてから、実際のデータベースが作成され、実際のユーザーが追加されます。

version: '3'

services:
#  app:
#    build: .
#    env_file: .env
#    environment:
#      DB_HOST: 'mongodb://mongodb'

  mongodb:
    image: mongo:4
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin-user
      MONGO_INITDB_ROOT_PASSWORD: admin-password
      DB_NAME: $DB_NAME
      DB_USER: $DB_USER
      DB_PASSWORD: $DB_PASSWORD
    ports:
      - 27017:27017
    volumes:
      - db-data:/data/db
      - ./mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh

volumes:
  db-data:
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.