620

我不确定我是否在这里误解了某些东西,但似乎只能通过从图像创建新容器来设置端口映射。有没有办法将端口映射分配给现有的 Docker 容器?

4

15 回答 15

581

我也对这个问题感兴趣。

正如@Thasmo提到的,端口转发只能使用docker run(and docker create) 命令指定。
其他命令,docker start没有-p选项,docker port只显示当前转发。

要添加端口转发,我总是按照以下步骤操作,

  1. 停止运行容器

    docker stop test01
    
  2. 提交容器

    docker commit test01 test02
    

    注意:以上test02是我从test01容器中构建的新图像。

  3. 从提交的图像重新运行

    docker run -p 8080:8080 -td test02
    

其中第一个 8080 是本地端口,第二个 8080 是容器端口。

于 2014-10-29T02:55:15.440 回答
416

您可以通过直接编辑hostconfig.json文件来更改端口映射, /var/lib/docker/containers/[hash_of_the_container]/hostconfig.json或者/var/snap/docker/common/var-lib-docker/containers/[hash_of_the_container]/hostconfig.json,我相信,如果您将 Docker 安装为快照。

您可以通过命令确定 [hash_of_the_container]docker inspect <container_name>并且“Id”字段的值是哈希值。

  1. 停止容器 ( docker stop <container_name>)。
  2. 停止 docker 服务(根据 Tacsiazuma 的评论)
  3. 更改文件。
  4. 重新启动您的 docker 引擎(以刷新/清除配置缓存)。
  5. 启动容器 ( docker start <container_name>)。

因此,您不需要使用这种方法创建图像。您还可以在此处更改重新启动标志。

PS 您可以访问https://docs.docker.com/engine/admin/了解如何根据您的主机正确重启您的 docker 引擎。我曾经sudo systemctl restart docker重新启动在 Ubuntu 16.04 上运行的 docker 引擎

于 2016-08-05T07:20:57.267 回答
64

如果“现有”是指“正在运行”,那么(当前)不可能添加端口映射。

但是,如果您需要在正在运行的容器中公开服务而不停止/重新启动它,您可以使用例如Pipework动态添加新的网络接口。

于 2013-10-17T02:34:33.037 回答
33

在 Fujimoto Youichi 的示例test01中是容器,而test02图像是图像。

在这样做之前,docker run您可以删除原始容器,然后再次为容器分配相同的名称:

$ docker stop container01
$ docker commit container01 image01
$ docker rm container01
$ docker run -d -P --name container01 image01

-P用于将端口公开给随机端口,而不是手动分配)。

于 2016-03-23T21:37:03.983 回答
29

编辑hostconfig.json现在似乎不起作用。它仅以该端口被公开但未发布到主机结束。提交和重新创建容器对我来说不是最好的方法。没有人提到docker network

最好的解决方案是在同一网络中使用反向代理

  1. 如果您以前的容器不在任何命名的容器中,请创建一个新网络。

    docker network create my_network

  2. 将现有容器加入创建的网络

    docker network connect my_network my_existing_container

  3. 启动反向代理服务(例如 nginx),发布你需要的端口,加入同一个网络

    docker run -d --name nginx --network my_network -p 9000:9000 nginx

    可选择删除nginx中的default.conf

    docker exec nginx rm /etc/nginx/conf.d/default.conf

  4. 创建一个新的 nginx 配置

    server
    {
        listen 9000;
    
        location / {
            proxy_pass http://my_existing_container:9000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
    

    将配置复制到 nginx 容器。

    docker cp ./my_conf.conf nginx:/etc/nginx/conf.d/my_conf.conf

  5. 重启nginx

    docker restart nginx

优点:要发布新端口,您可以安全地停止/更新/重新创建 nginx 容器,而无需接触业务容器。如果您需要 nginx 零停机时间,可以添加更多反向代理服务加入同一网络。此外,一个容器可以加入多个网络。

编辑:

要反向代理非 http 服务,配置文件有点不同。这是一个简单的例子:

upstream my_service {
    server my_existing_container:9000;
}

server {
    listen 9000;
    proxy_pass my_service;
}
于 2018-03-08T03:41:08.120 回答
27

如果您运行docker run <NAME>它,它将生成一个新图像,这很可能不是您想要的。

如果要更改当前图像,请执行以下操作:

docker ps -a

获取目标容器的 id 并转到:

cd /var/lib/docker/containers/<conainerID><and then some:)>

停止容器:

docker stop <NAME>

更改文件

vi config.v2.json

"Config": {
    ....
    "ExposedPorts": {
        "80/tcp": {},
        "8888/tcp": {}
    },
    ....
},
"NetworkSettings": {
....
"Ports": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],

并更改文件

vi hostconfig.json

"PortBindings": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],
     "8888/tcp": [
         {
             "HostIp": "",
             "HostPort": "8888"
         } 
     ]
 }

重新启动您的 docker,它应该可以工作。

于 2018-03-19T20:37:28.347 回答
24

如果您对 Docker 深度配置不满意,iptables 将是您的朋友。

iptables -t nat -A DOCKER -p tcp --dport ${YOURPORT} -j DNAT --to-destination ${CONTAINERIP}:${YOURPORT}

iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source ${CONTAINERIP} --destination ${CONTAINERIP} --dport ${YOURPORT}

iptables -A DOCKER -j ACCEPT -p tcp --destination ${CONTAINERIP} --dport ${YOURPORT}

