我不确定我是否在这里误解了某些东西,但似乎只能通过从图像创建新容器来设置端口映射。有没有办法将端口映射分配给现有的 Docker 容器?
15 回答
我也对这个问题感兴趣。
正如@Thasmo提到的,端口转发只能使用docker run
(and docker create
) 命令指定。
其他命令,docker start
没有-p
选项,docker port
只显示当前转发。
要添加端口转发,我总是按照以下步骤操作,
停止运行容器
docker stop test01
提交容器
docker commit test01 test02
注意:以上
test02
是我从test01
容器中构建的新图像。从提交的图像重新运行
docker run -p 8080:8080 -td test02
其中第一个 8080 是本地端口,第二个 8080 是容器端口。
您可以通过直接编辑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”字段的值是哈希值。
- 停止容器 (
docker stop <container_name>
)。 - 停止 docker 服务(根据 Tacsiazuma 的评论)
- 更改文件。
- 重新启动您的 docker 引擎(以刷新/清除配置缓存)。
- 启动容器 (
docker start <container_name>
)。
因此,您不需要使用这种方法创建图像。您还可以在此处更改重新启动标志。
PS 您可以访问https://docs.docker.com/engine/admin/了解如何根据您的主机正确重启您的 docker 引擎。我曾经sudo systemctl restart docker
重新启动在 Ubuntu 16.04 上运行的 docker 引擎。
如果“现有”是指“正在运行”,那么(当前)不可能添加端口映射。
但是,如果您需要在正在运行的容器中公开服务而不停止/重新启动它,您可以使用例如Pipework动态添加新的网络接口。
在 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现在似乎不起作用。它仅以该端口被公开但未发布到主机结束。提交和重新创建容器对我来说不是最好的方法。没有人提到docker network
?
最好的解决方案是在同一网络中使用反向代理
如果您以前的容器不在任何命名的容器中,请创建一个新网络。
docker network create my_network
将现有容器加入创建的网络
docker network connect my_network my_existing_container
启动反向代理服务(例如 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
创建一个新的 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
重启nginx
docker restart nginx
优点:要发布新端口,您可以安全地停止/更新/重新创建 nginx 容器,而无需接触业务容器。如果您需要 nginx 零停机时间,可以添加更多反向代理服务加入同一网络。此外,一个容器可以加入多个网络。
编辑:
要反向代理非 http 服务,配置文件有点不同。这是一个简单的例子:
upstream my_service {
server my_existing_container:9000;
}
server {
listen 9000;
proxy_pass my_service;
}
如果您运行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,它应该可以工作。
如果您对 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}
这只是一个技巧,不是推荐的方式。这适用于我的场景,因为我无法停止容器。
不确定是否可以将端口映射应用到正在运行的容器。您可以在运行与创建新容器不同的容器时应用端口转发。
$ docker run -p <public_port>:<private_port> -d <image>
将开始运行容器。本教程解释了端口重定向。
我们使用 ssh 等方便的工具来轻松完成此任务。
我使用的是 ubuntu 主机和基于 ubuntu 的 docker 镜像。
- 在 docker 内部安装了 openssh-client。
- 外部 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对此进行了测试。
在 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 的回答。
- 停止 docker 引擎和该容器。
- 转到
/var/lib/docker/containers/${container_id}
目录并编辑hostconfig.json
- 编辑
PortBindings.HostPort
您想要更改的内容。 - 启动 docker 引擎和容器。
我正在开发一个 dockerizer go 包,用于在 docker 容器中部署批处理应用程序。我的包包含一个 MessageBroker 组件,它有 3 个要发布的端口:jobAgentPort、backendPort、frontendPort。
长话短说,我建议最好设计一个嵌入到服务器/代理/代理中的 endpointProvider 组件。
也就是说,容器部署至少是一个 2 步过程。
- endpointProvider 组件由 jobId 或类似 key 创建并缓存在相关包中。
- server/proxy/broker 内置在二进制文件中,您的代码在其中接受由 endpointProvider 输出的 endpointConfig 组件。
例如 server/proxy/broker 构造函数有一个签名:
NewMessageBroker(epc *EndpointConfig) *MessageBroker
. 然后,使用 docker-client api 创建容器映像,最后启动容器(docker run)并使用公开端口值的 endpointConfig 发布端口。
对于 Windows 和 Mac 用户,还有另一种非常简单友好的方法来更改映射端口:
下载风筝
进入容器的设置页面,在端口选项卡上,您可以直接在此处修改已发布的端口。
再次启动容器
“docker run -p 8761:8761 --name <containerName(或任何名称)> <image_Name> 。”
如何将端口映射分配给现有的 Docker 容器?
这很简单。有两件事,一是您机器上的本地服务器端口,如 800,8080 等,第二件事是您要映射的容器端口。Docker 端口映射
docker run -p 8080:8080 <Image ID>
要获取图像 ID,您可以使用
docker ps