Docker compose mongo: 覆盖 entrypoint

huangapple go评论68阅读模式
英文:

Docker compose mongo: Overriding entrypoint

问题

我正在尝试使用Docker Compose设置带有副本集的MongoDB:

services:
  mongo1:
    image: mongo:6
    container_name: mongo-rs-primary
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password
      MONGO_INITDB_DATABASE: admin
    volumes:
      - ./_docker/volumes/mongo1:/data/db
      - ./_docker/mongo-rs-key:/data/mongo-rs-key
    ports:
      - 27017:27017
    entrypoint:
      - bash
      - -c
      - |
        chmod 400 /data/mongo-rs-key
        chown 999:999 /data/mongo-rs-key
        exec docker-entrypoint.sh $$0        
    command: --replSet rs0 --keyFile /data/mongo-rs-key --port 27017

  mongo2:
    image: mongo:6
    container_name: mongo-rs-replica1
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password
      MONGO_INITDB_DATABASE: admin
    volumes:
      - ./_docker/volumes/mongo2:/data/db
      - ./_docker/mongo-rs-key:/data/mongo-rs-key
    ports:
      - 27018:27018
    entrypoint:
      - bash
      - -c
      - |
        chmod 400 /data/mongo-rs-key
        chown 999:999 /data/mongo-rs-key
        exec docker-entrypoint.sh $$0        
    command: --replSet rs0 --keyFile /data/mongo-rs-key --port 27018

  mongo3:
    image: mongo:6
    container_name: mongo-rs-replica2
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password
      MONGO_INITDB_DATABASE: admin
    volumes:
      - ./_docker/volumes/mongo3:/data/db
      - ./_docker/mongo-rs-key:/data/mongo-rs-key
    ports:
      - 27019:27019
    entrypoint:
      - bash
      - -c
      - |
        chmod 400 /data/mongo-rs-key
        chown 999:999 /data/mongo-rs-key
        exec docker-entrypoint.sh $$0        
    command: --replSet rs0 --keyFile /data/mongo-rs-key --port 27019

请注意,我需要覆盖安全密钥文件的所有权,我在网上找到了这种方法,但奇怪的是现在我的副本集名称是--auth而不是rs0?我怀疑是因为exec docker-entrypoint.sh $$0,但是出了什么问题?我从某个地方复制了它,似乎在--replSet中使用了--auth而不是rs0

英文:

I am trying to setup a MongoDB with replicaset with Docker Compose:

services:
  mongo1:
    image: mongo:6
    container_name: mongo-rs-primary
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password
      MONGO_INITDB_DATABASE: admin
    volumes:
      - ./_docker/volumes/mongo1:/data/db
      - ./_docker/mongo-rs-key:/data/mongo-rs-key
    ports:
      - 27017:27017
    entrypoint:
      - bash
      - -c
      - |
        chmod 400 /data/mongo-rs-key
        chown 999:999 /data/mongo-rs-key
        exec docker-entrypoint.sh $$0
    command: --replSet rs0 --keyFile /data/mongo-rs-key --port 27017

  mongo2:
    image: mongo:6
    container_name: mongo-rs-replica1
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password
      MONGO_INITDB_DATABASE: admin
    volumes:
      - ./_docker/volumes/mongo2:/data/db
      - ./_docker/mongo-rs-key:/data/mongo-rs-key
    ports:
      - 27018:27018
    entrypoint:
      - bash
      - -c
      - |
        chmod 400 /data/mongo-rs-key
        chown 999:999 /data/mongo-rs-key
        exec docker-entrypoint.sh $$0
    command: --replSet rs0 --keyFile /data/mongo-rs-key --port 27018

  mongo3:
    image: mongo:6
    container_name: mongo-rs-replica2
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password
      MONGO_INITDB_DATABASE: admin
    volumes:
      - ./_docker/volumes/mongo3:/data/db
      - ./_docker/mongo-rs-key:/data/mongo-rs-key
    ports:
      - 27019:27019
    entrypoint:
      - bash
      - -c
      - |
        chmod 400 /data/mongo-rs-key
        chown 999:999 /data/mongo-rs-key
        exec docker-entrypoint.sh $$0
    command: --replSet rs0 --keyFile /data/mongo-rs-key --port 27019

Note that I needed to override the ownership of the security key file and I found online this is one way to do it, however, the weird thing is now my replica set name is --auth and not rs0? I suspect its because of exec docker-entrypoint.sh $$0 but whats wrong? I copied that from somewhere, seems like its using --auth in --replSet instead of rs0

答案1

得分: 2

我怀疑你只传递了第一个 --replSet 选项给镜像的入口脚本。我可能会改变你传递选项的方式,从 $0 改为 "$@",确保传递所有选项并正确引用它,然后插入一个额外的参数作为(现在未使用的)$0 值。

entrypoint:
  - /bin/sh
  - -c
  - |
    ...
    exec docker-entrypoint.sh "$$@"    
  - entrypoint-script
command: --replSet rs0 ...

sh -c 的语法

sh -c command_string command_name argument ...

其中 command_name 变成了 command_string 内部的 $0 值,而 argument 变成了 $1$2 等等。因此,为 command_name 参数添加一个明确的值应该有助于解决语法问题。

在你的原始配置中,这被组合成:

  1. Compose 解析 YAML;
  2. Compose 在字符串内部用 $ 替换 $$
  3. 字符串格式的 command: 被拆分成单词;
  4. 被覆盖的 entrypoint:command: 被连接在一起。

这会得到如下命令:

sh -c "...\nexec docker-entrypoint.sh $0\n" --replSet rs0 ...

请注意,在此命令中,我们只插入了单一的参数 $0,而该位置的选项是 --replSet。其余选项将被忽略。

我怀疑如果你能强制 Compose 将 command: 转换为一个单一字符串,可能通过将其嵌入到 YAML 列表中 command: [--replSet rs0 ...]。然后,未引用的参数展开 $0 将在评估参数值后执行单词拆分。尽管如此,在 shell 脚本中依赖这种行为通常不是一个好做法。

英文:

I suspect you're only passing the first --replSet option to the image's entrypoint script. I might change the place you pass on the option from $0 to "$@", making sure to pass all the options and to correctly quote it, and then insert an extra argument to be the (now unused) $0 value.

entrypoint:
  - /bin/sh
  - -c
  - |
    ...
    exec docker-entrypoint.sh "$$@"    
  - entrypoint-script
command: --replSet rs0 ...

The syntax of sh -c is

sh -c command_string command_name argument ...

where command_name becomes the $0 value inside command_string, and the arguments become $1, $2, and so on. So adding an explicit value for the command_name argument should help resolve the syntax.

In your original formation, this gets put together as:

  1. Compose parses the YAML;
  2. Compose replaces $$ with $ inside the string;
  3. The string-format command: is split into words;
  4. The overridden entrypoint: and command: are concatenated together.

This gives you a command like

sh -c "...\nexec docker-entrypoint.sh $0\n" --replSet rs0 ...

Notice in this command we're only inserting the single parameter $0, and the option in that position is --replSet. The remaining options just get ignored.

I suspect the original pattern you had found would work if you could force Compose to make the command: into a single string, maybe by embedding it into a YAML list command: [--replSet rs0 ...]. Then the unquoted parameter expansion $0 would do word splitting after evaluating the parameter value. It's usually not a good practice in shell scripts to rely on this, though.

huangapple
  • 本文由 发表于 2023年6月15日 18:25:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76481557.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定