시작할 때 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

@Valentin 물론 할 수 있지만 요점은 무엇입니까?
ReynierPM

내 요점은 변수를 사용하여 기본 DB, 관리자 사용자 / 암호 및 가능하면 dockerfile에서 auth 메소드를 설정 한 다음 compose 파일에 전달할 수 있다는 것입니다
Valentin

참고 : mongo-init 스크립트를 사용하는 솔루션을 사용하는 경우 mongo에 종속 된 컨테이너에 대해 restart : without-stopped (또는 no 이외의 항목)를 설정했는지 확인하십시오. 이는 이러한 컨테이너가 초기화하는 동안 처음 mongo에 연결하지 못하기 때문입니다 (depend_on 플래그를 사용하더라도). 자세한 내용은이 스레드를 참조하십시오. stackoverflow.com/questions/31746182/…
java-addict301 2010 년

답변:


98

공식 mongo이미지가 있다 기능을 포함하는 PR 병합 시작시 사용자와 데이터베이스를 만들 수 있습니다.

데이터베이스 초기화는 /data/db디렉토리에 아무것도 채워지지 않을 때 실행됩니다 .

관리자 사용자 설정

"루트"사용자 설정을 제어하는 ​​환경 변수는 다음과 같습니다.

  • 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 스크립트는 환경 변수가 존재할 때 이것을 추가하므로 명령 줄에서 사용할 필요가 없거나 사용할 수 없습니다 .

데이터베이스 초기화

이 이미지는 데이터베이스 초기화시 한 번 실행되는 /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 셸 자바 스크립트 파일입니다 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)
}

이것은 훌륭 합니다. 정의 에서 변수를 읽 set -e도록 entrypoint.sh지시 ENV하여 MySQL의 예제와 동일한 접근 방식을 사용할 수 있다고 가정합니다. 맞습니까? 귀하의 답변에 추가로, 누군가가 귀하의 제안과 유사한 작업을 다른 관점에서보고있는 것으로 보이는 이 PR을 발견 했습니다
ReynierPM

기본적으로 얻는 환경 변수입니다. set -e명령이 실패하면 전체 스크립트가 종료되므로 스크립트가 자동으로 실패하고 mongo를 시작할 수 없습니다.
Matt

모든 &&곳 에서 사용되는 모든 Dockerfile 빌드 스크립트와 유사합니다 .
Matt

그 몽고 PR은 훨씬 더 철저한 구현입니다! 그리고 docker-entrypoint-initdb.d디렉토리는 확장 가능하게 만듭니다. 그 가져 오기의 병합 희망
매트

합병 ( 여기 참조 )
ReynierPM

99

여기 docker-composejs스크립트 를 사용하여 또 다른 깨끗한 솔루션 입니다.

이 예에서는 두 파일 (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 폴더의 코드는 데이터베이스가 이전에 초기화 된 적이없는 경우에만 실행됩니다.


스 니펫의 모든 <> 값을 설정으로 바꿔야합니다.
Paul Wasilewski

6
mongo-init.js : ro는 무엇입니까?
Heril Muratovic

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
Paul Wasilewski

2
@GustavoSilva 나는 그것이 작동하고 있다고 확신합니다. 도 커가 파일을 작성하고 js 스크립트가 동일한 폴더에없는 것 같습니다. 아니면 창문에서 일하고 있습니까? 그런 다음 volumes옵션을 조정하고 mongo-init.js예를 들어 파일에 절대 경로를 추가하십시오 c:\docker\mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro.
Paul Wasilewski

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그렇지 않으면 스크립트가 testdb 에 대해 실행 됩니다. docker-entrypoint.sh 의 소스 코드를 확인하십시오 .


1
역할에 오타가 있습니까? db는 테스트 데이터베이스 여야합니까?
Winster

getSiblingDB가있는 두 번째 줄에 두 개의 주석이 있습니다. 첫째,이 줄없이 모든 것이 테스트에서 작동했습니다. 둘째, 이와 같이 db 변수를 덮어 쓰는 것은 잘못된 형태 인 것 같습니다. 전역 객체로 간주되고 덮어 쓰면 모든 것에 대한 컨텍스트가 변경되기 때문입니다.
Lazor

50

UPD 오늘의 피할 도커 떼, 비밀, 그리고 CONFIGS. 나는 그것을 실행하는 것 docker-compose.env파일. 자동 확장이 필요하지 않는 한. 그렇다면 아마도 k8s를 선택할 것입니다. 그리고 데이터베이스 암호, 루트 계정 여부 ... 외부 세계와 연결되지 않은 컨테이너에서 단일 데이터베이스를 실행할 때 정말 중요합니까? .. 당신이 그것에 대해 어떻게 생각하는지 알고 싶지만 스택 오버플로 이런 종류의 의사 소통에 적합하지 않을 것입니다.

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.sh구성 ( 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
나는 처음에 내 자신의 db를 만드는 방법을 찾는 데 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-yuri

@ 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당신의 몽고 인스턴스를 인증 활성화 자동으로 실행됩니다. 주어진 암호로 관리 데이터베이스를 갖게됩니다.


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

1
당신은 할 필요가 mongo admin --username ADMIN --password PASSWORT귀하의 몽고 인스턴스에 연결할 수 있습니다.
Philipp Schemel

1
작동하지 않습니다. "admin @ admin 사용자를 찾을 수 없습니다". 사용자가 자동으로 생성되지 않는 것 같습니다.
batjko

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

@TaraPrasadGurung이 문제가 발생했습니다. 이미 데이터베이스 용으로 볼륨이 생성되어 있음을 알았습니다. 새 사용자를 생성하려면 컨테이너에서이 볼륨을 삭제해야합니다.
Daniel S.

5

docker-compose.yml에서 사용자 이름과 비밀번호를 제거하려는 경우 Docker Secrets를 사용할 수 있습니다 . 여기에 내가 접근 한 방법이 있습니다.

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

내 비밀에 대해 file : 옵션을 사용 했지만 external : 을 사용할 수도 있고 떼에서 비밀을 사용할 수도 있습니다 .

비밀은 / var / run / secrets에있는 컨테이너의 모든 스크립트에서 사용할 수 있습니다.

Docker 문서에는 민감한 데이터 저장에 대해 언급되어 있습니다.

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

비밀을 사용하여 컨테이너가 런타임에 필요하지만 이미지 또는 소스 제어에 저장하지 않으려는 민감한 데이터를 관리 할 수 ​​있습니다.

사용자 이름 및 암호 TLS 인증서 및 키 SSH 키 데이터베이스 또는 내부 서버 이름과 같은 기타 중요한 데이터 일반 ​​문자열 또는 이진 콘텐츠 (최대 500kb 크기)


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.ymladmin 데이터베이스와 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.