我试图创建一个Docker容器,就像一个完整的虚拟机。我知道我可以在Dockerfile中使用EXPOSE指令来公开一个端口,并且我可以使用-p标志与docker run一起分配端口,但是一旦容器实际运行,是否有命令打开/映射其他端口?
例如,假设我有一个运行sshd的Docker容器。其他人使用容器ssh并安装httpd。有没有办法公开容器上的80端口,并将其映射到主机上的8080端口,以便人们可以访问容器中运行的web服务器,而无需重新启动它?
我试图创建一个Docker容器,就像一个完整的虚拟机。我知道我可以在Dockerfile中使用EXPOSE指令来公开一个端口,并且我可以使用-p标志与docker run一起分配端口,但是一旦容器实际运行,是否有命令打开/映射其他端口?
例如,假设我有一个运行sshd的Docker容器。其他人使用容器ssh并安装httpd。有没有办法公开容器上的80端口,并将其映射到主机上的8080端口,以便人们可以访问容器中运行的web服务器,而无需重新启动它?
当前回答
您可以使用像Weave Net这样的覆盖网络,它将为每个容器分配唯一的IP地址,并隐式地将所有端口暴露给网络的每个容器部分。
Weave还提供主机网络集成。缺省情况下是禁用的,但是,如果您还想从主机访问容器IP地址(及其所有端口),您可以简单地运行weave expose。
坦白说,我在纺织工场工作。
其他回答
你不能通过Docker来做到这一点,但是你可以从主机上访问容器未暴露的端口。
如果您有一个在端口8000上运行某些内容的容器,您可以运行
wget http://container_ip:8000
要获取容器的IP地址,运行以下2条命令:
docker ps
docker inspect container_name | grep IPAddress
在内部,当你运行一个图像时,Docker外壳会调用iptables,所以这可能会有一些变化。
将容器的端口8000暴露在本地主机的端口8001上:
iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.17.0.19:8000
解决这个问题的一种方法是使用您想要的端口映射设置另一个容器,并比较iptables-save命令的输出(尽管如此,我不得不删除一些迫使通信通过docker代理的其他选项)。
注意:这是在颠覆docker,所以应该注意到它可能会产生蓝烟。
OR
另一种选择是查看(new?- p选项-它将使用随机的主机端口,然后将它们连接起来。
OR
在0.6.5中,你可以使用LINKs特性来启动一个与现有容器对话的新容器,并附加一些对该容器的-p标志的中继?(我还没用过LINKs。)
OR
docker 0.11?你可以使用docker run——net host ..将容器直接连接到主机的网络接口(即,net没有命名空间),因此在容器中打开的所有端口都是公开的。
我会这么做:
提交活动容器。 使用新映像再次运行容器,并打开端口(我建议挂载一个共享卷并打开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
您可以使用像Weave Net这样的覆盖网络,它将为每个容器分配唯一的IP地址,并隐式地将所有端口暴露给网络的每个容器部分。
Weave还提供主机网络集成。缺省情况下是禁用的,但是,如果您还想从主机访问容器IP地址(及其所有端口),您可以简单地运行weave expose。
坦白说,我在纺织工场工作。
您可以使用SSH创建隧道并在主机中公开容器。
可以采用两种方式,从容器到主机或从主机到容器。但是你需要一个SSH工具,比如OpenSSH(一个是客户端,另一个是服务器)。
例如,在容器中,可以这样做
$ 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..
你可以从这一行(在容器中)找到容器的IP地址:
$ ifconfig eth0 | grep "inet addr" | sed 's/^[^:]*:\([^ ]*\).*/\1/g'
172.17.0.2
然后在主机中,你可以这样做:
sudo ssh -NfL 80:0.0.0.0:80 root@172.17.0.2
我不得不处理同样的问题,并且能够在不停止任何正在运行的容器的情况下解决它。这是截至2016年2月的最新解决方案,使用Docker 1.9.1。不管怎样,这个答案是@ricardo-branco的答案的详细版本,但对新用户来说更有深度。
在我的场景中,我想临时连接到运行在容器中的MySQL,由于其他应用程序容器都链接到它,停止、重新配置和重新运行数据库容器是不可能的。
由于我想从外部(通过SSH隧道从Sequel Pro)访问MySQL数据库,我将使用主机上的端口33306。(不是3306,只是以防有一个外部MySQL实例在运行。)
我花了大约一个小时摆弄iptables,结果一无所获,尽管:
一步一步地,我是这样做的:
mkdir db-expose-33306
cd db-expose-33306
vim Dockerfile
编辑dockerfile,把这个放在里面:
# Exposes port 3306 on linked "db" container, to be accessible at host:33306
FROM ubuntu:latest # (Recommended to use the same base as the DB container)
RUN apt-get update && \
apt-get -y install socat && \
apt-get clean
USER nobody
EXPOSE 33306
CMD socat -dddd TCP-LISTEN:33306,reuseaddr,fork TCP:db:3306
然后构建图像:
docker build -t your-namespace/db-expose-33306 .
然后运行它,链接到正在运行的容器。(使用-d代替-rm将其保留在后台,直到显式地停止和删除。在这种情况下,我只希望它暂时运行。)
docker run -it --rm --name=db-33306 --link the_live_db_container:db -p 33306:33306 your-namespace/db-expose-33306