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

文章目录

    • 1. 安装 docker
    • 2. 编写代码
    • 3. 编写 Dockerfile
    • 4. 上传镜像
    • 5. 修改镜像

learn from 《深入剖析Kubernetes》

1. 安装 docker

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

# Executing docker install script, commit: 93d2499759296ac1f9c510605fef85052a2c32beWSL DETECTED: We recommend using Docker Desktop for Windows.
Please get Docker Desktop from https://www.docker.com/products/docker-desktopYou 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.0sUse '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         PORTSNAMES
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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/471674.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 代码文件路径注意事项

检查代码的工作路径&#xff0c;是不是代码文件所在路径 导入别处的包 基于该代码的工作路径写如下的代码&#xff0c;加入相对路径&#xff0c;可以找到要导入的文件 import sys import os sys.path.append("../xxx/") sys.path.append("../../xxx") fro…

微信小程序独立服务器的好处,微信小程序的优势和缺点

原标题&#xff1a;微信小程序的优势和缺点微信小程序从刚开始面世就引起了很多人的关注&#xff0c;虽然截止到目前&#xff0c;官方仍没有大肆宣传和推广&#xff0c;但是微信小程序的所带来的影响还是很大的&#xff0c;甚至让苹果&#xff0c;百度&#xff0c;阿里都头疼不…

LeetCode 2007. 从双倍数组中还原原数组(map)

文章目录1. 题目2. 解题1. 题目 一个整数数组 original 可以转变成一个 双倍 数组 changed &#xff0c;转变方式为将 original 中每个元素 值乘以 2 加入数组中&#xff0c;然后将所有元素 随机打乱 。 给你一个数组 changed &#xff0c;如果 change 是 双倍 数组&#xff…

怎么画韦布尔分布_手机按键寿命测试的样本数量怎么定?一文看懂 简述威布尔分布及其应用...

有一种手机按键的质量要求是&#xff0c;95%的产品的按压寿命需要达到1万次。根据这一要求&#xff0c;QC部门需要进行1.2万次的按压测试。那么QC部门需要选取多少按键来进行测试&#xff08;不允许有失效&#xff09;&#xff0c;才能保证95%的按键按压寿命达到1万次呢&#x…

Chrome浏览器报错:Origin null is not allowed by Access-Control-Allow-Origin.

问题&#xff1a;Chrome浏览器报错&#xff1a;Origin null is not allowed by Access-Control-Allow-Origin. 原因&#xff1a;.js文件中使用load()方法&#xff0c;而Chrome浏览器出于安全起见&#xff0c;不允许load本地文件。 方法&#xff1a;给Chrome添加启动参数--allow…

LeetCode 2008. 出租车的最大盈利(DP)

文章目录1. 题目2. 解题1. 题目 你驾驶出租车行驶在一条有 n 个地点的路上。 这 n 个地点从近到远编号为 1 到 n &#xff0c;你想要从 1 开到 n &#xff0c;通过接乘客订单盈利。 你只能沿着编号递增的方向前进&#xff0c;不能改变方向。 乘客信息用一个下标从 0 开始的二…

华为服务器清除系统日志,清空服务器日志

清空服务器日志 内容精选换一换为加强对系统数据的容灾管理&#xff0c;云堡垒机支持配置日志备份&#xff0c;提高审计数据安全性和系统可扩展性。本小节主要介绍如何在系统配置FTP/SFTP服务器参数&#xff0c;将日志远程备份至FTP/SFTP服务器。开启远程备份后&#xff0c;系统…

动态行转列小记

数据库环境&#xff1a;SQL SERVER 2005 最近在整理数据时&#xff0c;要将查询到的数据张贴到Excel中。在Excel中&#xff0c;要展示的行数是固定的&#xff0c;列数不固定&#xff0c; 一个一个数据的复制张贴太烦人。想了一个偷懒的方法&#xff0c;直接将查询的数据进行行转…

使用swiper_关于使用swiper制作web轮播图

我这个方法是很适用于小白的&#xff0c;利用swiper插件的应用。https://www.swiper.com.cn/这个是swiper中文官网的网址&#xff0c;上面有关于swiper的说明和使用方法。想要用到swiper插件要在官网下载swiper文件&#xff0c;如下图所示&#xff0c;在导航条上面找到下载swip…

