coo*_*aac 6 macos docker docker-network
请注意,这与如何公开在 docker 容器内运行的服务(绑定到 localhost )不同,后者可以在 Docker for Linux 中以多种方式解决,比如通过--net host甚至-v绑定我的 Linux 风格的客户端等。我的问题是特定的对于 Mac 版 Docker,所以事情没那么简单。
I have a TCP server binding to localhost:5005 running inside Docker for Mac. (For security reason, I must not bind to 0.0.0.0:5005.)
I have a TCP client sending request to this server from my Mac (not inside the docker container).
My question is, how do I make it work?
In Linux Docker, I would simply use --net=host so the server binds to my host lo interface, but it seems that Docker for Mac runs on a managed VM, so the host network behavior is different behavior.
To illustrate my point:
On MacBook
It simply would not work
[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:
Run Code Online (Sandbox Code Playgroud)
On Linux
In comparison, it would be trivial to do on Linux by using host network mode. Since I'm using my Linux's lo interface as my container lo interface.
[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!
Run Code Online (Sandbox Code Playgroud)
My Simulated Server Code
Requirement: It MUST bind to localhost, and nothing else. So I cannot change it to 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()
Run Code Online (Sandbox Code Playgroud)
My Simulated Client Code
Requirement: It MUST be ran on MacBook, since the real client is written in CPP and compiled to run only on 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
Run Code Online (Sandbox Code Playgroud)
这是一个可行的解决方案。基本思想是使用 SSH 隧道来进行端口转发。
\n\nubuntu图像没有sshd开箱即用,而且root正在运行的容器的密码。作为参考,\xc2\xa0命令\xc2\xa0用于\xc2\xa0 SSH隧道\xc2\xa0可以在这里找到,\xc2\xa0创建sshd docker镜像的过程是\xc2\xa0在这里解释,\xc2\xa0以及如何这里解释了如何通过 ssh 进入 docker 容器
\n\n创建 Docker 文件Dockerfile
#Use whatever image you are using on Docker Linux , say "FROM ubuntu:16.04"\nFROM nitincypher/docker-ubuntu-python-pip\n\nRUN apt-get update && apt-get install -y openssh-server\nRUN mkdir /var/run/sshd\nRUN echo \'root:screencast\' | chpasswd\nRUN sed -i \'s/PermitRootLogin prohibit-password/PermitRootLogin yes/\' /etc/ssh/sshd_config\n\n# SSH login fix. Otherwise user is kicked off after login\nRUN sed \'s@session\\s*required\\s*pam_loginuid.so@session optional pam_loginuid.so@g\' -i /etc/pam.d/sshd\n\nENV NOTVISIBLE "in users profile"\nRUN echo "export VISIBLE=now" >> /etc/profile\n\nEXPOSE 22\nCMD ["/usr/sbin/sshd", "-D"]\nRun Code Online (Sandbox Code Playgroud)从 Dockerfile 创建 Docker 镜像
\n\n[me@MacBook App]$ docker build -t my_ssh_python .\nRun Code Online (Sandbox Code Playgroud)启动您的服务器容器
\n\n[me@MacBook App]$ docker run -d -P -v `pwd`:/App --name myserver my_ssh_python\nRun Code Online (Sandbox Code Playgroud)在容器内启动服务器
\n\n[me@MacBook App]$ docker exec myserver /App/server.py\nRun Code Online (Sandbox Code Playgroud)创建 SSH 隧道
\n\n[me@MacBook App]$ ssh root@`hostname` -p `docker port myserver 22 | awk -F ":" \'{print $2}\'` -L 8000:localhost:8000 -N\n#Password is "screencast" as you built in Dockerfile\nRun Code Online (Sandbox Code Playgroud)\n\n注意
\n\nA。您必须使用 MacBook 的 IP 地址,而不是 docker 容器的 IP 地址。
\n\nb. ssh您将使用主机上默认容器端口22映射到的端口
C。在隧道中-L 8000:localhost:8000,您所说的是将任何内容从 MacBook (第一个 8000)转发到端口上的8000Docker 容器localhost8000
现在您可以在本地使用您的客户端
\n\n[me@MacBook App]$ ./client.py \nClient received data: Hello, World!\nRun Code Online (Sandbox Code Playgroud)\n\n在服务器端,你可以看到
\n\nServer Connection address: (\'127.0.0.1\', 55396)\nServer received data: Hello, World!\nRun Code Online (Sandbox Code Playgroud)