API读取Docker容器/etc/passwd遇阻:SDK与命令调用异常排查
问题描述
我尝试读取Docker容器内的/etc/passwd文件来区分初始用户与新增用户,但通过API实现时遇到两类问题:
- 使用
docker.from_env()方法时,Postman请求返回未识别from_env()的错误 - 通过subprocess调用
/usr/bin/docker exec命令读取文件时,系统提示找不到/usr/bin/docker路径
相关代码与配置
myoswrap模块代码
def readFileByLine( filename): try: command = f"cat {filename}" output = subprocess.check_output(["/usr/bin/docker", "exec", "userapi_cnt_ad", "sh", "-c", command]) output_lines = output.decode("utf-8").splitlines() return output_lines except subprocess.CalledProcessError: return None
userapi代码
@app.route('/users') def route_getUsers(): users = dom.getUserList() newUsers = [] initialUsers = [] for user in users: if dom.isInitialUser(user) == False: newUsers.append(user) else: initialUsers.append(user) return jsonify({"newUsers": newUsers, "initialUsers": initialUsers}), 200
userrepo代码
import json import docker INITIAL_USERS = ['root:x:0:0:root:/root:/bin/bash', 'daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin', 'bin:x:2:2:bin:/bin:/usr/sbin/nologin', 'sys:x:3:3:sys:/dev:/usr/sbin/nologin', 'sync:x:4:65534:sync:/bin:/bin/sync', 'games:x:5:60:games:/usr/games:/usr/sbin/nologin', 'man:x:6:12:man:/var/cache/man:/usr/sbin/nologin', 'lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin', 'mail:x:8:8:mail:/var/mail:/usr/sbin/nologin', 'news:x:9:9:news:/var/spool/news:/usr/sbin/nologin', 'uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin', 'proxy:x:13:13:proxy:/bin:/usr/sbin/nologin', 'www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin', 'backup:x:34:34:backup:/var/backups:/usr/sbin/nologin', 'list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin', 'irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin', 'gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin', 'nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin', '_apt:x:100:65534::/nonexistent:/usr/sbin/nologin']
userdomain代码
def getUserList(): users = [] lines = myoswrap.readFileByLine('/etc/passwd') if lines is not None: # Check if lines is not None for line in lines: users.append(line.split(':')[0]) return users def isInitialUser(username): if username in repo.INITIAL_USERS: return True return False
./startdocker脚本
#!/bin/bash docker container stop userapi_cnt_ad docker container rm userapi_cnt_ad docker image rm userapi_img_ad docker volume rm ad_vol docker volume create --name ad_vol --opt device=/mnt/share/ad-infra-tp-2-h-2024 --opt o=bind --opt type=none docker build -t userapi_img_ad -f ./project/docker/Dockerfile . docker run -d -p 15556:25556 --mount source=ad_vol,target=/mnt/app --name userapi_cnt_ad userapi_img_ad
Dockerfile内容
FROM demers/python420w4a COPY ./requirements.txt / RUN pip3 install -r /requirements.txt WORKDIR /mnt/app/ CMD ["./run.sh", "./project/main/userapi.py", "25556"]
解决方案
问题1:docker.from_env()未识别错误
- 校验模块版本:卸载旧版
docker-py(如果存在),重新安装官方docker模块:pip uninstall docker-py -y pip install docker - 修正导入与调用:确保代码中正确导入并初始化客户端:
import docker client = docker.from_env() - 容器内权限配置:如果API运行在容器内,启动容器时需挂载Docker套接字以获取宿主机Docker访问权限:
docker run -d -p 15556:25556 -v /var/run/docker.sock:/var/run/docker.sock --mount source=ad_vol,target=/mnt/app --name userapi_cnt_ad userapi_img_ad
问题2:subprocess调用docker路径找不到
- 确认Docker真实路径:在宿主机执行
which docker获取实际路径,替换代码中的/usr/bin/docker - 容器内安装Docker客户端:修改Dockerfile添加Docker客户端安装步骤:
FROM demers/python420w4a COPY ./requirements.txt / RUN apt-get update && apt-get install -y docker.io RUN pip3 install -r /requirements.txt WORKDIR /mnt/app/ CMD ["./run.sh", "./project/main/userapi.py", "25556"] - 优化文件读取逻辑:无需通过
docker exec读取自身容器内的文件,直接本地读取即可,修改readFileByLine函数:def readFileByLine(filename): try: with open(filename, 'r') as f: return f.read().splitlines() except (FileNotFoundError, PermissionError): return None
内容的提问来源于stack exchange,提问作者LADsy8
相关产品推荐
相关产品推荐

