本次作业为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等都没有连上,最后是看到老师的博客说是写数据库容器名字才知道。