PythonDocker教程展示了如何将Docker用于Python应用程序。
泊坞窗
Docker是一个供开发人员和系统管理员使用容器构建、运行和共享应用程序的平台。Docker促进了应用程序的可移植性和可扩展性。Docker提供了应用程序隔离,从而消除了由库和环境差异引起的许多问题。它有助于自动化开发和部署。借助预定义的社区图像,开发人员可以节省时间并改善他们的整体体验。
Docker镜像是一个只读模板,其中包含创建Docker容器的说明。Docker容器是图像的可运行实例。
Docker图像存储在存储库中。DockerHub是官方的Docker存储库。Docker引擎是使用Docker的组件和服务构建和运行容器的底层客户端-服务器技术。
Dockerfile是一个特殊文件,其中包含构建Docker映像所需的指令。
$ sudo docker --version Docker version 19.03.12, build 48a66213fe
这是我们使用的Docker版本。
PythonDocker你好示例
在下面的例子中,我们创建并运行了一个非常简单的Docker镜像。当我们运行图像时,会执行一个简单的Python文件。
#!/usr/bin/python
import sys
print("hello there!")
print(sys.version)
这是要在容器内执行的简单文件。
FROM python:3.8 COPY hello.py /tmp/ CMD ["python", "/tmp/hello.py"]
这些是构建Docker镜像的说明。
FROM python:3.8
我们的图像基于社区python:3.8图像。
COPY hello.py /tmp/
COPY指令将hello.py文件复制到图像的tmp目录中。
CMD ["python", "/tmp/hello.py"]
CMD指令启动Python程序。
$ sudo docker build -t hello .
我们构建图像并将其命名为hello。
$ sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 60251c18f538 5 minutes ago 882MB firstimage latest 319917db1025 5 hours ago 111MB python slim 38cd21c9e1a8 5 days ago 113MB python 3.8 79cc46abd78d 5 days ago 882MB python latest 79cc46abd78d 5 days ago 882MB
我们使用dockerimages命令列出可用的图像。
$ sudo docker run hello hello there! 3.8.5 (default, Aug 5 2020, 08:22:02) [GCC 8.3.0]
我们运行hello图像。
PythonDocker交互模式
我们可以使用-it选项以交互模式运行图像。-it指示Docker分配一个连接到容器标准输入的伪TTY;在容器中创建交互式bashshell。
$ sudo docker run -it python3.8:slim bash root@98ece0c01946:/#
我们运行图像并在容器中获取bashshell。
root@98ece0c01946:/# python -c "import os; print(os.system('ls -l'))"
total 68
drwxr-xr-x 1 root root 4096 Aug 4 16:25 bin
drwxr-xr-x 2 root root 4096 Jul 10 21:04 boot
drwxr-xr-x 5 root root 360 Aug 19 13:40 dev
drwxr-xr-x 1 root root 4096 Aug 19 13:39 etc
drwxr-xr-x 2 root root 4096 Jul 10 21:04 home
drwxr-xr-x 1 root root 4096 Aug 4 16:25 lib
drwxr-xr-x 2 root root 4096 Aug 3 07:00 lib64
drwxr-xr-x 2 root root 4096 Aug 3 07:00 media
drwxr-xr-x 2 root root 4096 Aug 3 07:00 mnt
drwxr-xr-x 2 root root 4096 Aug 3 07:00 opt
dr-xr-xr-x 345 root root 0 Aug 19 13:40 proc
drwx------ 1 root root 4096 Aug 4 16:18 root
drwxr-xr-x 3 root root 4096 Aug 3 07:00 run
drwxr-xr-x 2 root root 4096 Aug 3 07:00 sbin
drwxr-xr-x 2 root root 4096 Aug 3 07:00 srv
dr-xr-xr-x 13 root root 0 Aug 19 13:40 sys
drwxrwxrwt 1 root root 4096 Aug 11 20:37 tmp
drwxr-xr-x 1 root root 4096 Aug 3 07:00 usr
drwxr-xr-x 1 root root 4096 Aug 3 07:00 var
0
我们可以运行Python代码。
root@98ece0c01946:/# python -c "import sys; print(sys.version)" 3.8.5 (default, Aug 4 2020, 16:24:08) [GCC 8.3.0]
在我们的例子中,我们预装了Python3.8.5。
PythonDocker获取请求
在下一个示例中,我们构建一个检索HTML页面的图像。我们使用requests库,它必须安装在镜像中。
#!/usr/bin/python
import requests as req
resp = req.get("http://webcode.me")
print(resp.text)
代码示例通过发出GET请求重试简单网页。
FROM python:slim RUN pip install requests COPY get_req.py /tmp/ CMD ["python", "/tmp/get_req.py"]
这是Dockerfile。
FROM python:slim
在这个例子中,我们使用社区python:slim图像,它占用的空间要小得多。
RUN pip install requests
使用RUN指令,我们执行pip管理器并安装requests模块。
COPY get_req.py /tmp/
COPY指令将get_req.py文件从我们的主机复制到容器的/tmp/目录。如果目录不存在,则创建该目录。
CMD ["python", "/tmp/get_req.py"]
CMD指令在启动容器时运行程序。
$ sudo docker build -t pygetreq .
我们构建图像并将其命名为pygetreq。
$ sudo docker images | grep pygetreq pygetreq latest 0d3c5953ff60 23 seconds ago 121MB
这张图片只需要121MB。
$ sudo docker run pygetreq
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My html page</title>
</head>
<body>
<p>
Today is a beautiful day. We go swimming and fishing.
</p>
<p>
Hello there. How are you?
</p>
</body>
</html>
PythonDocker烧瓶
在下一个示例中,我们将在Docker容器中运行一个简单的Flask应用程序。
#!/usr/bin/python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello there!'
这是一个简单的Flask应用程序,只有一条主路径。
FROM python:slim COPY app.py /app/ WORKDIR /app RUN pip install flask RUN export FLASK_APP=app.py EXPOSE 5000 CMD ["/usr/local/bin/flask", "run", "--host", "0.0.0.0"]
这是Dockerfile。
FROM python:slim
我们的图像基于python-slim图像。
COPY app.py /app/ WORKDIR /app
我们复制一个文件到镜像上的一个目录下,并设置工作目录。如果目录不存在,则创建一个。
RUN pip install flask
使用RUN指令,我们安装Flask。
RUN export FLASK_APP=app.py
我们将FLASK_APP环境变量设置为app.py应用程序文件。
EXPOSE 5000
我们公开端口。
CMD ["/usr/local/bin/flask", "run", "--host", "0.0.0.0"]
使用CMD指令,我们设置容器启动时运行的默认命令。我们将主机IP设置为0.0.0.0,以便可以在容器外访问该应用程序。
$ sudo docker build -t flasksimple .
我们构建图像。
$ docker run -p 5000:5000 flasksimple
我们运行图像。容器的5000端口映射到我们电脑的5000端口。
$ curl localhost:5000/ Hello there!
使用curl工具,我们向应用程序生成GET请求。
PythonDockerMariaDB
在下面的例子中,我们创建了一个基于mariadb镜像的容器。
USE testdb;
DROP TABLE IF EXISTS cities;
CREATE TABLE cities(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), population INT);
INSERT INTO cities(name, population) VALUES('Bratislava', 432000);
INSERT INTO cities(name, population) VALUES('Budapest', 1759000);
INSERT INTO cities(name, population) VALUES('Prague', 1280000);
INSERT INTO cities(name, population) VALUES('Warsaw', 1748000);
INSERT INTO cities(name, population) VALUES('Los Angeles', 3971000);
INSERT INTO cities(name, population) VALUES('New York', 8550000);
INSERT INTO cities(name, population) VALUES('Edinburgh', 464000);
INSERT INTO cities(name, population) VALUES('Berlin', 3671000);
这是cities表的SQL代码。
FROM mariadb
RUN apt-get update && apt-get install -y \
python3.8 \
python3-pip
RUN pip3 install pymysql
ADD schema.sql /docker-entrypoint-initdb.d
ENV MYSQL_USER=user7
ENV MYSQL_PASSWORD=7user
ENV MYSQL_DATABASE=testdb
ENV MYSQL_ROOT_PASSWORD=s$cret
EXPOSE 3306
我们从mariadb图像中导出我们的图像。
RUN apt-get update && apt-get install -y \
python3.8 \
python3-pip
在图像上,我们安装了Python和pip。
RUN pip3 install pymysql
我们安装pymysql驱动程序。
ADD schema.sql /docker-entrypoint-initdb.d
/docker-entrypoint-initdb.d目录下的SQL脚本在容器初始化时运行。我们使用ADD指令复制架构文件。
ENV MYSQL_USER=user7 ENV MYSQL_PASSWORD=7user ENV MYSQL_DATABASE=testdb ENV MYSQL_ROOT_PASSWORD=s$cret
使用环境变量,我们创建一个新用户,一个新数据库,并为root用户设置密码。
EXPOSE 3306
EXPOSE指令通知Docker容器在运行时监听指定的网络端口。
#!/usr/bin/python
import pymysql
con = pymysql.connect(host='localhost', user='user7',
password='7user', database='testdb', port=3306)
try:
with con.cursor() as cur:
cur.execute('SELECT * FROM cities')
rows = cur.fetchall()
for row in rows:
print(f'{row[0]}, {row[1]}, {row[2]}')
finally:
con.close()
该示例连接到容器内运行的MariaDBtestdb数据库。它显示了cities表中的所有行。
$ sudo docker build -t pymaria-simple .
Sending build context to Docker daemon 4.608kB
Step 1/9 : FROM mariadb
---> b95867b52886
Step 2/9 : RUN apt-get update && apt-get install -y python3.8 python3-pip
---> Using cache
---> 9370769248ed
Step 3/9 : RUN pip3 install pymysql
---> Using cache
---> 108146aaa2d8
...
我们构建图像。
$ sudo docker run -p 3306:3306 pymaria-simple
我们从自定义pymaria-simple图像运行容器。使用-p选项,我们将容器的3306端口发布到主机端口3306。
$ ./app.py 1, Bratislava, 432000 2, Budapest, 1759000 3, Prague, 1280000 4, Warsaw, 1748000 5, Los Angeles, 3971000 6, New York, 8550000 7, Edinburgh, 464000 8, Berlin, 3671000
容器启动后,我们运行显示城市的app.py程序。
在本教程中,我们使用了Python和Docker。
列出所有Python教程。
