Dockerfile CMD指令中环境变量未正常替换的问题求助
Dockerfile CMD指令中环境变量未正常替换的问题求助
大家好,我最近在折腾用Docker搭建单节点MongoDB集群,碰到个卡壳的问题——Dockerfile里CMD指令中的${REPLICASET}环境变量始终没法被替换成我在.env里设置的rs0值,折腾了好几种方法都没搞定,来求助大家!
问题场景与现象
我的思路是:在.env里定义REPLICASET=rs0,通过docker-compose的args把这个值传给Dockerfile的ARG,再转成ENV,最后在CMD里用这个变量启动mongod。但现在用docker inspect -f "{{.Name}} {{.Config.Cmd}}" node1查看容器配置,输出是:
/node1 [mongod --replSet ${REPLICASET} --bind_ip_all --auth --keyFile /run/keyfile.txt]
${REPLICASET}完全没被替换,就是个静态字符串,导致mongod启动时没法识别副本集名称。
我试过的方法都没生效:
- 直接在docker-compose的
environment字段里设置REPLICASET - 用docker-compose的
args传递给Dockerfile的ARG,再转成ENV
我的配置文件
docker-compose.yml
version: "3.8" services: node1: hostname: ${NODE1} container_name: node1 restart: unless-stopped ports: - "27017:27017" build: context: . args: REPLICASET: ${REPLICASET} volumes: - ./certs/node1:/certs:ro - ./init-user.js:/docker-entrypoint-initdb.d/init-user.js:ro - ./init-replset.js:/docker-entrypoint-initdb.d/init-replset.js:ro - ./dump:/dump - ./scripts:/scripts
Dockerfile
FROM mongo:8.0 ARG REPLICASET ENV REPLICASET=${REPLICASET} RUN openssl rand -base64 755 > /run/keyfile.txt RUN chmod 400 /run/keyfile.txt RUN chown 999:999 /run/keyfile.txt CMD ["mongod", "--replSet", "${REPLICASET}", "--bind_ip_all", "--auth", "--keyFile", "/run/keyfile.txt"]
.env
ENV=local USER=local PASSWORD=password1 REPLICASET=rs0 NODE1=node1 DATABASE=app
解决方案
问题的核心在于Docker的CMD指令形式!你现在用的是exec形式(数组格式),这种形式下Docker会直接把数组里的参数传给进程,不会调用shell来解析环境变量,所以${REPLICASET}会被当作字面量处理。
有两种简单的解决方法:
方法1:改用shell形式的CMD
把CMD改成字符串形式,Docker会自动启动sh -c来解析环境变量:
CMD mongod --replSet ${REPLICASET} --bind_ip_all --auth --keyFile /run/keyfile.txt
或者你也可以显式指定shell,效果是一样的:
CMD ["sh", "-c", "mongod --replSet ${REPLICASET} --bind_ip_all --auth --keyFile /run/keyfile.txt"]
方法2:使用自定义Entrypoint脚本
如果之后需要添加更多启动前的逻辑,也可以写一个脚本作为Entrypoint:
- 在项目根目录创建
entrypoint.sh:
#!/bin/sh # 这里可以添加更多启动前的逻辑,比如检查环境变量是否存在 exec mongod --replSet "${REPLICASET}" --bind_ip_all --auth --keyFile /run/keyfile.txt
- 在Dockerfile里复制脚本并设置权限:
COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]
修改完成后,重新构建镜像并启动容器,再用docker inspect查看,${REPLICASET}就会被正确替换成rs0啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

