我不确定是否理解有误,但似乎只能通过从镜像创建新的容器来设置端口映射。是否存在一种方式可以将端口映射分配给现有的Docker容器?
我不确定是否理解有误,但似乎只能通过从镜像创建新的容器来设置端口映射。是否存在一种方式可以将端口映射分配给现有的Docker容器?
我也对这个问题很感兴趣。
正如@Thasmo所提到的,端口映射只能在docker run
(和docker create
)命令中指定。
其他命令,如docker start
没有-p
选项,docker port
仅显示当前的端口映射。
为了添加端口映射,我通常按照以下步骤操作:
停止正在运行的容器
docker stop test01
提交容器
docker commit test01 test02
注意: 上面的test02
是我从test01
容器构建的新图像。
从已提交的镜像中重新运行
docker run -p 8080:8080 -td test02
docker start
时使用端口规范(--publish)吗? - Elijah Lynnhostconfig.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”字段中。
docker stop <container_name>
)。docker start <container_name>
)。因此,您无需创建图像即可完成此操作。您还可以在此处更改重启标志。
P.S. 您可以访问https://docs.docker.com/engine/admin/,了解如何根据您的主机计算机正确地重新启动Docker引擎。我使用sudo systemctl restart docker
来重启我的运行在Ubuntu 16.04上的Docker引擎。
hostconfig.json
和config.v2.json
两个文件。请使用@rohitmohta提供的链接查看详细信息。 - Kalpak Gadre编辑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;
}
socat
的TCP代理可能会更容易。 - Konstantin Pelepelinreproxy
,因为它更容易配置:docker create -p EXTERNAL_PORT:8080 --name reproxy_container --network NETWORK_NAME umputun/reproxy --static.enabled --static.rule=*,^/(.*),http://ORIGINAL_CONTAINER:INTERNAL_PORT/$1
。 - Winandnginx
则涵盖了更多情况。尽管如此,reproxy 似乎是工具集的一个不错的补充。 - quetzalcoatl如果您对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}
-D
标志从iptables中删除/恢复/删除规则;如果您要移除容器并希望使用该端口,这将是必要的。DOCKER_PORT
映射到 MACHINE_PORT
,哪些部分应该更改? - Ciprian Tomoiagă在藤本洋一的例子中,test01
是一个容器,而test02
是一个镜像。
在执行docker run
之前,您可以删除原始容器,然后再次为容器分配相同的名称:
$ docker stop container01
$ docker commit container01 image01
$ docker rm container01
$ docker run -d -P --name container01 image01
(使用-P
将端口暴露给随机端口而不是手动分配)。
docker inspect container01
,保留卷名称并在运行新容器时挂载它。 - Sergei Vavilovcontainer01
中且未在卷、挂载点或原始镜像中的数据将会被保存在image01
中。因此产生了混淆。我猜这些数据可能会丢失,就像你在房间里把钥匙丢了一样,但并非永久丢失。你只需要了解一些关于docker的知识就可以找到它。 - CivFan如果您运行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 run -p <public_port>:<private_port> -d <image>
将开始运行容器。这篇教程解释了端口重定向。
docker run
创建并启动一个新的容器。其等效于执行 docker create
后立即执行 docker start
。 - user189198# 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://dev59.com/RVIH5IYBdhLWcg3wQLVU#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
的更改将被还原。8092
。8092
。参考 @holdfenytolvaj 的回答。
find /var/lib/docker/containers/ -name config.v2.json -exec grep -H f7828c0aa {} \;
- kreigan我们可以使用诸如ssh之类的便利工具轻松地完成这项任务。
我正在使用ubuntu主机和基于ubuntu的docker镜像。
当需要映射新端口时,
在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进行了测试。