创建新容器后,是否可以运行命令从主机获取容器的IP地址?

基本上,一旦Docker创建了容器,我就想滚动我自己的代码部署和容器配置脚本。


当前回答

如果您使用Docker工具箱安装Docker,则可以使用Kitematic应用程序获取容器IP地址:

选择容器单击设置在“端口”选项卡中单击。

其他回答

如果您想快速查看所有Docker IP地址,或者不键入实例名称,可以破解Docker ps命令,将其添加到~/.bashrc文件中:

function docker-ips() {
    docker ps | while read line; do
        if `echo $line | grep -q 'CONTAINER ID'`; then
            echo -e "IP ADDRESS\t$line"
        else
            CID=$(echo $line | awk '{print $1}');
            IP=$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" $CID);
            printf "${IP}\t${line}\n"
        fi
    done;
}

这来自Andrew Johnstone在Docker GitHub上的提议:https://github.com/docker/docker/issues/8786

for containerId in $(sudo docker ps -a | cut -f1 -d' ' | grep -v CONTAINER); do
    echo " ContainerId - $containerId >>  $(sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' $containerId) "
done

使用任意字符串提取IP:

我在这个问题中读到的许多(几乎所有)解决方案都需要用户首先识别<容器名称>或<容器ID>,然后将其提供给他们的解决方案以显示IP的中间步骤。

当容器被重新创建时,IP可以改变,如果发生这种情况,引用它的任何脚本现在都将被破坏。。。。

因此,我需要一种无需手动干预即可提取容器IP的方法,确保脚本始终具有正确的IP,即使每次重新创建容器时都会更改。

解决方案:

#!/bin/bash

# Only need to set "CONTAINERNAME" variable with an arbitrary
# string found in either the Container ID or Image Name and
# it prints container IP. Ensure the string is unique to desired host

CONTAINERNAME='mariadb-blog'
CONTAINERID="$(docker ps | grep -i $CONTAINERNAME | awk '{print $1}')"
CONTAINERIP="$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $CONTAINERID)"

echo "$CONTAINERIP"

结论:

我已经用自己的Linux Docker Compose主机测试了这个脚本,截至20220722年,它运行可靠。事实上,很容易复制并粘贴脚本,以验证我的结果是否可复制。

请注意:有一个潜在的可靠性弱点:如果你不剪切自己的docker图像并依赖第三方的图像,他们可能会更改图像的命名惯例,并打破脚本中的grep。因此,我建议将任意字符串设置为ContainerName,因为您可以控制它,确保字符串的grep始终成功,并打印IP以提供给脚本。

这对我有用,我正在运行docker工具箱18.09.3,在windows 10家庭版:

键入命令“docker machine ls”

λdocker机器lsNAME活动驱动程序状态URL群集DOCKER错误default*virtualbox正在运行tcp://192.168.98.100:2376版本8.09.6

它将在URL列下显示实际IP。例如,“192.168.98.100”

公认的答案很好地涵盖了要键入的内容,但这里有一个小的改进:

docker container inspect \
  --format '{{range .NetworkSettings.Networks}}{{.IPAddress}} {{end}}' \
  $container_id_or_name

这使用docker容器inspect而不是更通用的docker inspect,因为docker在其命令中使用了名词+动词语法,并消除了所检查内容的歧义。我还在IP地址后面加了一个空格,因为容器可以位于多个具有多个IP地址的docker网络上。可以将其替换为对您有意义的任何其他字符或字符串。


对于那些想知道如何查找其他值的人,我经常使用以下方法将任何docker格式的语法输出为json:

docker container inspect --format '{{json .}}' $container_id_or_name | jq .

您可能需要安装jq才能正常工作,或者您可以不使用尾随命令,将json作为一个单行读取。在查看此输出时,您可以看到每个键的名称及其父级,这样您就可以创建自己的格式字符串来输出所需的任何内容。格式语法是用golang的模板实现的,其中包含一些额外的docker特定函数。


基本上,一旦Docker创建了容器,我就想滚动我自己的代码部署和容器配置脚本。

我回答的主要原因是,这条评论给我带来了一个巨大的危险。它表明您的图像不包含运行应用程序所需的所有内容,在处理容器时,这是一个很大的反模式。多年来,我有十几个客户,但我还没有找到一个真正的用例,可以通过docker主机的内部IP地址直接连接到容器,这是没有更好的选择的。相反,如果容器中有启动后配置需要运行,则通常使用入口点脚本来完成。

还有一个危险信号,你正在绕过docker的网络模型。对于docker网络,有两种选择。首先,在容器之间进行通信时,这是通过用户创建的网络完成的,并使用docker的内置DNS通过名称或网络别名连接到容器,而不是通过重新创建容器时会更改的IP地址。对于从docker外部到容器的通信,这是通过将端口从docker主机发布到容器,然后连接到该端口上的主机而不是直接连接到容器来完成的。如果您坚持使用这两个选项,您应该能够在不知道其内部IP地址的情况下访问应用程序。