最近在使用 docker 挂载文件时,发现一个问题,在宿主机更新挂载文件,容器内并未同步。但是重启容器后,容器内又更新了文件。
容器举个例子
以下以 nginx 容器举个例子
version: '3'
services:
nginx:
image: nginx:latest
container_name: my-nginx
volumes:
- /root/docker-compose/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- /root/docker-compose/nginx/index.html:/usr/share/nginx/html/index.html
ports:
- "80:80"
- "443:443"
输出容器内 nginx index 页面内容
docker exec my-nginx cat /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
修改宿主机上 index 页面内容
vi index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Hello World!</h1>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
再次查看容器内 index 页面内容,发现内容并未同步更新。
docker exec my-nginx cat /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
原因分析
Docker 挂载文件时,挂载的是文件的 inode,而不是路径。当你用 Vim 编辑并保存文件时,它会创建一个新文件并替换原文件,从而改变 inode。由于 inode 改变,容器内的文件没有更新。重启容器时,会挂载新的 inode。
接下来验证一下,首先先重启下容器,让原本的更新生效。
docker exec my-nginx cat /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Hello World!</h1>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
接下来查看一下宿主机 index.html 的 inode,可以看到 inode 值 = 5349362
stat index.html
文件:index.html
大小:298 块:8 IO 块:4096 普通文件
设备:略 Inode:5349362 硬链接:1
权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root)
最近访问:2024-11-17 00:17:02.430672510 +0800
最近更改:2024-11-17 00:16:59.236639833 +0800
最近改动:2024-11-17 00:16:59.238639854 +0800
创建时间:-
再看一下容器里 index.html 的 inode,可以看到 inode 值和宿主机是一样的。
docker exec my-nginx stat /usr/share/nginx/html/index.html
File: /usr/share/nginx/html/index.html
Size: 298 Blocks: 8 IO Block: 4096 regular file
Device: 252,1 Inode: 5349362 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2024-11-16 16:17:02.430672510 +0000
Modify: 2024-11-16 16:16:59.236639833 +0000
Change: 2024-11-16 16:16:59.238639854 +0000
Birth: 2024-11-16 16:16:59.236639833 +0000
接下来通过 vi 修改宿主机 index.html 文件
vi index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Hello World!!!!!!!</h1>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
之后再看看宿主机 index.html 对应 inode,发现宿主机的 inode 值已经发生变化。
stat index.html
文件:index.html
大小:304 块:8 IO 块:4096 普通文件
设备:略 Inode:4878009 硬链接:1
权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root)
最近访问:2024-11-17 00:40:32.826158500 +0800
最近更改:2024-11-17 00:40:24.556072681 +0800
最近改动:2024-11-17 00:40:24.558072702 +0800
创建时间:-
再看看容器内 index.html 对应 inode 值,发现容器内 inode 值还是旧值。因此,宿主机更新文件内容并未同步到容器内。
docker exec my-nginx stat /usr/share/nginx/html/index.html
File: /usr/share/nginx/html/index.html
Size: 298 Blocks: 8 IO Block: 4096 regular file
Device: 252,1 Inode: 5349362 Links: 0
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2024-11-16 16:17:02.430672510 +0000
Modify: 2024-11-16 16:16:59.236639833 +0000
Change: 2024-11-16 16:40:24.558072702 +0000
Birth: 2024-11-16 16:16:59.236639833 +0000
解决方案
-
调整宿主机文件权限为 664,网上有些文章写着是需要将文件权限改成 777,亲测,只需要将组权限改成读写既可以,接下来在测试一下。
chmod 664 index.html vi index.html <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Hello World!!!</h1> <p><em>Thank you for using nginx.</em></p> </body> </html> stat index.html 文件:index.html 大小:300 块:8 IO 块:4096 普通文件 设备:略 Inode:4878009 硬链接:1 权限:(0664/-rw-rw-r--) Uid:( 0/ root) Gid:( 0/ root) 最近访问:2024-11-17 00:46:38.674904905 +0800 最近更改:2024-11-17 00:47:00.742129147 +0800 最近改动:2024-11-17 00:47:00.743129157 +0800 创建时间:-
可以看见,将文件权限设置成 664 后,可以避免 vi 编辑器更新导致 inode 变更问题。
-
使用挂载目录,挂载目录即使文件 inode 发生变更,容器内也能同步新的 inode