1.错误说明
当使用docker-compose启动容器后,通过浏览器访问服务器,发现一直转圈,通过php-fpm slow慢日志查看,发现如下错误:
[31-May-2023 12:02:34] ERROR: failed to ptrace(ATTACH) child 12: Operation not permitted (1)
[31-May-2023 12:02:34] WARNING: [pool www] child 12, script '/www/index.php' (request: "GET /index.php") executing too slow (5.021099 sec), logging
2.错误原因
这是因为Docker容器权限问题
在docker中部署的php容器默认是不能记录慢日志的;
在Linux系统中,PHP-FPM使用SYS_PTRACE跟踪worker进程,而SYS_PTRACE是什么呢?(这是Linux capabilities里的一种操作特权),那么Linux capabilities又是什么呢?linux从内核2.2开始,将传统上与超级用户root关联的特权划分为不同的单元,称为capabilites,Capabilites 作为线程(Linux 并不真正区分进程和线程)的属性存在,每个单元可以独立启用和禁用。
如此一来,权限检查的过程就变成了:在执行特权操作时,如果进程的有效身份不是 root,就去检查是否具有该特权操作所对应的capabilites,并以此决定是否可以进行该特权操作。所以在docker容器中php写慢日志就得有CAP_KILL capability ,设置系统时间,就得具有 capability CAP_SYS_TIME,docker容器中默认是不启用这个功能的,因此导致了问题
3.解决办法
在容器启动时,加入参数--cap-add SYS_PTRACE即可
(1).通过–security-opt seccomp=unconfined命令
简单暴力(不推荐),直接关闭 seccomp 配置,用法:
docker run --security-opt seccomp:unconfined ...
(2).启动docker时加上 –cap-add=SYS_PTRACE
使用 --cap-add 明确添加指定功能:
docker run --cap-add=SYS_PTRACE ...
(3). 在Docker Compose中的解决方式
Docker Compose 自 version 1.1.0 (2015-02-25) 起支持 cap_add,官方文档:cap_add, cap_drop.在docker-compose.yml用法:
version: "3"
services:
nginx:
build: ./nginx/
ports:
- 80:80
volumes:
- "${PROJECT_ROOT}:/var/www"
- "${VHOST_ROOT}:/etc/nginx/conf.d"
networks:
- server
depends_on:
- php
cap_add:
- SYS_PTRACE
php:
build: ./php-fpm/
expose:
- 9000
volumes:
- "${PROJECT_ROOT}:/var/www"
- "/etc/crontab:/etc/crontab"
links:
- redis
# - sphinx
- mysql
- mongo
networks:
- server
cap_add:
- SYS_PTRACE
# sphinx:
# build: ./sphinx/
# ports:
# - 9312:9312
# networks:
# - server
redis:
build: ./redis/
ports:
- 6379:6379
networks:
- server
mysql:
build: ./mysql
ports:
- 3306:3306
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/data:/var/lib/mysql
restart: always
networks:
- server
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_USER: user
MYSQL_PASSWORD: 123456
rabbitmq:
hostname: rabbit01
environment:
RABBITMQ_DEFAULT_VHOST: "/"
RABBITMQ_DEFAULT_USER: "user"
RABBITMQ_DEFAULT_PASS: "123456"
TZ: 'Asia/Shanghai'
RABBITMQ_ERLANG_COOKIE: 'rabbitmqCookie'
image: "rabbitmq:3.7.16-management"
restart: always
networks:
- server
volumes:
- "./rabbitmq:/var/lib/rabbitmq"
- "./rabbitmq/log:/var/log/rabbitmq/log"
ports:
- "15672:15672"
- "4369:4369"
- "5672:5672"
- "25672:25672"
mongo:
build:
context: ./mongo
ports:
- "27017:27017"
#container_name: mongo
environment:
AUTH: "yes"
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 123456
volumes: #数据卷映射
- /mongo/mongod.conf:/etc/mongod.conf #这里做配置文件的映射,想通过配置文件开启数据库的权限验证,但好像没有效果,后面在研究下
- /mongo/data:/data/db
- /mongo/logs/:/var/log/mongodb
#command: mongodb
restart: always
privileged: true
networks:
- server
#mongodb可视化工具:部署完后,需开放对应端口号
mongo-express:
image: mongo-express
restart: always
links:
- mongo
depends_on:
- mongo
ports:
- "28017:8081"
networks:
- server
environment:
#注意: 冒号后面需要有对应的空格,不然docker-compose安装会报错,fuck!
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: 123456
ME_CONFIG_BASICAUTH_USERNAME: root
ME_CONFIG_BASICAUTH_PASSWORD: b123456
ME_CONFIG_MONGODB_URL: mongodb://root:123456@mongo:27017/
networks:
server:
好了,问题解决
但是在这里还需要注意一点:在 docker-compose.yml中加入cap_add配置时,注意空格的处理,不然启动docker-compose时会报下面错误:
ERROR: yaml.parser.ParserError: while parsing a block mapping in "./docker-compose.yml", line 1, column 1 expected <block end>, but found '<block mapping start>' in "./docker-compose.yml", line 31, column 7
错误原因:空格导致的未对齐(严格意义上的对齐)
解决方案:对应位置line 31, column 7添加或者删除空格,使得同一层的保持对齐,在这里建议先在编辑器中编辑docker-compose.yml后再传到服务器中