Docker中Apache Kafka执行/bin/sh遇Permission Denied问题
问题描述
用Docker Compose基于wurstmeister/kafka镜像部署Kafka集群后,执行docker exec -it test-kafka /bin/sh进入容器,不管是访问目录还是使用/usr/bin下的消费者控制台工具、topics.sh脚本,都会弹出错误:/bin/sh: 1: /bin: Permission denied。
用户的Docker Compose配置如下:
version: '3' services: zookeeper: image: wurstmeister/zookeeper:latest hostname: zookeeper-hostname container_name: zookeeper ports: - "2181:2181" environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_SERVER_ID: 1 ZOOKEEPER_SERVERS: zookeeper:2888:3888 ALLOW_ANONYMOUS_LOGIN: yes kafka: image: wurstmeister/kafka:latest hostname: my-test-kafka container_name: test-kafka ports: - "9092:9092" - "29092:29092" - "9999:9999" environment: KAFKA_LISTENERS: INTERNAL://0.0.0.0:19092,EXTERNAL://0.0.0.0:9092,DOCKER://0.0.0.0:29092 KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092 KAFKA_CREATE_TOPICS: "gratitude-topic:3:1,order-is-processed-topic:1:1:" ALLOW_PLAINTEXT_LISTENER: yes KAFKA_CFG_LISTENERS: PLAINTEXT://0.0.0.0:9092 KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181" KAFKA_BROKER_ID: 1 KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO" KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 KAFKA_JMX_PORT: 9999 KAFKA_JMX_HOSTNAME: ${DOCKER_HOST_IP:-127.0.0.1} KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true" depends_on: - zookeeper
问题原因
- 镜像默认用户权限不足:wurstmeister/kafka镜像默认用非root用户(一般是
kafka用户)启动容器,这个用户对/bin目录和部分系统工具没有执行权限,执行命令时就会触发权限拒绝错误。 - 环境变量冲突:配置里同时设置了
KAFKA_LISTENERS和KAFKA_CFG_LISTENERS两组监听器变量,二者冲突会导致容器启动时权限配置异常,加重了命令执行的权限问题。
解决方法
临时方案:以root身份进入容器
直接执行下面的命令,以root用户进入容器,就能获得完整权限,正常使用各类工具:
docker exec -it -u root test-kafka /bin/sh
修正配置:解决环境变量冲突
删掉配置里重复的KAFKA_CFG_LISTENERS和KAFKA_CFG_ADVERTISED_LISTENERS,保留KAFKA_LISTENERS相关的正确配置,避免冲突。修正后的kafka服务环境变量部分如下:
environment: KAFKA_LISTENERS: INTERNAL://0.0.0.0:19092,EXTERNAL://0.0.0.0:9092,DOCKER://0.0.0.0:29092 KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092 KAFKA_CREATE_TOPICS: "gratitude-topic:3:1,order-is-processed-topic:1:1:" ALLOW_PLAINTEXT_LISTENER: yes KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181" KAFKA_BROKER_ID: 1 KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO" KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 KAFKA_JMX_PORT: 9999 KAFKA_JMX_HOSTNAME: ${DOCKER_HOST_IP:-127.0.0.1} KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
修改后重启容器:
docker-compose down && docker-compose up -d
之后再进入容器就能正常执行命令了。
长期方案:指定容器以root用户运行
在Docker Compose的kafka服务配置里添加user: root,让容器直接以root用户启动,从根源避免权限问题:
kafka: image: wurstmeister/kafka:latest hostname: my-test-kafka container_name: test-kafka user: root # 添加该行 ports: - "9092:9092" - "29092:29092" - "9999:9999" # 其余环境变量和配置保持不变
重启容器后,直接进入即可正常操作。
内容的提问来源于stack exchange,提问作者Smetana Po Aktsii
相关产品推荐
相关产品推荐

