• 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

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

    $ sudo docker run --help
    ...
      -u, --user string                    Username or UID (format: [:])
          --userns string                  User namespace to use
          --uts string                     UTS namespace to use
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

    docker指定用户

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

    $ sudo docker run -itd -u testuser -p 8080:8080 -v /log/:/log xxx-job:latest
    
    • 1

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

    docker: Error response from daemon: unable to find user testuser: no matching entries in passwd file.'
    
    • 1

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

    获得Linux用户UID

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

    方法一:执行命令。

    获得UID命令:

    $ id -u
    1002
    
    • 1
    • 2

    当前用户的UID便是1002。

    获得组ID命令:

    $ id -g
    1002
    
    • 1
    • 2

    当前用户所属组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
    
    • 1

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

    Docker日志查看

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

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

    docker logs 97069f94437b
    
    • 1

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

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

    小结

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

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

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

  • 相关阅读:
    嘉立创EDA的一些使用技巧
    【数值分析】复习知识点整合
    程序员年薪50万有多难?背后真相曝光,溢价程度超乎你想象
    计算机设计大赛 题目:基于深度学习卷积神经网络的花卉识别 - 深度学习 机器视觉
    springboot:异步注解@Async的前世今生
    禅道bug统计并发送钉钉通知
    对一个以“#”结束的字符串
    elasticsearch14-高亮
    Java基础20221105
    深入研究下Spring Boot Actuator 在kubernetes中探针的应用
  • 原文地址:https://blog.csdn.net/wo541075754/article/details/127915498