【Docker学习】深入研究命令docker exec

使用docker的过程中,我们会有多重情况需要访问容器。比如希望直接进入MySql容器执行命令,或是希望查看容器环境,进行某些操作或访问。这时就会用到这个命令:docker exec。

命令:

docker container exec

描述:

在运行的容器中执行命令。

您使用 docker exec 指定的命令只会在容器的首要进程(PID 1)运行时执行,如果容器重启,该命令不会被重新启动。

该命令在容器的默认工作目录中运行。

该命令必须是一个可执行程序。链式命令或引号内的命令不起作用

这样是有效的:docker exec -it my_container sh -c "echo a && echo b"

这样是无效的:docker exec -it my_container "echo a && echo b"

用法:

复制代码
docker container exec [OPTIONS] CONTAINER COMMAND [ARG...]

别名:

docker exec(docker的一些命令可以简写,docker exec和docker container exec是等价的)

选项:

选项 描述
-d, --detach 分离模式:在后台运行命令
--detach-keys 覆盖用于分离容器的键序列
-e, --env API 1.25+ 设置环境变量
--env-file 读取的环境变量文件
-i, --interactive 即使未附着也保持 STDIN 打开
--privileged 为命令提供扩展权限
-t, --tty 分配一个伪TTY
-u, --user 用户名或用户ID(格式:<name|uid>[:<group|gid>])
-w, --workdir 容器内的工作目录

示例1:选项-d, --detach、-i, --interactive、-t, --tty

-d相当于后台运行,使用这个选项,不影响终端的进一步操作。-i和-t两个选项通常一起使用,在【Docker学习】docker run之黄金搭档-it选项 -- 筑天兄的清净小站 (skycreator.top)有详细介绍。

关于这三个选项,官方给出的例子挺好。我就直接使用官方例子,在我的阿里云上操作,借花献佛了。

使用exec,首先要确保有一个运行着的容器。使用以下命令创建并启动一个名为mycontainer的基于alpine的容器,该容器以sh shell作为其主进程。其中,-d选项(--detach的简写形式)会让容器以后台运行的方式启动,即分离模式,并附加一个伪TTY(-t)。-i选项设置为保持STDIN附加(-i),这可以防止sh进程立即退出。

复制代码
docker run --name mycontainer -d -i -t alpine /bin/sh

执行之后,使用ps来查看一下:

在这之后,我们使用-d选项,在运行的mycontainer容器中运行一个命令touch /tmp/execWorks。该命令在容器的根目录tmp下创建execWorks文件。

复制代码
docker exec -d mycontainer touch /tmp/execWorks

这条命令执行之后没效果,需要进入容器的sh下查看。使用-it选项(-i加-t选项),直接与容器交互。

复制代码
docker exec -it mycontainer sh

在容器的终端进入tmp文件夹查看,发现execWorks被创建。

示例2:选项--detach-keys

这个选项说起来比较复杂,在【Docker学习】docker start深入研究 -- 筑天兄的清净小站 (skycreator.top)中有详细讲解,大家可以对照着来学习。

示例3:选项-e, --env和选项--env-file

这两个选项都是设置环境变量的,前者是直接设置,后者是通过一个文件设置。在【Docker学习】docker run的环境变量相关选项(-e, --env, --env-file) -- 筑天兄的清净小站 (skycreator.top)中有详细讲解,这个不再赘述了。

示例4:--privileged

这个选项用于提升容器权限,它为容器提供了以下功能:

  • 启用所有Linux内核功能
  • 禁用默认的seccomp配置文件
  • 禁用默认的AppArmor配置文件
  • 禁用SELinux进程标签
  • 授予访问所有主机设备的权限
  • 使/sys变为可读写
  • 使cgroups挂载变为可读写

换句话说,容器几乎可以做主机能做的任何事情。这个标志的存在是为了允许特殊用途,比如在Docker中运行Docker。

这个选项很强大,未来详细讲解,这里只简要介绍。

我们使用刚才的容器作测试,进入容器的终端,执行命令

复制代码
docker exec -it mycontainer sh

在终端输入以下命令,将一个tmpfs文件系统挂载到/mnt目录,允许在这个目录下存储临时数据,这些数据在系统重启后不会保留。

复制代码
/ # mount -t tmpfs none /mnt

这个命令具体作用如下:

  • mount:这是用来挂载文件系统的命令。
  • -t tmpfs:这指定了要挂载的文件系统类型为tmpfs,这是一种基于内存的文件系统,也称为临时文件系统。数据存储在内存中,而不是写入磁盘,这意味着它的读写速度非常快,但数据在系统重启后会丢失。
  • none:这里指定了设备的源,none表示没有实际的设备或文件名与tmpfs关联。因为tmpfs不依赖于具体的设备,所以使用none作为占位符。
  • /mnt:这是挂载点,即文件系统在目录树中的位置。在这个例子中,tmpfs将被挂载到/mnt目录下。

看看运行结果。显示permission denied,说明没有权限。默认情况下,Docker会丢弃大多数可能危险的核心功能,包括CAP_SYS_ADMIN(挂载文件系统所必需的)。

