我试图创建一个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服务器,而无需重新启动它?
当前回答
请先阅读里卡多的回答。这对我很管用。
但是,如果使用docker-compose启动正在运行的容器,则存在这样的情况。这是因为docker-compose(我正在运行docker 1.17)创建了一个新的网络。解决这种情况的方法是
Docker网络ls
然后追加如下内容 Docker运行-d——name sqlplus——link db:db -p 1521:1521 sqlplus——net network_name
其他回答
这是另一个想法。使用SSH协议进行端口转发;当你的Docker主机是一个虚拟机时,它也可以在OS X(可能还有Windows)中工作。
docker exec -it <containterid> ssh -R5432:localhost:5432 <user>@<hostip>
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网络中启动一个新容器,并让它将流量转发到原始容器。
# docker run \
--rm \
-p $PORT:1234 \
verb/socat \
TCP-LISTEN:1234,fork \
TCP-CONNECT:$TARGET_CONTAINER_IP:$TARGET_CONTAINER_PORT
工作的例子
启动一个监听80端口的web服务,但不要公开它的内部端口80(哎呀!)
# docker run -ti mkodockx/docker-pastebin # Forgot to expose PORT 80!
查找其Docker网络IP:
# docker inspect 63256f72142a | grep IPAddress
"IPAddress": "172.17.0.2",
启动verb/socat,暴露端口8080,并让它将TCP流量转发到该IP的端口80:
# docker run --rm -p 8080:1234 verb/socat TCP-LISTEN:1234,fork TCP-CONNECT:172.17.0.2:80
现在,您可以访问http://localhost:8080/上的pastebin,您的请求将被发送到socat:1234, socat:1234将它转发到pastebin:80,并且响应反向沿着相同的路径传播。
我会这么做:
提交活动容器。 使用新映像再次运行容器,并打开端口(我建议挂载一个共享卷并打开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
不可能进行实时端口映射,但有多种方法可以给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选项允许将主机接口共享到一个容器中,但由于共享的性质,这可能不是在一个主机上运行多个容器的良好设置。