如何从 Mac 到达 docker 容器 `localhost`?
How to reach docker container `localhost` from Mac?
请注意,这与 How to expose a service running inside a docker container, bound to localhost 不同,后者可以在 Docker 中以多种方式解决 Linux,比如通过 --net host
甚至 -v
绑定我的 Linux-flavor 客户端等等。我的问题是针对 Docker 和 Mac,所以它不是那么简单。
我有一个 TCP 服务器绑定到 localhost:5005
运行ning inside Docker for Mac。 (出于安全原因,我不能绑定到 0.0.0.0:5005
。)
我有一个 TCP 客户端从我的 Mac(不在 docker 容器内)向此服务器发送请求。
我的问题是,如何让它发挥作用?
在 Linux Docker 中,我会简单地使用 --net=host
以便服务器绑定到我的主机 lo
接口,但似乎 Docker 用于Mac 运行s 在托管 VM 上,因此 host
网络行为是不同的行为。
为了说明我的观点:
上Mac书
根本行不通
[me@MacBook App]$ docker run -v `pwd`:/App -p 127.0.0.1:5005:5005 nitincypher/docker-ubuntu-python-pip /App/server.py
[me@MacBook App]$ ./client.py
Client received data:
上Linux
相比之下,使用 host
网络模式在 Linux 上进行操作将是微不足道的。因为我使用我的 Linux 的 lo
接口作为我的容器 lo
接口。
[me@Linux App]$ docker run -v `pwd`:/App --net=host nitincypher/docker-ubuntu-python-pip /App/server.py
Server Connection address: ('127.0.0.1', 52172)
Server received data: Hello, World!
[me@Linux App]$ ./client.py
Client received data: Hello, World!
我的模拟服务器代码
要求:它必须绑定到 localhost
,除此之外别无其他。所以我无法将其更改为 0.0.0.0
.
#!/usr/bin/env python
import socket
TCP_IP = 'localhost'
TCP_PORT = 5005
BUFFER_SIZE = 20 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print 'Server Connection address:', addr
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print "Server received data:", data
conn.send(data) # echo
conn.close()
我的模拟客户端代码
要求:必须是 MacBook 上的 运行,因为真正的客户端是用 CPP 编写的,并且只在 MacBook 上编译为 运行。
#!/usr/bin/env python
import socket
TCP_IP = 'localhost'
TCP_PORT = 5005
BUFFER_SIZE = 1024
MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
print "Client received data:", data
这是一个可行的解决方案。基本思路是使用 SSH 隧道进行端口转发。
高级创意
- 您首先需要构建一个 docker 镜像来支持 SSH 访问,因为
ubuntu
图片没有 sshd
开箱,而且
- 您需要知道 运行ning 容器的
root
的密码。
- 然后您将像往常一样启动您的容器,只是您是根据您创建的新映像执行此操作。
- 您从 MacBook 创建 SSH 隧道会话,然后您 运行 MacBook 上的客户端像往常一样。
作为参考,SSH tunneling can be found here, the process of creating a sshd docker image is , and how to ssh into docker container is explained here
的命令
步骤
创建一个 Docker 文件 Dockerfile
#Use whatever image you are using on Docker Linux , say "FROM ubuntu:16.04"
FROM nitincypher/docker-ubuntu-python-pip
RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:screencast' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
从 Docker 文件
创建一个 Docker 图像
[me@MacBook App]$ docker build -t my_ssh_python .
启动您的服务器容器
[me@MacBook App]$ docker run -d -P -v `pwd`:/App --name myserver my_ssh_python
在容器中启动你的服务器
[me@MacBook App]$ docker exec myserver /App/server.py
创建 SSH 隧道
[me@MacBook App]$ ssh root@`hostname` -p `docker port myserver 22 | awk -F ":" '{print }'` -L 8000:localhost:8000 -N
#Password is "screencast" as you built in Dockerfile
注意
一个。您必须使用 MacBook 的 IP 地址而不是 docker 容器的 IP 地址。
b。您将使用默认容器 ssh
端口 22
映射到主机
上的端口
c。在隧道 -L 8000:localhost:8000
中,你说的是从你的 MacBook 8000
(第一个 8000)转发任何东西到 Docker 容器的 localhost
在端口 8000
现在您可以在本地使用您的客户端了
[me@MacBook App]$ ./client.py
Client received data: Hello, World!
而在服务器端,你可以看到
Server Connection address: ('127.0.0.1', 55396)
Server received data: Hello, World!
请注意,这与 How to expose a service running inside a docker container, bound to localhost 不同,后者可以在 Docker 中以多种方式解决 Linux,比如通过 --net host
甚至 -v
绑定我的 Linux-flavor 客户端等等。我的问题是针对 Docker 和 Mac,所以它不是那么简单。
我有一个 TCP 服务器绑定到 localhost:5005
运行ning inside Docker for Mac。 (出于安全原因,我不能绑定到 0.0.0.0:5005
。)
我有一个 TCP 客户端从我的 Mac(不在 docker 容器内)向此服务器发送请求。
我的问题是,如何让它发挥作用?
在 Linux Docker 中,我会简单地使用 --net=host
以便服务器绑定到我的主机 lo
接口,但似乎 Docker 用于Mac 运行s 在托管 VM 上,因此 host
网络行为是不同的行为。
为了说明我的观点:
上Mac书
根本行不通
[me@MacBook App]$ docker run -v `pwd`:/App -p 127.0.0.1:5005:5005 nitincypher/docker-ubuntu-python-pip /App/server.py
[me@MacBook App]$ ./client.py
Client received data:
上Linux
相比之下,使用 host
网络模式在 Linux 上进行操作将是微不足道的。因为我使用我的 Linux 的 lo
接口作为我的容器 lo
接口。
[me@Linux App]$ docker run -v `pwd`:/App --net=host nitincypher/docker-ubuntu-python-pip /App/server.py
Server Connection address: ('127.0.0.1', 52172)
Server received data: Hello, World!
[me@Linux App]$ ./client.py
Client received data: Hello, World!
我的模拟服务器代码
要求:它必须绑定到 localhost
,除此之外别无其他。所以我无法将其更改为 0.0.0.0
.
#!/usr/bin/env python
import socket
TCP_IP = 'localhost'
TCP_PORT = 5005
BUFFER_SIZE = 20 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print 'Server Connection address:', addr
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print "Server received data:", data
conn.send(data) # echo
conn.close()
我的模拟客户端代码
要求:必须是 MacBook 上的 运行,因为真正的客户端是用 CPP 编写的,并且只在 MacBook 上编译为 运行。
#!/usr/bin/env python
import socket
TCP_IP = 'localhost'
TCP_PORT = 5005
BUFFER_SIZE = 1024
MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
print "Client received data:", data
这是一个可行的解决方案。基本思路是使用 SSH 隧道进行端口转发。
高级创意
- 您首先需要构建一个 docker 镜像来支持 SSH 访问,因为
ubuntu
图片没有sshd
开箱,而且- 您需要知道 运行ning 容器的
root
的密码。
- 然后您将像往常一样启动您的容器,只是您是根据您创建的新映像执行此操作。
- 您从 MacBook 创建 SSH 隧道会话,然后您 运行 MacBook 上的客户端像往常一样。
作为参考,SSH tunneling can be found here, the process of creating a sshd docker image is
步骤
创建一个 Docker 文件
Dockerfile
#Use whatever image you are using on Docker Linux , say "FROM ubuntu:16.04" FROM nitincypher/docker-ubuntu-python-pip RUN apt-get update && apt-get install -y openssh-server RUN mkdir /var/run/sshd RUN echo 'root:screencast' | chpasswd RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config # SSH login fix. Otherwise user is kicked off after login RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd ENV NOTVISIBLE "in users profile" RUN echo "export VISIBLE=now" >> /etc/profile EXPOSE 22 CMD ["/usr/sbin/sshd", "-D"]
从 Docker 文件
创建一个 Docker 图像[me@MacBook App]$ docker build -t my_ssh_python .
启动您的服务器容器
[me@MacBook App]$ docker run -d -P -v `pwd`:/App --name myserver my_ssh_python
在容器中启动你的服务器
[me@MacBook App]$ docker exec myserver /App/server.py
创建 SSH 隧道
[me@MacBook App]$ ssh root@`hostname` -p `docker port myserver 22 | awk -F ":" '{print }'` -L 8000:localhost:8000 -N #Password is "screencast" as you built in Dockerfile
注意
一个。您必须使用 MacBook 的 IP 地址而不是 docker 容器的 IP 地址。
b。您将使用默认容器
上的端口ssh
端口22
映射到主机c。在隧道
-L 8000:localhost:8000
中,你说的是从你的 MacBook8000
(第一个 8000)转发任何东西到 Docker 容器的localhost
在端口8000
现在您可以在本地使用您的客户端了
[me@MacBook App]$ ./client.py Client received data: Hello, World!
而在服务器端,你可以看到
Server Connection address: ('127.0.0.1', 55396) Server received data: Hello, World!