M1芯片MacOS下Docker Compose host网络模式失效问题咨询
问题与解决方法
环境信息
- Docker Compose版本:v2.23.3
- Docker(podman)版本:
Client: Podman Engine Version: 4.9.3 API Version: 4.9.3 Go Version: go1.21.7 Git Commit: 8d2b55ddde1bc81f43d018dfc1ac027c06b26a7f Built: Tue Feb 13 14:55:17 2024 OS/Arch: darwin/arm64 Server: Podman Engine Version: 4.9.0 API Version: 4.9.0 Go Version: go1.21.6 Built: Wed Jan 24 05:07:09 2024 OS/Arch: linux/arm64 - 操作系统:MacOS 14.3.1 (23D60)
- 芯片:M1
场景与配置
有一个名为app的服务,预期监听1997端口接收主机消息。文件夹结构:
tree . . ├── Dockerfile ├── app │ ├── app.py │ ├── received.txt │ └── send.py └── docker-compose.yaml
各文件内容
Dockerfile
FROM python:3.9-slim # Set the working directory in the container WORKDIR /app # Command to run the application CMD sh -c 'pwd && ls && exec python app.py'
app.py
import socket def write_to_file(message): with open("/app/received.txt", "a") as f: # Use mode 'a' to append to the file f.write(message + "\n") # Write the message followed by a newline def start_server(host='0.0.0.0', port=1997): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((host, port)) s.listen() print(f"Listening on {host}:{port}") while True: conn, addr = s.accept() with conn: print(f"Connected by {addr}") while True: data = conn.recv(1024) if not data: break message = data.decode('utf-8') write_to_file(message) if message.strip().lower() == "bye": print("Received 'bye', shutting down the server.") return # Exit the function and terminate the server if __name__ == "__main__": start_server()
send.py
import socket import sys def send_message(host, port, message): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, port)) s.sendall(message.encode('utf-8')) # If you want to wait for a response, uncomment the next line # data = s.recv(1024) print(f"Message sent: {message}") if __name__ == "__main__": if len(sys.argv) > 1: message = ' '.join(sys.argv[1:]) # Join all arguments into a single message, separated by spaces send_message('localhost', 1997, message) else: print("Usage: python send_message.py <message>")
初始docker-compose.yaml
version: '3.8' services: app: build: context: . network: host volumes: - ./app:/app
问题现象
启动服务后,本地执行python3 ./app/send.py hello hello gello触发连接拒绝错误:
python3 ./app/send.py hello hello gello Traceback (most recent call last): File "/~~~/draft/./app/send.py", line 15, in <module> send_message('localhost', 1997, message) File "/~~~/draft/./app/send.py", line 6, in send_message s.connect((host, port)) ConnectionRefusedError: [Errno 61] Connection refused
但在容器内部执行相同命令可正常工作:
docker exec -it draft-app-1 python /app/send.py jillo Message sent: jillo
改用network_mode: "host"配置后,问题依旧存在。
解决方法
M1 Mac上的Podman基于虚拟机运行,network_mode: host仅作用于虚拟机内部,无法直接让Mac主机访问容器端口。提供两种解决方案:
方案1:使用端口映射(推荐)
修改docker-compose.yaml,添加端口映射规则,将容器1997端口映射到主机同端口:
version: '3.8' services: app: build: . ports: - "1997:1997" volumes: - ./app:/app
修改后重启服务,本地执行send.py即可正常连接。
方案2:连接Podman虚拟机IP
若必须使用host网络,先获取Podman虚拟机的IP地址:
podman machine inspect --format '{{.IPAddress}}'
将send.py中的localhost替换为该IP,或执行命令时指定对应主机地址即可。
内容的提问来源于stack exchange,提问作者IsaIkari
相关产品推荐
相关产品推荐

