在 docker 中部署一个最小的烧瓶应用程序 - 服务器连接问题

新手上路,请多包涵

我有一个应用程序,其唯一依赖项是烧瓶,它在 docker 外运行良好并绑定到默认端口 5000 。这是完整的来源:

 from flask import Flask

app = Flask(__name__)
app.debug = True

@app.route('/')
def main():
    return 'hi'

if __name__ == '__main__':
    app.run()

问题是当我在 docker 中部署它时,服务器正在运行,但无法从容器外部访问。

下面是我的 Dockerfile 。该图像是安装了烧瓶的 ubuntu。 tar 只包含上面列出的 index.py

 # Dockerfile
FROM dreen/flask
MAINTAINER dreen
WORKDIR /srv

# Get source
RUN mkdir -p /srv
COPY perfektimprezy.tar.gz /srv/perfektimprezy.tar.gz
RUN tar x -f perfektimprezy.tar.gz
RUN rm perfektimprezy.tar.gz

# Run server
EXPOSE 5000
CMD ["python", "index.py"]

这是我正在执行的部署步骤

$> sudo docker build -t perfektimprezy .

据我所知,上述运行良好,图像在 /srv 中包含 tar 的内容。现在,让我们在容器中启动服务器:

 $> sudo docker run -i -p 5000:5000 -d perfektimprezy
1c50b67d45b1a4feade72276394811c8399b1b95692e0914ee72b103ff54c769

它真的在运行吗?

 $> sudo docker ps
CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS                    NAMES
1c50b67d45b1        perfektimprezy:latest   "python index.py"   5 seconds ago       Up 5 seconds        0.0.0.0:5000->5000/tcp   loving_wozniak

 $> sudo docker logs 1c50b67d45b1
    * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
    * Restarting with stat

是的,似乎烧瓶服务器正在运行。这就是奇怪的地方。让我们向服务器发出请求:

 $> curl 127.0.0.1:5000 -v
* Rebuilt URL to: 127.0.0.1:5000/
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: 127.0.0.1:5000
> Accept: */*
>
* Empty reply from server
* Connection #0 to host 127.0.0.1 left intact
curl: (52) Empty reply from server

空回复…但是进程正在运行吗?

 $> sudo docker top 1c50b67d45b1
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                2084                812                 0                   10:26               ?                   00:00:00            python index.py
root                2117                2084                0                   10:26               ?                   00:00:00            /usr/bin/python index.py

现在让我们通过 ssh 进入服务器并检查…

 $> sudo docker exec -it 1c50b67d45b1 bash
root@1c50b67d45b1:/srv# netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:47677         127.0.0.1:5000          TIME_WAIT
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   Path
root@1c50b67d45b1:/srv# curl -I 127.0.0.1:5000
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 5447
Server: Werkzeug/0.10.4 Python/2.7.6
Date: Tue, 19 May 2015 12:18:14 GMT

没关系……但不是从外面。

我究竟做错了什么?

原文由 Dreen 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 558
2 个回答

问题是您只绑定到 localhost 接口,如果您希望容器可以从外部访问,则应该绑定到 0.0.0.0 。如果你改变:

 if __name__ == '__main__':
    app.run()

if __name__ == '__main__':
    app.run(host='0.0.0.0')

它应该工作。

请注意,这将绑定到主机上的 所有 接口,这在某些情况下可能存在安全风险 - 有关绑定到特定接口的更多信息,请参阅 https://stackoverflow.com/a/58138250/4332

原文由 Adrian Mouat 发布,翻译遵循 CC BY-SA 4.0 许可协议

当使用 flask 命令代替 app.run 时,您可以通过 --host 选项来更改主机。 Docker 中的行将是:

 CMD ["flask", "run", "--host", "0.0.0.0"]

或者

CMD flask run --host 0.0.0.0

原文由 Marku 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题