我试图创建一个Docker容器,就像一个完整的虚拟机。我知道我可以在Dockerfile中使用EXPOSE指令来公开一个端口,并且我可以使用-p标志与docker run一起分配端口,但是一旦容器实际运行,是否有命令打开/映射其他端口?

例如,假设我有一个运行sshd的Docker容器。其他人使用容器ssh并安装httpd。有没有办法公开容器上的80端口,并将其映射到主机上的8080端口,以便人们可以访问容器中运行的web服务器,而无需重新启动它?


当前回答

不可能进行实时端口映射,但有多种方法可以给Docker容器提供类似虚拟机的真实接口。

Macvlan接口

Docker现在包含一个Macvlan网络驱动程序。这将Docker网络附加到一个“真实世界”接口上,并允许你直接将网络地址分配给容器(就像虚拟机桥接模式)。

docker network create \
    -d macvlan \
    --subnet=172.16.86.0/24 \
    --gateway=172.16.86.1  \
    -o parent=eth0 pub_net

管道也可以将一个真实的接口映射到容器中,或者在旧版本的Docker中设置一个子接口。

IP的路由

如果你可以控制网络,你可以将额外的网络路由到Docker主机中,以供容器使用。

然后将该网络分配给容器,并设置Docker主机通过Docker网络路由数据包。

共享主机接口

——net host选项允许将主机接口共享到一个容器中,但由于共享的性质,这可能不是在一个主机上运行多个容器的良好设置。

其他回答

您可以使用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

IPtables黑客不能工作,至少在Docker 1.4.1上是这样。

最好的方法是使用暴露的端口运行另一个容器,并使用socat进行中继。下面是我使用SQLPlus(临时)连接数据库所做的工作:

docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus

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

不可能进行实时端口映射,但有多种方法可以给Docker容器提供类似虚拟机的真实接口。

Macvlan接口

Docker现在包含一个Macvlan网络驱动程序。这将Docker网络附加到一个“真实世界”接口上,并允许你直接将网络地址分配给容器(就像虚拟机桥接模式)。

docker network create \
    -d macvlan \
    --subnet=172.16.86.0/24 \
    --gateway=172.16.86.1  \
    -o parent=eth0 pub_net

管道也可以将一个真实的接口映射到容器中,或者在旧版本的Docker中设置一个子接口。

IP的路由

如果你可以控制网络,你可以将额外的网络路由到Docker主机中,以供容器使用。

然后将该网络分配给容器,并设置Docker主机通过Docker网络路由数据包。

共享主机接口

——net host选项允许将主机接口共享到一个容器中,但由于共享的性质,这可能不是在一个主机上运行多个容器的良好设置。

这是另一个想法。使用SSH协议进行端口转发;当你的Docker主机是一个虚拟机时,它也可以在OS X(可能还有Windows)中工作。

docker exec -it <containterid> ssh -R5432:localhost:5432 <user>@<hostip>

Docker运行-i——expose=22 b5593e60c33b bash

裁判:https://forums.docker.com/t/how-to-expose-port-on-running-container/3252/5

这可能对你有帮助