Docker 部署一个用 Python 编写的 Web 应用

Michael阿明 2021-09-15 11:19:08
docker Python 部署 编写 一个



learn from 《深入剖析Kubernetes》

1. 安装 docker

在 WSL2 中安装 docker https://www.runoob.com/docker/ubuntu-docker-install.html
会报错:

# Executing docker install script, commit: 93d2499759296ac1f9c510605fef85052a2c32be
WSL DETECTED: We recommend using Docker Desktop for Windows.
Please get Docker Desktop from https://www.docker.com/products/docker-desktop
You may press Ctrl+C now to abort this script.
+ sleep 20

去下载安装 windows 下的 docker
在这里插入图片描述
在这里插入图片描述

2. 编写代码

使用 Flask 框架启动了一个 Web 服务器,而它唯一的功能是:如果当前环境中有 “NAME” 这个环境变量,就把它打印在 “Hello” 后,否则就打印 “Hello world”,最后再打印出当前环境的 hostname

import os
from flask import Flask
import socket
from gevent import pywsgi
app = Flask(__name__)
@app.route('/')
def hello():
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())
if __name__ == "__main__":
server = pywsgi.WSGIServer(('0.0.0.0', 12345), app)
server.serve_forever()

导出依赖包

pip freeze >requirements.txt
Flask==2.0.1
gevent==21.8.0
greenlet==1.1.1
itsdangerous==2.0.1
Jinja2==3.0.1
MarkupSafe==2.0.1
Werkzeug==2.0.1
zope.event==4.5.0
zope.interface==5.4.0

3. 编写 Dockerfile

# 使用官方提供的 Python 开发镜像作为基础镜像 
FROM python:3.8-slim
# 将工作目录切换为 /app 
WORKDIR /app
# 将当前目录下的所有内容复制到 /app 下 
ADD . /app
# 使用 pip 命令安装这个应用所需要的依赖 
# RUN pip install --trusted-host pypi.python.org -r requirements.txt 
RUN pip install --trusted-host https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
# 国内的源更快
# 允许外界访问容器的 12345 端口 
EXPOSE 12345
# 设置环境变量 
ENV NAME World
# 设置容器进程为:python app.py,即:这个 Python 应用的启动命令 
CMD ["python", "app.py"]
# CMD 前面 隐式的包含了 ENTRYPOINT , /bin/sh -c

在这里插入图片描述
在 WSL 里操作 :

  • 让 docker 制作镜像,-t 加 tag,自动加载 Dockerfile,执行里面的语句
docker build -t helloworld .
[+] Building 17.4s (10/10) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 757B 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/python:3.8-slim 2.9s
=> [auth] library/python:pull token for registry-1.docker.io 0.0s
=> [1/4] FROM docker.io/library/python:3.8-slim@sha256:4dd66d1ccaddaa0587851cb92b365bf3090dccb41393c6f8b 0.0s
=> [internal] load build context 0.1s
=> => transferring context: 813B 0.0s
=> CACHED [2/4] WORKDIR /app 0.0s
=> [3/4] ADD . /app 0.1s
=> [4/4] RUN pip install --trusted-host https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt 13.6s
=> exporting to image 0.6s
=> => exporting layers 0.6s
=> => writing image sha256:390d32b9f7a20ccd347361bd31450807d3e63d052e334865cf8460968ffceff4 0.0s
=> => naming to docker.io/library/helloworld 0.0s
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
  • 查看镜像
(k8s)PC:/mnt/d/gitcode/k8s$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld latest 390d32b9f7a2 About a minute ago 169MB
  • 启动容器
docker run -p 4000:12345 helloworld

因为在 Dockerfile 中已经指定了 CMD。否则,就得把进程的启动命令加在后面 python app.py

  • 查看容器启动
(base) $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6e051d1af6b helloworld "python app.py" 2 minutes ago Up 2 minutes 0.0.0.0:4000->12345/tcp, :::4000->12345/tcp upbeat_elion