那么我们执行--privileged选项看看。

**居然没有效果!!!**好吧,看来只能放大招了。

官网讲解--privileged选项时,也讲解了docker run 的--cap-add选项,该选项可以为容器添加linux功能。而SYS-ADMIN是linux系统管理必备的功能。因此我使用该选项,先给mycontainer加入这个功能。

复制代码
docker run --cap-add SYS_ADMIN --name mycontainer -dit  alpine /bin/sh

执行之后,我尝试进行挂载,这次成功了。通过df -h命令查看文件系统磁盘空间使用情况。可以看到最下面一行,文件系统是none的就是我进行的挂载。不过这么做也用不着--privileged选项了。

官网的例子使用的并不是alpine,而是ubuntu。通过对比--privileged使用与否的情况,可以看到ubuntu的/dev目录发生了明显的变化:

上面是不使用--privileged选项的/dev目录。

上面是使用--privileged选项的/dev目录。

可以明显看出两者的不同,说明使用--privileged选项,为/dev目录增加了不少特性。

回过头再来看alpine,使用不使用/dev的目录是相同的。如下图所示:

也就是说,alpine这个镜像并没有为--privileged选项预留功能。毕竟alpine是阉割版的linux系统,它的大小只有4m多。下面是几个linux官方镜像的大小对比。

另外,docker run的--cap-add选项,没有加入到docker exec中,可能是因为这只能是创建时加入,运行中的容器是不能直接设置的。

示例5:-u, --user选项

这个选项用于以某个用户身份进入容器。

还是使用alpine这个镜像的mycontainer容器,进入容器的shell下,添加一个普通用户zl

复制代码
adduser zl

然后exit退出,重新使用docker exec进入,这次加入-u选项

复制代码
docker exec -it -u zl  mycontainer sh

在shell中输入id,查看当前用户的信息

可以看出,当前用户是zl,uid,gid和groups均显示出来了。

示例6:-w, --workdir选项

该选项用于设置容器的工作目录。不指定的情况下,工作目录就是/,如下图所示:

下面指定了工作目录为/etc,使用pwd查看当前工作目录,即是/etc。

关于alpine

Alpine是一个轻量级的Linux发行版,它基于musl libc和 BusyBox,旨在提供一个小巧、安全、简单且高效的操作系统。Alpine特别适合用于容器和云环境,因为它的大小很小,启动速度快,同时提供了一个包管理器工具apk,可以用来安装、更新和管理软件包。

在Docker等容器平台中,Alpine经常被用作基础镜像,因为它可以创建出非常小的容器镜像,这对于开发和部署都非常有利。由于它的体积小,Alpine在资源有限的场景下也非常受欢迎,比如在嵌入式设备或者需要快速部署的应用中。

Alpine 官网:https://www.alpinelinux.org/
Alpine 官方仓库:https://github.com/alpinelinux

Alpine 官方镜像:https://hub.docker.com/_/alpine/

Alpine 官方镜像仓库:https://github.com/gliderlabs/docker-alpine

关于--privileged

请谨慎使用--privileged标志。带有--privileged的容器并不是一个安全沙箱化的进程。在此模式下的容器可以在主机上获取root权限的shell并控制系统。

对于大多数用例来说,这个标志不应该是首选解决方案。如果您的容器需要提升的权限,您应该更愿意明确授予必要的权限,例如通过使用--cap-add添加单个内核功能。

关于df -h命令

在Linux和类Unix操作系统中,df -h是一个常用的命令,用于显示文件系统的磁盘空间使用情况。df代表disk free,即磁盘空闲空间。-h选项表示human-readable,它会以更易于阅读的格式显示大小,例如将字节转换为千字节、兆字节或吉字节,并附加适当的单位(K、M、G)。

df -h命令的输出通常包括以下信息:

  • 文件系统的挂载点(Mounted on)
  • 文件系统的总大小(Size)
  • 已使用的空间大小(Used)
  • 可用的空闲空间(Avail)
  • 使用百分比(Use%)
  • 文件系统的标识(Filesystem)
相关推荐
早睡冠军候选人16 小时前
Ansible学习----管理复杂的 Play 和 Playbook 内容
运维·学习·云原生·ansible
LBuffer17 小时前
破解入门学习笔记题四十六
数据库·笔记·学习
Yurko1319 小时前
【计网】基于三层交换机的多 VLAN 局域网组建
网络·学习·计算机网络·智能路由器
月下倩影时20 小时前
视觉进阶篇——机器学习训练过程(手写数字识别,量大管饱需要耐心)
人工智能·学习·机器学习
旦沐已成舟20 小时前
K8S中修改apiserver地址
云原生·容器·kubernetes
MasterLi80231 天前
我的读书清单
android·linux·学习
hssfscv1 天前
JAVA学习笔记——集合的概念和习题
笔记·学习
ha20428941941 天前
Linux操作系统学习之---初识网络
linux·网络·学习
hakukun1 天前
docker避免每次sudo方法
运维·docker·容器
杨凯凡1 天前
Docker Compose:多容器应用编排入门与实战
运维·docker·容器