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教程。