Docker - Ubuntu - bash:ping命令未找到。

681
我正在运行一个Ubuntu的Docker容器,步骤如下:
docker run -it ubuntu /bin/bash

然而,它似乎没有ping。例如:

bash: ping: command not found

我需要安装那个吗?

这似乎是一个非常基本的命令,但却不见了。我尝试了whereis ping,但没有任何报告。


13
Docker镜像能够保持精简是非常合适的。在大多数情况下,容器永远只会运行单个应用程序 -- 为什么要安装该应用程序不需要的东西呢? - Charles Duffy
这个问题不仅仅存在于Docker镜像中,Ubuntu 22.X最小服务器安装程序镜像中也存在同样的问题(可能其他版本也有)。我是说,谁会在他们的服务器上需要IP工具呢? - undefined
8个回答

1327

Docker镜像相当精简,但是您可以通过以下方式在官方Ubuntu Docker镜像中安装ping

apt-get update -y
apt-get install -y iputils-ping

很可能您不需要在图像上使用 ping 命令,只是想用它进行测试。上面的示例将帮助您。

但如果您需要在您的图像上存在 ping 命令,则可以创建一个 Dockerfile 或将运行上述命令的容器 commit 到新的镜像中。

Commit:

docker commit -m "Installed iputils-ping" --author "Your Name <name@domain.com>" ContainerNameOrId yourrepository/imagename:tag

Dockerfile:

FROM ubuntu
RUN apt-get update && apt-get install -y iputils-ping
CMD bash
请注意,创建Docker镜像有最佳实践,例如在完成后清除apt缓存文件等。

apt-get失败,显示“临时解析' security.ubuntu.com' 的错误”,很显然是因为网络连接不可用。 - Pavel Niedoba
我已经养成了使用“apt install”的习惯,结果出现了“未找到软件包”的情况,但正如答案所说的那样,“apt-get”完全可以胜任。 - a2k42
1
如果您需要在正在运行的容器上安装,则需要使用root权限执行,因此请执行docker exec -u 0 -it <container> /bin/bash。其中“-u 0”表示用户root。 - Aldo Inácio da Silva
2
debian11: E: 无法定位软件包 iputils-ping :/ - jaques-sam
@jaques-sam 我刚在 Debian:11.5 镜像上尝试了一下,它可以工作。你之前有执行过 apt update 吗? - Farhad Farahi
是的,这是个好主意。除非你正在尝试调试为什么apt/apt-get失败了... - JHBonarius

72

这里是Ubuntu的Docker Hub页面,这里是它的创建方式。它只安装了(有点)最基本的软件包,因此如果需要其他软件包,您需要自己安装。

apt-get update && apt-get install -y iputils-ping

通常情况下,您需要创建一个"Dockerfile"并进行构建:

mkdir ubuntu_with_ping
cat >ubuntu_with_ping/Dockerfile <<'EOF'
FROM ubuntu
RUN apt-get update && apt-get install -y iputils-ping
CMD bash
EOF
docker build -t ubuntu_with_ping ubuntu_with_ping
docker run -it ubuntu_with_ping

请使用Google查找教程并浏览现有的Dockerfile,以了解它们通常如何处理 :) 例如,在运行apt-get install命令后,应通过运行apt-get clean && rm -rf /var/lib/apt/lists/*来最小化镜像大小。

1
echo -e 实际上违反了 POSIX sh 标准(http://pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html),它只允许在输出中打印 -e。即使是在某些版本的 bash 中,这也是默认行为。使用 printf 替代:printf '%s\n' "FROM ubuntu" "RUN apt-get update && apt-get install -y iputils-ping" "CMD bash",并查看上述链接标准文档中的 APPLICATION USAGE 部分。 - Charles Duffy
即使是bash也不会像你期望的那样支持echo -e(但在POSIX模式下编译时将具有符合标准的行为),或者使用适当的环境变量或其他运行时配置。 - Charles Duffy
POSIX 允许 echo 在给定 -n 作为第一个参数或存在任何反斜杠文字时以实现定义的方式运行,但即使如此,它也是 实现定义,而不是标准保证,因此行为取决于使用的个别 shell。 - Charles Duffy
感谢您的评论和改进,"复制粘贴"友好的示例更多是事后想法。 - NikoNyrh

21

或者您可以使用已经安装了ping的Docker镜像,例如busybox

docker run --rm busybox ping SERVER_NAME -c 2

2
这是一个解决方案,但仅为了执行ping而创建图像似乎有些过度。我宁愿在需要它的镜像上使用“apt-get iputils-ping”。 - renatoaraujoc

13

一般人会拉取Ubuntu/CentOS的官方镜像,但他们可能没有意识到这些镜像是迷你版本,并且没有其他额外的内容。

对于Ubuntu,该镜像是由Canonical提供的官方rootfs tarballs构建而成。鉴于这是一个最小的Ubuntu安装,该镜像默认只包括C、C.UTF-8和POSIX本地设置。

可以在容器中安装net-tools(包括ifconfig、netstat)、ip-utils(包括ping)和curl等其他工具,并从容器创建镜像或编写Dockerfile,在创建镜像时安装这些工具。

以下是Dockerfile示例,从这个文件创建镜像将包括这些工具:

FROM vkitpro/ubuntu16.04
RUN     apt-get  update -y \
&& apt-get upgrade -y \
&& apt-get install iputils-ping -y \
&& apt-get install net-tools -y \
CMD bash
从基础镜像启动容器,然后在容器中安装这些工具,并提交到镜像中。 docker commit -m "任何描述性信息" 容器ID 镜像名称:最新版本
镜像将会拥有所有已安装的工具。

4

我在Debian 10上使用了以下语句。

apt-get install iputils-ping

4

有时,在Docker中最小化安装的Linux系统没有定义路径,因此需要使用...来调用ping。

cd /usr/sbin
ping <ip>

2
每次您遇到这种错误,它都会显示"最初的回答"。
bash: <command>: command not found
  • On a host with that command already working with this solution:

    dpkg -S $(which <command>)
    
  • Don't have a host with that package installed? Try this:

    apt-file search /bin/<command>
    

1
或者,您可以在进入容器的网络命名空间后,在主机上运行ping命令。
首先,在主机上找到容器的进程ID(可以是shell或者您在容器内部运行的应用程序)。然后切换到容器的网络命名空间(在主机上以root身份运行):
host# PS1='container# ' nsenter -t <PID> -n

修改PS1环境变量仅用于在容器的网络命名空间中显示不同的提示符。
现在,您可以使用pingnetstatifconfigip等命令,前提是它们已安装在主机上。
container# ping <IP>
container# ip route get <IP>
....
container# exit

请记住,这只改变了网络命名空间,挂载命名空间(文件系统)并没有改变,因此名称解析可能无法正常工作(它仍然使用主机上的/etc/hosts文件)。

1
非常迷人。谢谢你提供这个信息,我从未想到这是可能的。 - Aquarelle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接