LeetCode 2012. 数组美丽值求和

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 nums 。对于每个下标 i&#xff08;1 < i < nums.length - 2&#xff09;&#xff0c;nums[i] 的 美丽值 等于&#xff1a; 2&#xff0c;对于所有 0 < j < i 且 i < k < nums.length - 1 …

华为服务器上传文件后怎么通过链接查看,远程服务器文件上传后的操作

远程服务器文件上传后的操作 内容精选换一换本节指导您基于Linux操作系统环境完成镜像文件快速导入&#xff0c;推荐使用云平台的EulerOS云服务器作为转换镜像格式和生成位表文件的环境。Linux操作系统环境下&#xff0c;建议使用qemu-img-hw工具进行镜像格式转换。已完成镜像文…

Android学习笔记(十三)

Android中的广播机制 Android提供了一套完整的API&#xff0c;允许应用程序自由地发送和接受广播。 发送广播的方法借助于Intent&#xff0c;接受广播的方法需要广播接收器&#xff08;BroadcastsReceiver&#xff09;。 Android中的广播主要分为两种类型&#xff0c;标准广播和…

LeetCode 2013. 检测正方形(字典)

文章目录1. 题目2. 解题2.1 超时2.1 改进1. 题目 给你一个在 X-Y 平面上的点构成的数据流。设计一个满足下述要求的算法&#xff1a; 添加 一个在数据流中的新点到某个数据结构中。可以添加 重复 的点&#xff0c;并会视作不同的点进行处理。给你一个查询点&#xff0c;请你从…

python 获取英文人名翻译

# 获取中英文人名翻译 import time import urllib.requestdef getename(ename_dataename2cname.txt):flag "jerry.asp?id" # 特定标记位置url https://name.supfree.net/tom.asp?idalphas [chr(x) for x in range(ord(a), ord(z) 1)]with open(ename_data, w,…

浅析Java内存模型

概述 Java内存模型的主要目标是定义程序中各个变量的访问规则&#xff0c;即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量是线程共享的&#xff0c;存在竞争问题的。 Java内存模型规定了所有的变量都存储在主内存&#xff0c;每条线程还有自己的工…

fastapi quickstart学习

文章目录1. 安装包2. 编写代码3. 终端运行4. 文档5. 增加数据learn from https://fastapi.tiangolo.com/zh/#typer-fastapi 1. 安装包 # pip install fastapi # pip install uvicorn[standard]2. 编写代码 main.py from typing import Optional # typing 模块用于类型检查…

单列变双列css_css 两列布局中单列定宽单列自适应布局的6种思路

前面的话说起自适应布局方式&#xff0c;单列定宽单列自适应布局是最基本的布局形式。本文将从float、inline-block、table、absolute、flex和grid这六种思路来详细说明如何巧妙地实现布局float【思路一】float说起两列布局&#xff0c;最常见的就是使用float来实现。float浮动…

fastapi 用户指南(路径参数、查询参数、请求体)

文章目录1. 第一步1.1 小结2. 路径参数2.1 顺序很重要2.2 预设值2.3 包含路径的路径参数3. 查询参数3.1 查询参数类型转换4. 请求体learn from https://fastapi.tiangolo.com/zh/tutorial/1. 第一步 pip install fastapi[all] from fastapi import FastAPI my_app FastAPI(…

DirectX API 编程起步 #01 项目设置

目录&#xff1a; DirectX API 编程起步 #02 窗口的诞生 DirectX API 编程起步 #02 创建3D世界 这里记录了我从零开始学习使用 DirectX API 的过程。 参考教程&#xff1a;rastertek -> DirectX 11 Tutorials 准备工作 1&#xff09;首先我们要有一套能写代码的软件&#…

LeetCode 2016. 增量元素之间的最大差值

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 nums &#xff0c;该数组的大小为 n &#xff0c;请你计算 nums[j] - nums[i] 能求得的 最大差值 &#xff0c;其中 0 < i < j < n 且 nums[i] < nums[j] 。 返回 最大差值 。如果不存在满足要求…