一、背景
使用 docker 部署的 nginx,并且已经配置了文件挂载,参数如下:
-v /deploy/nginx/conf.d/doc.crt:/etc/nginx/conf.d/doc.crt
-v /deploy/nginx/conf.d/doc.key:/etc/nginx/conf.d/doc.key
-v /deploy/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
<font style="color:rgb(40, 202, 113);">*.html</font>
禁用缓存,如下配置
于是就在宿主机上直接修改
if ($request_filename ~* .*\\.(htm|html)$) {
add_header Cache-Control "no-store";
}
<font style="color:rgb(40, 202, 113);">/deploy/nginx/conf.d/default.conf</font>
文件。
然后运行 <font style="color:rgb(40, 202, 113);">docker exec -it pc-nginx nginx -s reload</font>
,使配置生效。
但是实际测试结果并没有生效
还以为是配置加的不对,花了好长时间,改了几种方式,结果都不行。
直到进入容器内,查看容器内的文件发现,文件根本就没有改动!!!
重启了这个容器,配置文件才进行了更新,问题得到解决。
二、思考
docker容器的挂载难道不是生效,而是要容器启动的时候才会更新?
肯定不是这样,容器内产生的日志内容,在容器外可以实时查看,难道是内->外是实时,外->内 是启动的时候才加载?
经过一番查阅资料,发现了这个:
Docker 中,mount volume 的原理是借用了 Linux Namespace 中的 Mount NameSpace,隔离系统中不同进程的挂载点视图,实际文件是没有变化。
在container中,bash 实际就是一个运行在宿主机上的进程,被Docker用Linux分别隔离了 Mount Namespace、UTS Namespace、IPC Namespace、PID Namespace、Network Namespace和User Namespace,使得它看上去好像运行在了一个独立的、相对隔离的系统上,但实际它的一切资源都是宿主机在不同Namespace中的一个投影,文件也不例外。
Linux中,证明文件是否相同的根本途径是,使用<font style="color:rgb(40, 202, 113);">stat</font>
命令,判断其 inode,如果两个文件的inode相同,两个文件必定为同一文件,从而两个文件的内容也必然相同。
docker本身不支持直接映射文件,使用docker映射文件时可能会出现问题 。
三、实践
复现场景,验证问题
- 创建文件
nginx内容如下:
mkdir -p /opt/nginx
cd /opt/nginx
vi demo.conf
server {
listen 80;
server_name gateway.cn;
location / {
proxy_pass http://localhost:7001/;
}
}
- 创建2个容器,一个映射目录,一个映射文件
<font style="color:rgb(40, 202, 113);">docker run --name n1-dir -v /opt/nginx:/etc/nginx/conf.d -d nginx</font>
<font style="color:rgb(40, 202, 113);">docker run --name n2-file -v /opt/nginx/demo.conf:/etc/nginx/conf.d/demo.conf -d nginx</font>
- 再开启两个 shell ,进入容器内,查看文件
<font style="color:rgb(40, 202, 113);">docker exec -ti n1-dir /bin/bash</font>
<font style="color:rgb(40, 202, 113);">docker exec -ti n2-file /bin/bash</font>
<font style="color:rgb(40, 202, 113);">cat /etc/nginx/conf.d/demo.conf</font>
- 修改外部文件
- 简单修改,加一行注释
# fadsff
- 重新查看文件
- 但是得到了相同的结果,这与预期不符,使用
stat
命令,容器外和2个容器内的demo.conf 文件都是同一个inode
和线上的环境得到的结果不一致,这就很令人费解。想到线上的环境不是用的root账号部署的,难道和用户也有关系?
创建demo用户,再次尝试
n3
n4
<font style="color:rgb(40, 202, 113);">conf.d</font>
目录时,文件可以得到正常更新,但是如果直接挂载文件,文件的内容并不会实时更新。
四、小结
docker部署容器需要进行挂载时,使用挂载<font style="color:rgb(40, 202, 113);">目录</font><font style="color:rgb(63, 63, 63);">的方式</font>
,不要直接挂载<font style="color:rgb(40, 202, 113);">文件</font>
。 挂载目录不会出现宿主机文件更新,而容器中文件没有更新的问题。