2020系统综合实践 第5次实践作业

本次作业为Python专题。Python是将练习使用docker容器运行Python程序。Python是很常用的程序设计语言,但是Python程序的运行依赖于提前的系统环境配置,为了降低系统配置的复杂度,同时减小资源开销,将系统环境容器化是一种解决方案。请根据Python官方镜像的镜像说明,自定义Python镜像文件,将Python程序运行起来。

1、Python自定义镜像搭建

docker pull python:3.7  #拉取dockerhub上的python镜像

Dockerfile文件

#构建一个自定义镜像
Dockefile
FROM python:3.7
WORKDIR /usr/src/app  # 设置工作目录
COPY requirements.txt ./  # 添加依赖声明文件
RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
COPY apps/hello.py /usr/src/app/
VOLUME /usr/src/app
ENTRYPOINT ["python"]    # 实现命令行式调用容器
CMD ["hello.py"]   # ENTRYPOINT默认参数

requirements.txt中声明所需依赖:

#requirements.txt
PyMySQL
opencv-python
docker build -t python:v1 .  #构建自定义镜像

2、运行Python程序

在1、的基础上,通过容器完成简单helloworld、日历输出mysql数据库操作opencv程序的部署运行
mysql数据库可以使用之前作业创建的镜像
opencv可以参照链接任意选择

为便于程序修改调试,在容器启动时需将本地文件目录挂载至容器内的工作目录

文档结构

2.1 helloworld

#hello.py
print('hello world')
#无交互式输入:
docker run -v /home/ubuntu/5th/apps:/usr/src/app --rm [镜像名:标签]

参数说明:

  • 使用-v将本地目录挂载到python工作目录以方便代码修改
  • --rm运行完毕后自动移除容器(太方便了!)
  • 默认使用Dockerfile中ENTRYPOINT默认参数CMD ["hello.py"] 指定的hello.py作为命令行参数

2.2 日历输出

#date.py
import calendar
yy = int(input("输入年份: "))
mm = int(input("输入月份: "))
print(calendar.month(yy,mm))
#有交互式输入:
docker run -it -v /home/ubuntu/python/apps:/usr/src/app --rm [镜像名:标签] xx.py

注意:

  • 当命令行有输入需要执行的python文件就不会执行dockerfile中的CMD ["hello.py"]命令。
  • 由于用到了input,需要输入内容,因此运行容器的时候需要用到-it参数,否则会报EOFError: EOF when reaeding a line的错误。
  • 以上两个例子没有用到在requirement.txt中添加额外的包

2.3 mysql数据库操作

2.3.1 docker network create命令用于创建一个新的网络连接

docker network create --subnet=172.1.0.0/16 py_mysql #创建名为py_mysql的网络

2.3.2 在创建的网络中运行python和mysql容器

docker run --network py_mysql --name mysql1 -d mymysql:v1
docker exec -it mysql1 /bin/bash
docker run -it --network py_mysql -v /home/ubuntu/5th/apps:/usr/src/app --rm 
python:v1 db.py

db.py文件

#db.py 向已有的数据库和表格中添加一条数据(031702500,zz)
import pymysql

# 打开数据库连接
#数据库地址使用mysql的容器名
#使用实验二时候创建的用户,密码,数据库
db = pymysql.connect("mysql1", "hh", "123456", "docker_mysql") 
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()

# 使用 execute()  方法执行 SQL 查询
cursor.execute("SELECT VERSION()")

# 使用 fetchone() 方法获取单条数据.
data = cursor.fetchone()

print("Database version : %s " % data)

# SQL 插入语句
sql = """INSERT INTO user(id,name)
         VALUES (031702500', 'zz')"""
try:
   # 执行sql语句
   cursor.execute(sql)
   # 提交到数据库执行
   db.commit()
except:
   # 如果发生错误则回滚
   db.rollback()

# SQL 查询语句
sql = """SELECT * FROM EMPLOYEE"""

try:
   # 执行SQL语句
   cursor.execute(sql)
   # 获取所有记录列表
   results = cursor.fetchall()
   for row in results:
      idddd = row[0]
      name = row[1]
       # 打印结果
      print ("idddd=%s,namee=%s 
             (idddd, namee ))
except:
   print ("Error: unable to fetch data")

# 关闭数据库连接
db.close()

2.4 opencv程序的部署运行

cv.py

# cv.py将图片旋转90度并保存
import cv2

# flags传入0表示灰度图像, 1表示彩色图像
img=cv2.imread('test.jpg',flags=1)

# 获取图片尺寸
rows,cols=img.shape[:2]

# 这里的第一个参数为旋转中心,第二个为旋转角度,第三个为旋转后的缩放因子
# 可以通过设置旋转中心,缩放因子,以及窗口大小来防止旋转后超出边界的问题
M=cv2.getRotationMatrix2D((cols/2,rows/2),90,1)

# 第三个参数是输出图像的尺寸中心
dst=cv2.warpAffine(img,M,(cols,rows))

# 写入文件
cv2.imwrite("test-rotated.jpg", dst, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
print('rotated and saved.')
docker run -v /home/ubuntu/5th/apps:/usr/src/app --rm python:v1 cv.py

3、小结

3.1 问题和解决办法

问题一:可能是挂载没有成功,找不到py文件

解决方法:命令写错了,容器内的地址应该是/usr/src/app
问题二:AttributeError:module ‘calendar’ has no attribute ‘month’错误

解决方法:出现这个错误的一个可能的原因是执行的*.py文件文件名和Python自带文件或者第三方库文件重名。把py的名字改掉就好了。
问题三:创建了网络,但是mysql没连上网络

解决方法:先运行的mysql也要使用--network py_mysql,确保两个容器能在同一个网络内。

3.2 经验

花了两个上午看资料,做实验,写博客。这次实验相对来说比上次的要简单很多。主要是在数据库连接的地方花了比较多的时间,一个是没有提前把python容器和mysql放在同一个网络中,还有一个是数据库地址用了localhost,172.18.0.1等都没有连上,最后是看到老师的博客说是写数据库容器名字才知道。

原文地址:https://www.cnblogs.com/huang0926huang/p/12904815.html