这只是一个技巧,不是推荐的方式。这适用于我的场景,因为我无法停止容器。

于 2017-11-08T05:20:15.800 回答
21

不确定是否可以将端口映射应用到正在运行的容器。您可以在运行与创建新容器不同的容器时应用端口转发。

$ docker run -p <public_port>:<private_port> -d <image>  

将开始运行容器。本教程解释了端口重定向。

于 2013-10-13T13:05:23.000 回答
14

我们使用 ssh 等方便的工具来轻松完成此任务。

我使用的是 ubuntu 主机和基于 ubuntu 的 docker 镜像。

  1. 在 docker 内部安装了 openssh-client。
  2. 外部 docker(主机)安装了 openssh-server 服务器。

当需要映射一个新的端口时,

在 docker 内部运行以下命令

ssh -R8888:localhost:8888 <username>@172.17.0.1

172.17.0.1 是 docker 接口的 ip(你可以通过 ifconfig docker0 | grep "inet addr" | cut -f2 -d":" | cut -f1 -d" "在主机上运行来获得)。

在这里,我将本地 8888 端口映射回主机 8888。您可以根据需要更改端口。

如果您需要一个端口,您可以终止 ssh 并使用新端口再添加一行 -R 。

我已经用netcat对此进行了测试。

于 2018-10-12T13:05:52.537 回答
12

在 Docker Desktop 上更改容器的 HostPort(在 Windows 10 / MacOS 上)

# list all containers
$ docker ps -a
$ docker stop docker101tutorial 
# Use grep to get id of container
$ docker inspect docker101tutorial | grep -i id
        "Id": "sha256:fff0a4b22d6f3d2eb8d2748b8a8bbc9967ea87199988acee8e86ac70bce9c3eb",
# run plain ubuntu docker image with shell and change it's namespace to docker host
# https://stackoverflow.com/questions/60408574/how-to-access-var-lib-docker-in-windows-10-docker-desktop/60411313#60411313
# https://forums.docker.com/t/the-location-of-images-in-docker-for-windows/19647/4
$ docker run -it --privileged --pid=host ubuntu nsenter -t 1 -m -u -i sh
# We want to find out the directory of docker101tutorial container. We are looking for:
# `"Image":"sha256:fff0a4b22d6f3d2eb8d2748b8a8bbc9967ea87199988acee8e86ac70bce9c3eb"`
# in /var/lib/docker/containers/*/config.v2.json
$ find /var/lib/docker/containers/ -name config.v2.json -exec grep -H fff0a4b22d {} \;
/var/lib/docker/containers/c1eda20b30f058bce9f8ece3b47a21641df5b399770e12ab57416a954d3c8bbf/config.v2.json
# edit it
$ vi /var/lib/docker/containers/c1eda20b30f058bce9f8ece3b47a21641df5b399770e12ab57416a954d3c8bbf/hostconfig.json
  • i插入模式。
  • 更改"HostPort":"80""HostPort":"8092"
  • 按下Escape并写入:wq。按Enter
  • 现在不要启动/停止docker101tutorial。否则更改HostPort将被还原。
  • 右键单击 Docker 桌面托盘图标,然后单击重新启动。
  • 在 Docker Desktop 的容器列表中,查看您的容器。显示的端口应更改为8092
  • 启动你的容器。现在它将映射到8092主机上的端口。

基于@holdfenytolvaj 的回答。

于 2020-08-17T17:37:44.607 回答
4
  1. 停止 docker 引擎和该容器。
  2. 转到/var/lib/docker/containers/${container_id}目录并编辑hostconfig.json
  3. 编辑PortBindings.HostPort您想要更改的内容。
  4. 启动 docker 引擎和容器。
于 2019-07-30T11:59:30.857 回答
0

我正在开发一个 dockerizer go 包,用于在 docker 容器中部署批处理应用程序。我的包包含一个 MessageBroker 组件,它有 3 个要发布的端口:jobAgentPort、backendPort、frontendPort。

长话短说,我建议最好设计一个嵌入到服务器/代理/代理中的 endpointProvider 组件。

也就是说,容器部署至少是一个 2 步过程。

  1. endpointProvider 组件由 jobId 或类似 key 创建并缓存在相关包中。
  2. server/proxy/broker 内置在二进制文件中,您的代码在其中接受由 endpointProvider 输出的 endpointConfig 组件。

例如 server/proxy/broker 构造函数有一个签名: NewMessageBroker(epc *EndpointConfig) *MessageBroker. 然后,使用 docker-client api 创建容器映像,最后启动容器(docker run)并使用公开端口值的 endpointConfig 发布端口。

于 2021-04-14T06:35:44.107 回答
-1

对于 Windows 和 Mac 用户,还有另一种非常简单友好的方法来更改映射端口:

  1. 下载风筝

  2. 进入容器的设置页面,在端口选项卡上,您可以直接在此处修改已发布的端口。

  3. 再次启动容器

于 2017-02-23T10:07:36.570 回答
-3

“docker run -p 8761:8761 --name <containerName(或任何名称)> <image_Name> 。”

于 2021-06-17T00:14:38.140 回答
-7

如何将端口映射分配给现有的 Docker 容器?

这很简单。有两件事,一是您机器上的本地服务器端口,如 800,8080 等,第二件事是您要映射的容器端口。Docker 端口映射

 docker run -p 8080:8080 <Image ID> 

要获取图像 ID,您可以使用

docker ps
于 2021-07-20T06:16:22.113 回答