关于架构
- PHP7.2
- OpenResty
- Redis
- MySQL
更新于:2018-7-11
跟同事验证之后,似乎并不是我描述的那样。两个容器内,虽然分组的名称不同,但是只要GID相同,就有权限。至于为什么会造成nginx启动后没有权限读取socket文件,是因为在nginx.conf文件中没有指定运行用户的原因。
比如我的nginx是基于alpine构建的。php所运行的容器的www-data
的GID是33,对应到alpine中的GID:33
是xfs,需要在nginx.conf
中添加进 user xfs
就ok了。如果并不想这么干,那就需要执行下面的命令deluser xfs && \
删掉xfs这个用户,然后重新新建一个GID为33,用户组为
addgroup -g 33 -S www-data && adduser -u 33 -D -S -G www-data www-datawww-data
,用户名为www-data
的用户
分割线
下面是错误的解答
上面的架构在Linux中有个非常常见的名字是LNMP。基本上是在相同的系统中进行的配置。因此,常规的业务中几乎不会有人会在LNMP这架构上遇到标题中的问题。
但是在Docker中,可以有PHP环境是Debian,OpenResty环境是alpine这样的搭配。
验证无权限问题
拉取Debian 9.2的镜像 docker pull debian:9.2
,然后运行 docker run 6d83de432e98 ping baidu.com
。进入系统中查看用户分组 cat /etc/group
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:
floppy:x:25:
tape:x:26:
sudo:x:27:
audio:x:29:
dip:x:30:
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
gnats:x:41:
shadow:x:42:
utmp:x:43:
video:x:44:
sasl:x:45:
plugdev:x:46:
staff:x:50:
games:x:60:
users:x:100:
nogroup:x:65534:
上面就是debian镜像中的所有分组。
然后拉取apline 3.6 的镜像 docker pull alpine:3.6
,并运行docker run 77144d8c6bdc ping baidu.com
。进入系统查看用户分组
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
tty:x:5:
disk:x:6:root,adm
lp:x:7:lp
mem:x:8:
kmem:x:9:
wheel:x:10:root
floppy:x:11:root
mail:x:12:mail
news:x:13:news
uucp:x:14:uucp
man:x:15:man
cron:x:16:cron
console:x:17:
audio:x:18:
cdrom:x:19:
dialout:x:20:root
ftp:x:21:
sshd:x:22:
input:x:23:
at:x:25:at
tape:x:26:root
video:x:27:root
netdev:x:28:
readproc:x:30:
squid:x:31:squid
xfs:x:33:xfs
kvm:x:34:kvm
games:x:35:
shadow:x:42:
postgres:x:70:
cdrw:x:80:
usb:x:85:
vpopmail:x:89:
users:x:100:games
ntp:x:123:
nofiles:x:200:
smmsp:x:209:smmsp
locate:x:245:
abuild:x:300:
utmp:x:406:
ping:x:999:
nogroup:x:65533:
nobody:x:65534:
在Debian系统中用www-data
用户组中www-data
用户跑php服务。产生一个socket文件 php7.sock
代替端口监听。这个文件被挂载到宿主机的目录上。OpenResty通过挂载目录到相同的宿主机目录上来设置监听。
通过编写编排文件docker-compose.yml
文件,运行docker-compose up
进行部署服务。php服务中会给php7.sock
文件赋予 swr-wr----
的权限,而该文件所属www-data:www-data
。此时就会出现一个问题。在Debian中,该文件是www-data
这个组中的用户可以读写的,但是在alpine中并没有这个www-data
的用户组和这个用户。那他是怎么处理这个问题的呢?(在linux中的文件,是不可能没有所属用户和所属用户组的。)
观察Debian中的www-data
的用户组列表,发现该组中的编号是33
。在实际操作部署中,php7.sock
文件是属于xfs:xfs
,而Debian中的www-data
的GID正好与alpine中的xfs
的GID相同。
GID相同造成两个系统中的授权出现了不同,而(矫情的)sock文件只认www-data
这个用户组中的用户,因此造成了OpenResty在有请求时监听sockt文件会出现没有权限读取的问题。
解决问题
既然docker跨系统的授权是通过GID配对,而sockt文件只认同名字用户组用户。因此需要删除xfs
用户组创建www-data
用户组。
deluser xfs && \
addgroup -g 33 -S www-data && adduser -u 33 -D -S -G www-data www-data
编排代码
version: '2.0'
services:
php-fpm:
image: daocloud.io/xss_er/php:php72
container_name: php72
restart: always
ports:
- "9000"
volumes:
- ./code:/var/www/app #work dir
- /tmp/test/php7-fpm:/var/run/php7-fpm
networks:
- back-net
nginx:
image: daocloud.io/xss_er/nginx:openresty-server
container_name: openresty
restart: always
ports:
- "15000:80"
volumes:
- ./data/wwwlog:/usr/local/openresty/nginx/logs #logfile dir
- /tmp/test/php7-fpm:/var/run/php7-fpm
- ./code:/var/www/app #Code
- ./conf.d:/usr/local/openresty/nginx/conf/conf.d
networks:
- back-net
networks:
back-net:
external: true