写点什么

使用 Docker 踩坑,排查完问题之后,又涨知识了

作者:程序员小毕
  • 2022-11-18
    湖南
  • 本文字数:2342 字

    阅读完需:约 8 分钟

使用Docker踩坑,排查完问题之后,又涨知识了

背景

新上线一个批处理功能,基于 Docker 发布的。上线之后出现一个问题,Docker 批处理生成的文件目录,别的应用程序无法访问。

之前也在使用 Docker,但并未涉及到文件共享的问题,还真没留意到。经过一系列排查,终于找到原因。这篇文章就记录一下排查过程中使用到的技术点,也帮大家重温一下。

涉及的知识点:Docker help 命令、Linux 用户/组 id 查看、Docker 用户指定、Docker 启动失败日志查看等

现象分析

Docker 运行的项目定时创建文件目录并进行文件生成等操作,但当其他应用程序来操作 Docker 应用生成的目录时,会提示“Permission denied”错误。

查看 Docker 生成的文件夹权限,竟然是以 root 用户创建的。执行 Docker 的启动脚本明明是普通用户,生成的文件怎么就变成了 root 用户了?

这里就涉及到通过 Docker 执行执行时所使用的用户了。如果在执行 Docker 执行命令时,未指定所使用的用户,默认以 root 用户执行。在这生产环境下当然是不允许的了。

问题解决

既然找到问题的原因解决起来就比较容易了,下面记录一下解决问题及涉及到的一些 Docker 命令和 Linux 操作。

查询帮助文档

先来通过 help 命令查看一下 Docker 的命令参数,如何来指定执行命令的用户。

先尝试了docker --help命令,结果并未找到指定用户的命令参数:

$ sudo docker --help
Usage:  docker [OPTIONS] COMMAND
A self-sufficient runtime for containers
Options:      --config string      Location of client config files (default "/root/.docker")  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")  -D, --debug              Enable debug mode  -H, --host list          Daemon socket(s) to connect to  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")      --tls                Use TLS; implied by --tlsverify      --tlscacert string   Trust certs signed only by this CA (default "/root/.docker/ca.pem")      --tlscert string     Path to TLS certificate file (default "/root/.docker/cert.pem")      --tlskey string      Path to TLS key file (default "/root/.docker/key.pem")      --tlsverify          Use TLS and verify the remote  -v, --version            Print version information and quit
复制代码

后来才意识到,查找的应该是 docker 的 run 命令的帮助文档:

$ sudo docker run --help...  -u, --user string                    Username or UID (format: <name|uid>[:<group|gid>])      --userns string                  User namespace to use      --uts string                     UTS namespace to use...
复制代码

其中便有指定 run 命令操作的所属用户参数,通过-u可指定执行命令的用户和组。

docker 指定用户

参照帮助手册,整理了 docker 的运行命令(伪代码):

$ sudo docker run -itd -u testuser -p 8080:8080 -v /log/:/log xxx-job:latest
复制代码

上述指令中通过-u username指定了执行命令的用户,按理说可以正常执行的,但执行时抛出了以下异常信息:

docker: Error response from daemon: unable to find user testuser: no matching entries in passwd file.'
复制代码

虽然当前用户是 testuser,但 docker 貌似并未在 passwd 文件中找到它,此时直接通过用户的 UID 来替换 Username。

获得 Linux 用户 UID

获得 Linux 用户的 UID 有两种方法。

方法一:执行命令。

获得 UID 命令:

$ id -u1002
复制代码

当前用户的 UID 便是 1002。

获得组 ID 命令:

$ id -g1002
复制代码

当前用户所属组 ID 便是 1002。

方法二:查看/etc/passwd 获取 UID 和组 ID。

执行cat /etc/passwd命令,显示/etc/passwd 中的内容。

图片来源于网络

在/etc/passwd 中找到当前用户后面对应的 UID 和组 ID。

调整 Docker 命令

获得了当前用户的 UID 和组 ID 之后,Docker 运行命令修改如下:

$ sudo docker run -itd -u 1002:1002 -p 8080:8080 -v /log/:/log xxx-job:latest
复制代码

正常来说,问题到此便解决了,可正常启动应用程序。

Docker 日志查看

但笔者又遇到另外一个问题,就是 Docker 中应用的日志,由于之前的失误默认通过 root 用户创建的,此时使用了 testuser 来启动应用程序,发现 Docker 无法启动,原因很简单 testuser 启动的应用无法向 root 创建的日志文件写日志。

排查启动失败时用到了查看 Docker 失败日志的命令:

docker logs 97069f94437b
复制代码

此时,或将原来的日志备份,让系统重新生成日志文件,或直接修改日志文件权限为 testuser 即可。

至此,关于 Docker 生成目录权限问题解决完毕。

小结

其实,导致上面问题的原因很小,就是漏了一个参数的事。但不经一事,不长一智。可能很多朋友在使用 Docker 的过程中可能都没留意到这一问题。

而问题的排查过程也很有意思,不仅涉及到了 Docker 的操作命令,也涉及到了 Linux 的一些基础知识,知识和技能就是在出现问题、解决问题的过程中增长的。

在解决了上述问题之后,不仅感慨“纯学究式的技术学习,终究还是有缺陷的,必须实践,必须临床实践!

如果感觉本文对你有帮助,点赞关注支持一下,想要了解更多 Java 后端,大数据,算法领域最新资讯可以关注我公众号【架构师老毕】私信 666 还可获取更多 Java 后端,大数据,算法 PDF+大厂最新面试题整理+视频精讲

用户头像

领取资料添加小助理vx:bjmsb2020 2020-12-19 加入

Java领域;架构知识;面试心得;互联网行业最新资讯

评论

发布
暂无评论
使用Docker踩坑,排查完问题之后,又涨知识了_Java_程序员小毕_InfoQ写作社区