Python 在 docker 中部署最小的 Flask 应用程序 - 服务器连接问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30323224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 08:14:22  来源:igfitidea点击:

Deploying a minimal flask app in docker - server connection issues

pythondeploymentflaskdockerdockerfile

提问by Dreen

I have an app who's only dependency is flask, which runs fine outside docker and binds to the default port 5000. Here is the full source:

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

from flask import Flask

app = Flask(__name__)
app.debug = True

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

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

The problem is that when I deploy this in docker, the server is running but is unreachable from outside the container.

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

Below is my Dockerfile. The image is ubuntu with flask installed. The tar just contains the index.pylisted above;

下面是我的 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"]

Here are the steps I am doing to deploy

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

$> sudo docker build -t perfektimprezy .

$> sudo docker build -t perfektimprezy .

As far as I know the above runs fine, the image has the contents of the tar in /srv. Now, let's start the server in a container:

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

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

Is it actually running?

它真的在运行吗?

$> 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

Yep, seems like the flask server is running. Here is where it gets weird. Lets make a request to the server:

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

 $> 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

Empty reply... But is the process running?

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

$> 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

Now let's ssh into the server and check...

现在让我们 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

It's fine... but not from the outside :( What am I doing wrong?

没关系......但不是从外面:(我做错了什么?

采纳答案by Adrian Mouat

The problem is you are only binding to the localhost interface, you should be binding to 0.0.0.0if you want the container to be accessible from outside. If you change:

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

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

to

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

It should work.

它应该工作。

回答by Marku

When using the flaskcommand instead of app.run, you can pass the --hostoption to change the host. The line in Docker would be:

当使用flask命令而不是 时app.run,您可以传递--host选项来更改主机。Docker 中的行将是:

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

or

或者

CMD flask run --host 0.0.0.0

回答by Bert

Your Docker container has more than one network interface. For example, my container has the following:

您的 Docker 容器有多个网络接口。例如,我的容器具有以下内容:

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
32: eth0@if33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

if you run docker network inspect bridge, you can see that your container is connected to that bridge with the second interface in the above output. This default bridge is also connected to the Docker process on your host.

如果您运行docker network inspect bridge,您可以看到您的容器已通过上述输出中的第二个接口连接到该网桥。此默认网桥还连接到主机上的 Docker 进程。

Therefore you would have to run the command:

因此,您必须运行以下命令:

CMD flask run --host 172.17.0.2

To access your Flask app running in a Docker container from your host machine. Replace 172.17.0.2with whatever the particular IP address is of your container.

从主机访问在 Docker 容器中运行的 Flask 应用程序。替换172.17.0.2为容器的任何特定 IP 地址。