डॉकटर - सर्वर कनेक्शन मुद्दों में एक न्यूनतम फ्लास्क ऐप तैनात करना


108

मेरे पास एक ऐप है जो एकमात्र निर्भरता फ्लास्क है, जो डॉकटर के बाहर ठीक चलता है और डिफ़ॉल्ट पोर्ट से बांधता है 5000। यहाँ पूर्ण स्रोत है:

from flask import Flask

app = Flask(__name__)
app.debug = True

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

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

समस्या यह है कि जब मैं इसे डॉकटर में तैनात करता हूं, तो सर्वर चल रहा है लेकिन कंटेनर के बाहर से पहुंच से बाहर है।

नीचे मेरा डॉकरफाइल है। छवि को स्थापित फ्लास्क के साथ ubuntu है। टार में बस 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। अब, एक कंटेनर में सर्वर शुरू करते हैं:

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

यह ठीक है ... लेकिन बाहर से नहीं :( मैं गलत क्या कर रहा हूँ?


प्रासंगिक बात "<वर्ग 'httplib.BadStatusLine'> की वजह से" है, को देखने के stackoverflow.com/questions/16592568/...
user2915097

मैं केवल एक बार कनेक्ट करने की कोशिश कर रहा हूं और मुझे पूरा यकीन है कि यह httpie में बग नहीं है (मैंने उदाहरण को कर्ल में बदल दिया है), और न ही सर्वर में क्योंकि यह ठीक बाहर के काम करने वाला है। मैं एक मजबूत लग रहा है यह एक docker config / परिनियोजन गलत मुद्दा है
Dreen

जब आप एक फ्लास्क (पूंछ, बिल्ली ...) डिबग करते हैं, तब आप के साथ कंटेनर docker exec -it 1c50b67d45b1 bashऔर फिर सामान्य netstat -anया किसी भी कमांड को चेक करेंगे
user2915097

@ user2915097: सर्वर के भीतर से कुछ उत्पादन जोड़ा ive
Dreen

'कनेक्ट नहीं कर सकते ...' @ डिरेन, आप कनेक्ट कर सकते हैं , आपको बस एक खाली उत्तर मिल सकता है ( Connected to 127.0.0.1)
फोर्सब्रु

जवाबों:


179

समस्या यह है कि आप केवल लोकलहोस्ट इंटरफेस के लिए बाध्य हैं, 0.0.0.0यदि आप चाहते हैं कि कंटेनर बाहर से सुलभ होना चाहिए, तो आपको बाध्यकारी होना चाहिए । यदि आप बदलते हैं:

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

सेवा

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

यह काम करना चाहिए।


यह समाधान काम करता है। एक पूर्ण Dockerfile और python स्क्रिप्ट का उपयोग करके परिणाम यहाँ देख सकता है क्योंकि यह समाधान बताता है।

क्या फर्क पड़ता है?
Jwan622

1
@ Jwan622 स्थानीयहोस्ट इंटरफ़ेस केवल कंटेनर के अंदर उपलब्ध है। 0.0.0.0 सभी इंटरफेस को बांधता है। इंटरफेस विभिन्न नेटवर्कों से जुड़ते हैं (इसलिए आप वाईफाई, लेंस आदि के लिए एक हो सकते हैं)
एड्रियन मौट

सुनिश्चित करें कि आप -p 5000:5000अपने docker runआदेश के साथ ध्वज के साथ अपने कंटेनर में पोर्ट 5000 को बांधना याद रखें ।
टी पाश।

39

flaskइसके बजाय कमांड का उपयोग करते समय app.run, आप --hostहोस्ट को बदलने का विकल्प पास कर सकते हैं । डॉकर में लाइन होगी:

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

या

CMD flask run --host 0.0.0.0

2
इस समाधान के लिए बहुत बहुत धन्यवाद, मेरे पास एक ही समस्या है, क्या आप जानते हैं कि क्या कारण है जो app.run(host="0.0.0.0") काम नहीं करता है? मैंने इस प्रश्न के लिए एक पोस्ट भी बनाया: stackoverflow.com/q/53133350/3279996
xirururu

1
इस नोट पर, सुनिश्चित करें कि उपयोग न करें python run.py --host=0.0.0.0 । मेरे नामकरण सम्मेलनों के कारण मुझे हर बार एक बार मिलता है। वह कोड काम करता दिखाई देगा लेकिन सर्वर स्थानीय होस्ट पर चलेगा।
ब्रैडेन होल्ट

क्या यह निर्मित फ्लास्क सर्वर नहीं चलता है, जो उत्पादन वातावरण के लिए नहीं है?
code_dredd

यह बहुत अच्छा है, जो भी कारण से लगभग सभी फ्लास्क-साथ-डॉकर जानकारी फ्लास्क सीएलआई का उपयोग करने में विफल रहती है, जो ऐप शुरू करने के लिए फ्लास्क 1.0 तरीका है।
ज़च वैलेंटा

3
यहाँ 2020 में फ्लास्क 1.1.1 के साथ app.run(host="0.0.0.0")फेल और CMD ["flask", "run", "--host", "0.0.0.0" ]एक विजेता की तरह काम कर रहा है।
जो

2

अन्य उत्तरों पर निर्माण करने के लिए:

कल्पना कीजिए कि आपके पास दो कंप्यूटर हैं। प्रत्येक कंप्यूटर में एक नेटवर्क इंटरफ़ेस (वाईफाई, कहते हैं) है, जो इसका सार्वजनिक आईपी है। प्रत्येक कंप्यूटर में 127.0.0.1 पर लूपबैक / लोकलहोस्ट इंटरफ़ेस होता है। इसका मतलब है "बस यह कंप्यूटर।"

यदि आप कंप्यूटर ए पर 127.0.0.1 पर सूचीबद्ध हैं, तो आप कंप्यूटर बी पर चलने पर 127.0.0.1 के माध्यम से उस से कनेक्ट होने में सक्षम होने की उम्मीद नहीं करेंगे। आखिरकार, आपने कंप्यूटर ए के स्थानीय , निजी पते पर सुनने के लिए कहा ।

डॉकर समान सेटअप है; तकनीकी रूप से यह एक ही कंप्यूटर है, लेकिन लिनक्स कर्नेल प्रत्येक कंटेनर को अपने पृथक नेटवर्क स्टैक के साथ चलाने की अनुमति देता है। इसलिए कंटेनर में 127.0.0.1 आपके होस्ट की तुलना में एक अलग कंप्यूटर पर 127.0.0.1 के समान है - आप इसे कनेक्ट नहीं कर सकते।

चित्र के साथ लंबा संस्करण: https://pythonspeed.com/articles/docker-connection-refused/


1

आपके डॉकर कंटेनर में एक से अधिक नेटवर्क इंटरफ़ेस हैं। उदाहरण के लिए, मेरे कंटेनर में निम्नलिखित हैं:

$ 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

यदि आप चलाते हैं docker network inspect bridge, तो आप देख सकते हैं कि आपका कंटेनर उपरोक्त आउटपुट में दूसरे इंटरफ़ेस के साथ उस पुल से जुड़ा हुआ है। यह डिफ़ॉल्ट पुल आपके होस्ट पर डॉकर प्रक्रिया से भी जुड़ा हुआ है।

इसलिए आपको कमांड चलाना होगा:

CMD flask run --host 172.17.0.2

अपने मेजबान मशीन से डॉक कंटेनर में चल रहे अपने फ्लास्क ऐप को एक्सेस करने के लिए। 172.17.0.2जो भी विशेष IP पता आपके कंटेनर का है उसे प्रतिस्थापित करें।


0

सबसे पहले अपने अजगर की स्क्रिप्ट में आपको कोड बदलने की आवश्यकता है

app.run()

सेवा

app.run(host="0.0.0.0")

दूसरा, आपके डॉकटर फ़ाइल में, अंतिम पंक्ति जैसी होनी चाहिए

CMD ["flask", "run", "-h", "0.0.0.0", "-p", "5000"]

और पर होस्ट मशीन अगर 0.0.0.0:5000काम नहीं होता है आप के साथ प्रयास करना चाहिएlocalhost:5000

नोट - CMD कमांड को उचित होना चाहिए। क्योंकि CMD कमांड कंटेनर को निष्पादित करने के लिए चूक प्रदान करते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.