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

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

758922 次浏览

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

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

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

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

然而,你可以动态地添加一个新的网络接口,例如管道工程,如果你需要在一个运行的容器中公开一个服务,而不需要停止/重新启动它。

我对这个问题也很感兴趣。

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

要添加端口转发,我总是遵循以下步骤,

  1. 停止运行容器

    docker stop test01
    
  2. commit the container

    docker commit test01 test02
    

    上面的test02是我从test01容器中构建的新图像

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

    docker run -p 8080:8080 -td test02
    

Where the first 8080 is the local port and the second 8080 is the container port.

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

在执行docker run之前,你可以删除原来的容器,然后重新为容器分配相同的名称:

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

(使用-P将端口暴露给随机端口,而不是手动分配)。

您可以通过直接编辑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作为一个snap

您可以通过docker inspect <container_name>命令确定[hash_of_the_container]和"Id"字段是哈希值。

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

所以你不需要用这种方法创建一个图像。您还可以在这里更改重启标志。

# EYZ1。

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

  1. 下载kitematic

  2. 进入容器的“设置”页面,在“端口”页签中,可以直接在那里修改已发布的端口。

  3. 再次启动容器

如果你不适应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}

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

编辑hostconfig.json现在似乎不工作。它只以暴露该端口而不将其发布到主机而结束。提交和重新创建容器对我来说不是最好的方法。没人提到docker network?

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

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

    # EYZ0 < / p >

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

    # EYZ0 < / p >

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

    # EYZ0

    可选地删除nginx中的default.conf

    # EYZ0 < / p >

  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容器。

    # EYZ0 < / p >

  5. < p >重启nginx

    # EYZ0 < / p >

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

编辑:

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

upstream my_service {
server my_existing_container:9000;
}


server {
listen 9000;
proxy_pass my_service;
}

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

如果你想改变当前的图像,请执行以下操作:

# EYZ0

获取目标容器的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,它应该可以工作。

我们可以使用方便的工具,如SSH来轻松完成这一任务。

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

  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测试过了。

  1. 停止docker引擎和容器。
  2. 进入/var/lib/docker/containers/${container_id}目录,编辑hostconfig.json
  3. 编辑您想要更改的PortBindings.HostPort
  4. 启动码头引擎和容器。

使用实例在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。按# EYZ2。
  • 现在不要启动/停止docker101tutorial。否则,对HostPort的更改将被恢复。
  • 右键单击Docker桌面托盘图标,然后单击“重新启动”。
  • 在Docker Desktop的容器列表中,查看您的容器。显示的端口应该改为8092
  • 启动容器。现在它将被映射到主机上的端口8092

基于@holdfenytolvaj的答案。

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

这很简单。有两件事,一个是本地服务器端口,如800,8080等在你的机器上,第二个是你的容器端口,你想映射。# EYZ0

 docker run -p 8080:8080 <Image ID>

要获得图像Id,您可以使用

docker ps

我的容器有这样的情况:

127.0.0.1:8050->8000

我用一个iptalbes规则解决了这个问题

iptables -t nat -I DOCKER 1 -p tcp --dport ${HOST_PORT} -j DNAT --to-destination ${CONTAINER_IP}:${CONTAINER_PORT}

在本例中,HOST_PORT为8050,CONTAINER_PORT为8000。要找到CONTAINER_IP,使用docker inspect命令。

要删除iptables规则,使用以下命令:

iptables -t nat -D DOCKER 1

集装箱岸吊法

如果有人正在使用portainer,我发现这个解决方案是“Gui友好和安全”。

  1. 去Portainer的集装箱
  2. 停止容器
  3. 选择“复制/ Edit" # EYZ0
  4. 添加所需的端口并进行部署。
  5. 当被问到是替换还是取消时,选择替换
  6. 享受生活