通过 -p 4000:12345 告诉 Docker,把容器内的 12345 端口映射在宿主机的 4000 端口上

这样做的目的是,只要访问宿主机的 4000 端口,就可以看到容器里应用 返回的结果

curl http://localhost:4000
# <h3>Hello World!</h3><b>Hostname:</b> dc1c1343e366<br/>

使用容器完成了一个应用的开发与测试

4. 上传镜像

注册 docker hub,docker login 命令登录

docker tag helloworld kobe24o/helloworld:v0

kobe24o 是账号名(镜像仓库),helloworld 镜像名,v0自己分配的版本号

docker push kobe24o/helloworld:v0
(k8s) $ docker push kobe24o/helloworld:v0
The push refers to repository [docker.io/kobe24o/helloworld]
931022d457d6: Pushing [================> ] 16.07MB/47.27MB
c76dc68917fc: Pushed
047ca6dfe9ab: Pushed
d82f4c466b47: Mounted from library/python
5aa75f4e55e7: Mounted from library/python
74d6903a940b: Mounted from library/python
2f9c2b8e82bd: Mounted from library/python
ba5a5fe43301: Mounted from library/python

5. 修改镜像

(base) $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
dd3bf057cb09 helloworld "python app.py" 7 seconds ago Up 5 seconds 0.0.0.0:4000->12345/tcp, :::4000->12345/tcp compassionate_carver
(base) $ docker exec -it dd3bf057cb09 /bin/sh
# pwd
/app
# touch newfile.txt
# ls
Dockerfile app.py newfile.txt requirements.txt
# exit
(base) $ docker commit dd3bf057cb09 kobe24o/helloworld:v1
sha256:ca8880f84040f9bdd7ef13763b9c64f8bd4a513a74bc2b095be06aae5b60268a

上面操作,新加了一个文件到镜像里,commit 保存

docker inspect --format '{
{ .State.Pid}}' dd3bf057cb09
1763
# 查看正在运行的容器的进程号 PID 

通过查看宿主机的 proc 文件,看到这个 进程的所有 Namespace 对应的文件

root:/# ls -l /proc/{PID}/ns/
total 0
lrwxrwxrwx 1 root root 0 Sep 14 11:15 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Sep 14 11:15 ipc -> 'ipc:[4026532220]'
lrwxrwxrwx 1 root root 0 Sep 14 09:49 mnt -> 'mnt:[4026532218]'
lrwxrwxrwx 1 root root 0 Sep 14 11:15 net -> 'net:[4026531992]'
lrwxrwxrwx 1 root root 0 Sep 14 11:15 pid -> 'pid:[4026532221]'
lrwxrwxrwx 1 root root 0 Sep 14 11:15 pid_for_children -> 'pid:[4026532221]'
lrwxrwxrwx 1 root root 0 Sep 14 11:15 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Sep 14 11:15 uts -> 'uts:[4026532219]'

一个进程,可以选择 加入 到某个进程已有的 Namespace 当中,从而达到 “进入” 这个进程所在容器的目的,这正是 docker exec 的实现原理

  • push 到 hub
(base) $ docker push kobe24o/helloworld:v1
The push refers to repository [docker.io/kobe24o/helloworld]
dfee38b42dbb: Pushed
931022d457d6: Layer already exists
c76dc68917fc: Layer already exists
047ca6dfe9ab: Layer already exists
d82f4c466b47: Layer already exists
5aa75f4e55e7: Layer already exists
74d6903a940b: Layer already exists
2f9c2b8e82bd: Layer already exists
ba5a5fe43301: Layer already exists
v1: digest: sha256:7af7ff571ea9fd70d48abeaa2b38a1ed1c1a4e5a933b722d82af25d3e889f84e size: 2206

