前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一步步学KubeVirt CI (3) - gosu在容器中的使用

一步步学KubeVirt CI (3) - gosu在容器中的使用

作者头像
后端云
发布2022-11-25 16:16:42
1.1K0
发布2022-11-25 16:16:42
举报
文章被收录于专栏:后端云后端云

gosu在容器中的使用

容器中使用gosu的起源来自安全问题,容器中运行的进程,如果以root身份运行的会有安全隐患,该进程拥有容器内的全部权限,更可怕的是如果有数据卷映射到宿主机,那么通过该容器就能操作宿主机的文件夹了,一旦该容器的进程有漏洞被外部利用后果是很严重的。因此,容器内使用非root账号运行进程才是安全的方式。gosu类似linux中的su和sudo命令。但是既然有了su和sudo为何还要做出一个gosu来。因为:

  1. gosu启动命令时只有一个进程,所以docker容器启动时使用gosu,那么该进程可以做到PID等于1;
  2. sudo启动命令时先创建sudo进程,然后该进程作为父进程去创建子进程,1号PID被sudo进程占据;

拿经典的redis镜像举例

首先得了解RUN CMD ENTRYPOINT区别

三者的共同点是:都是执行命令;都有两种格式Shell格式和Exec格式。

不同点是:RUN命令执行命令并创建新的镜像层,通常用于安装软件包。CMD ENTRYPOINT是设置容器启动后默认执行的命令其参数且他们的组合官网有个说明。

No ENTRYPOINT

ENTRYPOINT exec_entry p1_entry

ENTRYPOINT [“exec_entry”, “p1_entry”]

No CMD

error, not allowed

/bin/sh -c exec_entry p1_entry

exec_entry p1_entry

CMD [“exec_cmd”, “p1_cmd”]

exec_cmd p1_cmd

/bin/sh -c exec_entry p1_entry

exec_entry p1_entry exec_cmd p1_cmd

CMD [“p1_cmd”, “p2_cmd”]

p1_cmd p2_cmd

/bin/sh -c exec_entry p1_entry

exec_entry p1_entry p1_cmd p2_cmd

CMD exec_cmd p1_cmd

/bin/sh -c exec_cmd p1_cmd

/bin/sh -c exec_entry p1_entry

exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

所以下面的Dockfile,docker-entrypoint.sh是0,redis-server是1

Dockfile

代码语言:javascript
复制
FROM alpine:3.4...RUN addgroup -S redis && adduser -S -G redis redis...ENTRYPOINT ["docker-entrypoint.sh"]EXPOSE 6379CMD [ "redis-server" ]
代码语言:javascript
复制
...RUN addgroup -S redis && adduser -S -G redis redis...

上面的需要root处理的步骤放这一段,后面启动redis-server用了非root用户启动。原因是下面的docker-entrypoint.sh脚本:

entrypoint.sh

代码语言:javascript
复制
#!/bin/sh...# allow the container to be started with `--user`if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
	find . \! -user redis -exec chown redis '{}' +	exec gosu redis "$0" "$@"fiexec "$@"

上面的代码有一层递归。

检测到root用户启动redis命令redis-server,就会做两件事:

  1. 找到当前目录的所有非redis用户文件并将找出的全部文件改成redis所有,find . \! -user redis是找出当前目录的所有非redis用户文件,-exec chown redis '{}' +是将找出的文件修改成redis用户所有。
  2. exec gosu redis "

第二次执行CMD+ENTRYPOINT,因为是redis用户执行的,所以不进入if语句,直接exec "

该脚本的内容就是根据 CMD 的内容来判断,如果是 redis-server 的话,则切换到 redis 用户身份启动服务器,否则依旧使用 root 身份执行。比如:

代码语言:javascript
复制
$ docker run -it redis iduid=0(root) gid=0(root) groups=0(root)

附 为何要用gosu代替sudo

sudo as it has unpredictable TTY and signal-forwarding behavior that can cause problems

上面是docker官方best practices提到的 https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user

gosu官方仓库有一段回复 https://github.com/tianon/gosu#gosu

su & gosu

代码语言:javascript
复制
$ docker run -it --rm ubuntu:trusty su -c 'exec ps aux'USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  46636  2688 ?        Ss+  02:22   0:00 su -c exec ps a
root         6  0.0  0.0  15576  2220 ?        Rs   02:22   0:00 ps aux
$ docker run -it --rm ubuntu:trusty sudo ps auxUSER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  3.0  0.0  46020  3144 ?        Ss+  02:22   0:00 sudo ps aux
root         7  0.0  0.0  15576  2172 ?        R+   02:22   0:00 ps aux
$ docker run -it --rm -v $PWD/gosu-amd64:/usr/local/bin/gosu:ro ubuntu:trusty gosu root ps auxUSER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   7140   768 ?        Rs+  02:22   0:00 ps aux

sudo: Why does sudo call fork() and exec() rather than just exec()?

If sudo merely called exec, then sudo couldn’t do things like run any cleanup tasks when the exec’d code completed. Take pam_open_session and pam_close_session for example.

https://linux.die.net/man/3/pam_open_session https://linux.die.net/man/3/pam_close_session

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-07-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端云 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • gosu在容器中的使用
  • 拿经典的redis镜像举例
    • 首先得了解RUN CMD ENTRYPOINT区别
      • Dockfile
        • entrypoint.sh
        • 附 为何要用gosu代替sudo
          • su & gosu
            • sudo: Why does sudo call fork() and exec() rather than just exec()?
            相关产品与服务
            云数据库 Redis
            腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档