docker与gosu(1),大厂面试必问

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Golang全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注go)
img

正文

既然不能用root账号,那就要创建其他账号来运行进程了,以redis官方镜像的Dockerfile为例,来看看如何创建账号,如下图,地址是:https://github.com/docker-library/redis/blob/6845f6d4940f94c50a9f1bf16e07058d0fe4bc4f/5.0/Dockerfile

在这里插入图片描述

可见redis官方镜像使用groupadd和useradd创建了名为redis的组合账号,接下来就是用redis账号来启动服务了,理论上应该是以下套路:

  1. 用USER redis将账号切换到redis;

  2. 在docker-entrypoint.sh执行的时候已经是redis身份了,如果遇到权限问题,例如一些文件只有root账号有读、写、执行权限,用sudo xxx命令来执行即可;

但事实并非如此!

在Dockerfile脚本中未发现USER redis命令,这意味着执行docker-entrypoint.sh文件的身份是root;

其次,在docker-entrypoint.sh中没有发现su - redis命令,也没有sudo命令;

这是怎么回事呢?难道容器内的redis服务是用root账号启动的?

确认redis服务的启动账号

还是自己动手来证实一下吧,我的环境信息如下:

操作系统:CentOS Linux release 7.6.1810

Docker: 1.13.1

操作步骤如下:

  1. 启动一个redis容器:

docker run --name myredis -idt redis

  1. 进入容器:

docker exec -it myredis /bin/bash

  1. 在容器内,先更新apt:

apt-get update

  1. 安装ps命令:

apt-get install procps

  1. 执行命令ps -ef查看redis服务,结果如下:

root@122c2df16bbb:/data# ps -ef

UID PID PPID C STIME TTY TIME CMD

redis 1 0 0 09:22 ? 00:00:01 redis-server *:6379

root 287 0 0 09:36 ? 00:00:00 /bin/bash

root 293 287 0 09:39 ? 00:00:00 ps -ef

上面的结果展示了两个关键信息:

第一,redis服务是redis账号启动的,并非root;

第二,redis服务的PID等于1,这很重要,宿主机执行docker stop命令时,该进程可以收到SIGTERM信号量,于是redis应用可以做一些退出前的准备工作,例如保存变量、退出循环等,也就是优雅停机(Gracefully Stopping);

现在我们已经证实了redis服务并非root账号启动,而且该服务进程在容器内还是一号进程,但是我们在Dockerfile和docker-entrypoint.sh脚本中都没有发现切换到redis账号的命令,也没有sudo和su,这是怎么回事呢?

答案是gosu

再看一次redis的docker-entrypoint.sh文件,如下图,地址是:https://github.com/docker-library/redis/blob/6845f6d4940f94c50a9f1bf16e07058d0fe4bc4f/5.0/docker-entrypoint.sh

在这里插入图片描述

注意上图中的代码,我们来分析一下:

  1. 假设启动容器的命令是docker run --name myredis -idt redis redis-server /usr/local/etc/redis/redis.conf;

  2. 容器启动后会执行docker-entrypoint.sh脚本,此时的账号是root;

  3. 当前账号是root,因此会执行上图红框中的逻辑;

  4. 红框中的$0表示当前脚本的名称,即docker-entrypoint.sh;

  5. 红框中的$@表示外部传入的所有参数,即redis-server /usr/local/etc/redis/redis.conf;

  6. gosu redis “$0” “@”,表示以redis账号的身份执行以下命令:

docker-entrypoint.sh redis-server /usr/local/etc/redis/redis.conf

  1. gosu redis “$0” "@"前面加上个exec,表示以gosu redis “$0” "@"这个命令启动的进程替换正在执行的docker-entrypoint.sh进程,这样就保证了gosu redis “$0” "@"对应的进程ID为1;

  2. gosu redis “ 0 ” " @ " 导致 d o c k e r − e n t r y p o i n t . s h 再执行一次,但是当前的账号已经不是 r o o t 了,于是会执行兜底逻辑 e x e c “ 0” "@"导致docker-entrypoint.sh再执行一次,但是当前的账号已经不是root了,于是会执行兜底逻辑 exec “ 0”"@"导致dockerentrypoint.sh再执行一次,但是当前的账号已经不是root了,于是会执行兜底逻辑exec@”;

  3. 此时的$@是redis-server /usr/local/etc/redis/redis.conf,因此redis服务会启动,而且账号是redis;

  4. $@前面有个exec,会用redis-server命令启动的进程取代当前的docker-entrypoint.sh进程,所以,最终redis进程的PID等于1,而docker-entrypoint.sh这个脚本的进程已经被替代,因此就结束掉了;

关于gosu

通过上面的分析,我们对gosu的作用有了基本了解:功能和sudo类似,提升指定账号的权限,用来执行指定的命令,其官网地址是:https://github.com/tianon/gosu ,如下图所示,官方的描述也是说su和sudo命令有一些问题,所以才有了gosu工具来作为替代品:

在这里插入图片描述

在docker的官方文档中,也见到了gosu的使用示例,和前面的redis很像,如下图,地址是:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

在这里插入图片描述

注意上图中底部的那段话:使用exec XXX命令以确保XXX对应的进程的PID保持为1,这样该进程才能收到宿主机发送给容器的信号量;

为什么要用gosu取代sudo?

前面主要讲gosu的用法,但是为什么要用gosu呢?接下来通过实战对比来看看sudo的问题在哪:

  1. 执行以下命令创建一个容器:

docker run --rm gosu/alpine gosu root ps aux

上述命令会启动一个安装了gosu的linux容器,并且启动后自动执行命令gosu root ps aux,作用是以root账号的身份执行ps aux,也就是将当前进程都打印出来,执行结果如下:

[root@centos7 ~]# docker run --rm gosu/alpine gosu root ps aux

PID USER TIME COMMAND

1 root 0:00 ps aux

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-b4A7Ylzs-1713298570274)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux和Docker面试中经常被问到的话题,下面是一些常见的Linux和Docker面试问题及回答: 1. Linux面试问题: - 什么是Linux操作系统? Linux是一种开源的、类Unix的操作系统,它具有高度的稳定性、安全性和可靠性。 - 什么是Linux文件系统? Linux文件系统是Linux操作系统用来组织和管理文件的一种方式,它采用层次化的目录结构,以树状结构组织文件和目录。 - 如何查看Linux系统的硬件信息? 可以使用命令`lshw`或`dmidecode`来查看Linux系统的硬件信息。 - 如何查看Linux系统的进程信息? 可以使用命令`ps`或`top`来查看Linux系统的进程信息。 2. Docker面试问题: - 什么是DockerDocker是一个开源的容器化平台,可以将应用程序及其依赖打包成一个独立的容器,实现应用程序在不同环境中的快速部署和运行。 - Docker与虚拟机的区别是什么? 虚拟机是通过模拟硬件来实现隔离,而Docker是通过容器化技术来实现隔离,容器化更加轻量级、启动更快、资源占用更少。 - Docker镜像和容器的关系是什么? Docker镜像是一个只读的模板,包含了运行应用程序所需的文件系统和依赖。Docker容器是从镜像创建的运行实例,可以被启动、停止、删除等操作。 - 如何在Docker中部署一个应用程序? 首先需要编写一个Dockerfile,定义应用程序的环境和依赖;然后使用`docker build`命令构建镜像;最后使用`docker run`命令创建并运行容器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值