版权声明
本文为[Michael阿明]所创,转载请带上原文链接,感谢
https://michael.blog.csdn.net/article/details/120280399

  1. Realizing the function of sending e-mail automatically with Python
  2. Smtpauthenticationerror in Python: solution
  3. 8 steps to teach you how to solve Sudoku in Python! (including source code)
  4. Python change la vie | identifier facilement des centaines de numéros de livraison
  5. Python change life | utilisation de modèles reconnus par ocr
  6. Bibliothèques Python utiles et intéressantes - - psutil
  7. 3. Traitement des données pandas
  8. 【Python编程基础】控制流之链式比较运算符
  9. MFC uses Python scripting language
  10. 【Python編程基礎】控制流之鏈式比較運算符
  11. 【 base de programmation python】 opérateur de comparaison de chaîne pour le flux de contrôle
  12. Python game development, pyGame module, python implementation of Xiaole games
  13. Mise en œuvre du Code de vérification unique (OTP) avec le cadre de repos Django
  14. Python - eval ()
  15. Python - Programmation orientée objet - _Rapport()
  16. Différence entre python - rep (), Str ()
  17. Python - Programmation orientée objet - _Appel()
  18. Python calling matlab script
  19. Python - Programmation orientée objet - _Nouveau() et mode Singleton
  20. Python - Programmation orientée objet - méthode magique (méthode de double soulignement)
  21. Python - Programmation orientée objet - pratique (6)
  22. Python - Programmation orientée objet - réflexion hasattr, GetAttr, GetAttr, delattr
  23. Python - Programmation orientée objet - _Dict
  24. Python - pydantic (2) Modèle imbriqué
  25. Non-ASCII character ‘\xe5‘ in file kf1.py on line 4, but no encoding declared; see http://python.or
  26. python笔记(一)
  27. Non - ASCII character 'xe5' in file kf1.py on Line 4, but no Encoding declared;Voirhttp://python.or
  28. Notes Python (1)
  29. Talk about how JMeter executes Python scripts concurrently
  30. In Beijing, you can't see the moon in the Mid Autumn Festival. Draw a blood red moon in Python
  31. Un des pandas crée un objet
  32. Machine learning | unitary regression model Python practical case
  33. Draw a "Lollipop chart" with Excel and python
  34. Python uses scikit learn to calculate TF-IDF
  35. Getting started with Python Basics_ 3 conditional statements and iterative loops
  36. Python dynamic properties and features
  37. 云计算开发:Python内置函数-min()函数详解
  38. [Python skill] how to speed up loop operation and numpy array operation
  39. 雲計算開發:Python內置函數-min()函數詳解
  40. Développement de l'informatique en nuage: explication détaillée de la fonction intégrée python - min ()
  41. 从0起步学Python(附程序实例讲解)第1讲
  42. 从0起步学Python(附程序实例讲解)第1讲
  43. Apprendre Python à partir de 0 (avec des exemples de programme) leçon 1
  44. Apprendre Python à partir de 0 (avec des exemples de programme) leçon 1
  45. With Python, I'll take you to enjoy it for a month when the Mid Autumn Festival is coming
  46. You can't write interface software in Python! Which software on sale has no UI?
  47. Python国内外原题解析及源码1~15
  48. Python实现长篇英文自动纠错~
  49. Python implémente la correction automatique des erreurs en anglais long
  50. Analyse des problèmes originaux et code source de Python au pays et à l'étranger 1 ~ 15
  51. 一张思维导图学Python之表白
  52. Python教学中课程思政建设的研究探索2
  53. Recherche sur la construction idéologique et politique du Programme d'études dans l'enseignement Python 2
  54. Une présentation de la cartographie mentale Python
  55. Python高级用法总结(8)-函数式编程
  56. Python + Mirai development QQ robot starting tutorial (2021.9.9 test is valid)
  57. Python Advanced use Summary (8) - functional Programming
  58. How to get started with Python and share learning methods for free. All you want to know is here
  59. Python + Mirai development QQ robot starting tutorial (2021.9.9 test is valid)
  60. Python基础第1讲(含代码、Python最新安装包、父与子的编程之旅:与小卡特一起学Python中文版)