本文翻译自:Exposing a port on a live Docker container
I'm trying to create a Docker container that acts like a full-on virtual machine. 我正在尝试创建一个充当完整虚拟机的Docker容器。 I know I can use the EXPOSE instruction inside a Dockerfile to expose a port, and I can use the -p
flag with docker run
to assign ports, but once a container is actually running, is there a command to open/map additional ports live? 我知道我可以使用Dockerfile中的EXPOSE指令来暴露端口,我可以使用-p
标志和docker run
来分配端口,但是一旦容器实际运行,是否有命令打开/映射其他端口直播?
For example, let's say I have a Docker container that is running sshd. 例如,假设我有一个运行sshd的Docker容器。 Someone else using the container ssh's in and installs httpd. 其他人使用容器ssh并安装httpd。 Is there a way to expose port 80 on the container and map it to port 8080 on the host, so that people can visit the web server running in the container, without restarting it? 有没有办法在容器上公开端口80并将其映射到主机上的端口8080,以便人们可以访问容器中运行的Web服务器,而无需重新启动它?
#1楼
参考:https://stackoom.com/question/1LUJL/在实时Docker容器上公开端口
#2楼
You cannot do this via Docker, but you can access the container's un-exposed port from the host machine. 您无法通过Docker执行此操作,但可以从主机访问容器的未公开端口。
if you have a container that with something running on its port 8000, you can run 如果你有一个容器,其端口8000上运行的东西,你可以运行
wget http://container_ip:8000
To get the container´s ip address, run the 2 commands: 要获取容器的IP地址,请运行以下命令:
docker ps
docker inspect container_name | grep IPAddress
Internally, Docker shells out to call iptables when you run an image, so maybe some variation on this will work. 在内部,Docker会在你运行图像时弹出来调用iptables,所以可能会有一些变化。
to expose the container's port 8000 on your localhosts port 8001: 在localhosts端口8001上公开容器的端口8000:
iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.17.0.19:8000
One way you can work this out, is to setup another container with the port mapping you want, and compare the output of the iptables-save command (though, I had to remove some of the other options that force traffic to go via the docker proxy). 解决这个问题的一种方法是使用你想要的端口映射设置另一个容器,并比较iptables-save命令的输出(但是,我必须删除一些强制流量通过docker的其他选项)代理)。
NOTE: this is subverting docker, so should be done with the awareness that it may well create blue smoke 注意:这是颠覆码头,所以应该意识到它可能会产生蓝烟
OR 要么
Another alternative, is to look the (new? post 0.6.6?) -P option - which will use random host ports, and then wire those up. 另一种选择是查看(新的?post 0.6.6?) - P选项 - 它将使用随机主机端口,然后连接它们。
OR 要么
with 0.6.5, you could use the LINKs feature to bring up a new container that talks to the existing one, with some additional relaying to that container´s -p flags? 使用0.6.5,您可以使用LINKs功能调出一个与现有容器对话的新容器,还有一些中继到该容器的-p标志? (I have not used LINKs yet) (我还没有用过LINK)
OR 要么
with docker 0.11? 与docker 0.11? you can use docker run --net host ..
to attach your container directly to the host's network interfaces (ie, net is not name-spaced) and thus all ports you open in the container are exposed. 您可以使用docker run --net host ..
将容器直接连接到主机的网络接口(即,net不是名称间隔的),因此您在容器中打开的所有端口都会被暴露。
#3楼
Here's what I would do: 这就是我要做的事情:
- Commit the live container. 提交活动容器。
- Run the container again with the new image, with ports open (I'd recommend mounting a shared volume and opening the ssh port as well) 使用新映像再次运行容器,端口打开(我建议安装共享卷并打开ssh端口)
sudo docker ps
sudo docker commit <containerid> <foo/live>
sudo docker run -i -p 22 -p 8000:80 -m /data:/data -t <foo/live> /bin/bash
#4楼
IPtables hacks don't work, at least on Docker 1.4.1. IPtables黑客行为不起作用,至少在Docker 1.4.1上是这样。
The best way would be to run another container with the exposed port and relay with socat. 最好的方法是运行带有暴露端口的另一个容器并使用socat中继。 This is what I've done to (temporarily) connect to the database with SQLPlus: 这就是我用SQLPlus(临时)连接数据库所做的事情:
docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus
Dockerfile: Dockerfile:
FROM debian:7
RUN apt-get update && \
apt-get -y install socat && \
apt-get clean
USER nobody
CMD socat -dddd TCP-LISTEN:1521,reuseaddr,fork TCP:db:1521
#5楼
Here's another idea. 这是另一个想法。 Use SSH to do the port forwarding; 使用SSH进行端口转发; this has the benefit of also working in OS X (and probably Windows) when your Docker host is a VM. 当您的Docker主机是VM时,这也可以在OS X(可能还有Windows)中运行。
docker exec -it <containterid> ssh -R5432:localhost:5432 <user>@<hostip>
#6楼
You can use SSH to create a tunnel and expose your container in your host. 您可以使用SSH创建隧道并在主机中公开容器。
You can do it in both ways, from container to host and from host to container. 您可以通过两种方式执行此操作,从容器到主机以及从主机到容器。 But you need a SSH tool like OpenSSH in both (client in one and server in another). 但是你需要一个像OpenSSH这样的SSH工具(一个是客户端,另一个是服务器)。
For example, in the container, you can do 例如,在容器中,您可以这样做
$ yum install -y openssh openssh-server.x86_64
service sshd restart
Stopping sshd: [FAILED]
Generating SSH2 RSA host key: [ OK ]
Generating SSH1 RSA host key: [ OK ]
Generating SSH2 DSA host key: [ OK ]
Starting sshd: [ OK ]
$ passwd # You need to set a root password..
You can find the container IP address from this line (in the container): 您可以从此行(在容器中)找到容器IP地址:
$ ifconfig eth0 | grep "inet addr" | sed 's/^[^:]*:\([^ ]*\).*/\1/g'
172.17.0.2
Then in the host, you can just do: 然后在主机中,您可以这样做:
sudo ssh -NfL 80:0.0.0.0:80 root@172.17.0.2