In meine letzten Artikel habe ich euch gezeigt, wie man mit einem Dockerfile eine Docker Image erstellen kann. Darauf möchte ich diesmal aufbauen und zeigen, wie man eine Docker Image mit einer kleinen Python Flask App erstellt und diesen startet.
Inhaltsverzeichnis
Vorbereitung der Python Flask App
Als erstes legen wir uns einen entsprechende Ordnerstruktur für unser Image an. Das ganze sieht bei mir wie folgt aus
1 2 3 4 5 6 | tree . └── example_app ├── Dockerfile └── app └── app.py |
Anschließend öffnen wir die Datei app.py. In diese fügen wir den folgenden Python Code ein. Da es sich hier nicht um ein ein Flask Tutorial handelt, verzichte ich an dieser Stelle auf eine entsprechende Erklärung des Codes.
1 2 3 4 5 6 7 8 9 | from flask import Flask app = Flask(__name__) @app.route('/') def hello_docker(): return 'Hello, I run in a docker container' if __name__ == '__main__': app.run(host='0.0.0.0') |
Anlegen des Dockerfile und erstellen des Docker Images
Widmen wir uns nun dem Dockerfile. Dieses hat bei mir den folgenden Inhalt
1 2 3 4 5 6 7 | FROM python:3.6 RUN pip install Flask RUN useradd -ms /bin/bash admin USER admin WORKDIR /app COPY app /app CMD ["python", "app.py"] |
FROM: Mit dem FROM Befehl, legen wir fest welches Base Image wir verwenden wollen. In diesem Fall bediene ich mich an dem python Image mit dem Tag 3.6
RUN: Mit dem ersten RUN Befehl installieren wir Flask über den Python Paketmanager pip nach. Der zweite RUN Befehl dient dazu, einen weiteren user mit dem Name admin anzulegen. Dieser dient dazu, dass die App nicht als root User gestartet wird.
USER: Mit diesem Befehl wechseln wir zum User admin
WORKDIR: WORKDIR legt das aktuelle Arbeitsverzeichnis fest
COPY: Anschließend kopieren wir mit dem COPY Befehl den Inhalt unseres app Ordners im Docker Image nach /app
CMD: Zu guter letzt führen wir die App aus. Da wir vorher das WORKDIR gesetzt haben, reicht ein einfacher aufruf der app.py
Nachdem das Dockerfile erstellt wurde, kann mit dem Erstellen des Docker Images begonnen werden. Dafür verwende man den Befehl docker build -t dockerapp:v0.1 .
Das ganze sieht dann folgendermaßen aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | docker build -t dockerapp:v0.1 . Sending build context to Docker daemon 3.584kB Step 1/7 : From python:3.6 3.6: Pulling from library/python cc1a78bfd46b: Pull complete 6861473222a6: Pull complete 7e0b9c3b5ae0: Pull complete 3ec98735f56f: Pull complete 9b311b87a021: Pull complete 048165938570: Pull complete 1ca3d78efb22: Pull complete 0f6c8999c3b7: Pull complete 5a85410f5000: Pull complete Digest: sha256:52a2bd143faf6430b182b56a5fdeb70f26b8ca8fbd40210c3ed8a8ee1eaba343 Status: Downloaded newer image for python:3.6 ---> 29d2f3226daf Step 2/7 : RUN pip install Flask ---> Running in a9400b472ba6 Collecting Flask Downloading https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl (91kB) Collecting click>=5.1 (from Flask) Downloading https://files.pythonhosted.org/packages/34/c1/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77/click-6.7-py2.py3-none-any.whl (71kB) Collecting Jinja2>=2.10 (from Flask) Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB) Collecting itsdangerous>=0.24 (from Flask) Downloading https://files.pythonhosted.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz (46kB) Collecting Werkzeug>=0.14 (from Flask) Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB) Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->Flask) Downloading https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz Building wheels for collected packages: itsdangerous, MarkupSafe Running setup.py bdist_wheel for itsdangerous: started Running setup.py bdist_wheel for itsdangerous: finished with status 'done' Stored in directory: /root/.cache/pip/wheels/2c/4a/61/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5 Running setup.py bdist_wheel for MarkupSafe: started Running setup.py bdist_wheel for MarkupSafe: finished with status 'done' Stored in directory: /root/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46 Successfully built itsdangerous MarkupSafe Installing collected packages: click, MarkupSafe, Jinja2, itsdangerous, Werkzeug, Flask Successfully installed Flask-1.0.2 Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 itsdangerous-0.24 Removing intermediate container a9400b472ba6 ---> 7ccdf491dc92 Step 3/7 : RUN useradd -ms /bin/bash admin ---> Running in 53cca5e81857 Removing intermediate container 53cca5e81857 ---> f19713be5cfe Step 4/7 : USER admin ---> Running in 201565b07fb3 Removing intermediate container 201565b07fb3 ---> fca960127c4b Step 5/7 : WORKDIR /app Removing intermediate container 4ae750177f23 ---> 2e72d0f77cb7 Step 6/7 : COPY app /app ---> f25babde6ce3 Step 7/7 : CMD ["python", "app.py"] ---> Running in e36f32556d11 Removing intermediate container e36f32556d11 ---> eb905ad45530 Successfully built eb905ad45530 Successfully tagged dockerapp:v0.1 |
Ausführen des Docker Images
Das zuvor erstellte Docker Image findet man nun in der Image Übersicht.
1 2 3 4 5 6 7 8 | docker images REPOSITORY TAG IMAGE ID CREATED SIZE dockerapp v0.1 eb905ad45530 24 seconds ago 923MB tomcat 8.0 8bfd42907609 2 weeks ago 360MB python 3.6 29d2f3226daf 3 weeks ago 912MB deeplearning latest d3bafbcb73ed 2 months ago 7.73GB ubuntu 16.04 0458a4468cbc 4 months ago 112MB rawar/deeplearning latest 8065c45e70c1 19 months ago 3.97GB |
Aus dieser Übersicht braucht man die Image ID um nun einen Container zu starten.
1 2 | docker run -d -p 5000:5000 eb905ad45530 27ddd3caadab07c06b2c01a626451ed4ad0323398eb4c3990807ef0c3ac64422 |
Nach dem Starten des Containers sollte diese in der docker ps liste auftauchen.
1 2 3 | docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 27ddd3caadab eb905ad45530 "python app.py" 2 hours ago Up 2 hours 0.0.0.0:5000->5000/tcp sad_blackwell |
Nun können wir die Python App im Browser unter 127.0.0.1:5000 aufrufen.
Um den Docker Container wieder zu stoppen kann der folgende Befehl verwendet werden.
1 2 | docker stop 27ddd3caadab 27ddd3caadab |
Wenn der Artikel für euch interessant war, dann schaut euch auch meinen Artikel zum Thema Docker Network – Eine kleine Übersicht an.
Der Artikel ist super verständlich, deswegen konnte ich das auch alles nachvollziehen und starten. Beim Aufrufen von Port 5000 von 127.0.0.1 kommt dann allerdings „connection refused“. Evtl hängt das mit irgendwelchen Berechtigungen unter Windows Docker zusammen?
Hi,
habe Docker unter Windows noch nicht verwendet. Aber ich würde mal vermuten, dass du die Windows Firewall ausschalten musst.
Gruß
Christian
Danke für die Anleitung. Ich kenne es so, dass man Ports im Dockerfile explizit freigibt.
Wenn es Port 5000 ist, wäre das hinzufügen von
EXPOSE 5000
sicherlich nicht falsch.
https://docs.docker.com/engine/reference/builder/#expose