使用Dockerfile构建一个Docker镜像
本实验验证使用 Dockerfile 文件来构建一个 Docker 镜像,并且使用该镜像构建一个docker容器实例来运行一个Python Flask demo。
前提条件
在开始实验之前,需要确保Linux上已经安装了 Docker。可以通过以下命令来检查 Docker 是否已经正确安装:
# docker 版本
root@server01:~# docker --version
Docker version 20.10.14# 另外 Linux 发行版信息
root@server01:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.6 LTS
Release: 20.04
Codename: focal
若输出了 Docker 的版本信息,就表明 Docker 已经安装成功。
构建镜像的步骤
1. 准备 Dockerfile 和项目文件
假设你已经编写好了一个简单的 Python Flask 应用,并且创建了对应的 Dockerfile。下面是项目文件的结构和具体内容示例:
项目文件结构
my_flask_app/
├── app.py
├── requirements.txt
└── Dockerfile
app.py
from flask import Flaskapp = Flask(__name__)@app.route('/')
def hello_flask():return 'Hello, Flask!'if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)
requirements.txt
flask==2.2.2
werkzeug==2.2.3
Dockerfile
# 使用 Python 3.9 作为基础镜像
FROM python:3.9-slim# 将当前目录下的所有文件复制到镜像中的 /app 目录
COPY . /app# 设置工作目录为 /app
WORKDIR /app# 安装 requirements.txt 中列出的依赖包
RUN pip install --no-cache-dir -r requirements.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple# 暴露容器的端口(假设应用监听 5000 端口)
EXPOSE 5000# 定义容器启动时要执行的命令
CMD ["python", "app.py"]
Dockerfile 中的 RUN
指令,用于在 Docker 镜像构建过程中执行命令。
整体功能说明
在 Docker 镜像构建时,使用 pip
工具安装 Python 项目所需的依赖包。具体来说,它从指定的清华镜像源下载并安装 requirements.txt
文件中列出的所有 Python 包,并且不缓存下载的包以减小镜像大小。
RUN
RUN
是 Dockerfile 中的一个指令,用于在新的镜像层中执行命令,并提交结果。每一个RUN
指令都会在镜像中创建一个新的层,因此可以利用它来逐步构建镜像。在这个例子中,RUN
后面跟着的是要执行的pip
命令。
pip install
pip
是 Python 的包管理工具,用于安装、升级和卸载 Python 包。install
是pip
的一个子命令,用于安装指定的 Python 包。
--no-cache-dir
- 这是
pip
命令的一个选项。默认情况下,pip
在安装包时会缓存下载的包文件,以便后续使用。使用--no-cache-dir
选项可以禁止pip
缓存下载的包文件,这样可以减少 Docker 镜像的大小。因为在 Docker 镜像中,缓存文件通常是不必要的,而且会增加镜像的体积。
-r requirements.txt
-r
是pip
命令的一个选项,用于指定一个包含包依赖信息的文件。requirements.txt
是一个常见的文本文件,通常用于列出 Python 项目所需的所有依赖包及其版本信息。例如,requirements.txt
文件可能包含如下内容:
flask==2.2.2
werkzeug==2.2.3
使用 -r requirements.txt
选项,pip
会读取 requirements.txt
文件,并安装其中列出的所有包。
-i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
-i
是pip
命令的一个选项,用于指定包的下载源。默认情况下,pip
会从 Python Package Index (PyPI) 下载包。但在某些情况下,由于网络原因,从默认源下载包可能会很慢。因此,可以使用-i
选项指定一个国内的镜像源来加速下载。https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
是清华大学提供的 PyPI 镜像源地址,使用这个镜像源可以显著提高包的下载速度。
2. 打开终端并进入项目目录
在终端中使用 cd
命令进入到包含 Dockerfile 的项目目录:
cd my_flask_app
3. 构建 Docker 镜像
使用 docker build
命令来构建镜像。该命令的基本语法如下:
docker build -t <镜像名称>:<标签> <构建上下文路径>
-t
:用于为构建的镜像指定名称和标签。标签是可选的,若不指定,默认标签为latest
。<镜像名称>
:你为镜像指定的名称,例如my_flask_app
。<标签>
:用于区分同一镜像的不同版本,例如1.0
。<构建上下文路径>
:指定 Docker 构建过程中使用的上下文路径,通常为当前目录,用.
表示。
对于上述示例,可使用以下命令来构建镜像:
docker build -t my_flask_app:1.0 .Sending build context to Docker daemon 4.096kB
Step 1/6 : FROM python:3.9-slim---> 1a47c1aaa88f
Step 2/6 : COPY . /app---> 01b3d06771d1
Step 3/6 : WORKDIR /app---> Running in 943e3b534644
Removing intermediate container 943e3b534644---> bf7722112588
Step 4/6 : RUN pip install --no-cache-dir -r requirements.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple---> Running in 89d60c12d112
Looking in indexes: https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
Collecting flask==2.2.2Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/43/15f4f9ab225b0b25352412e8daa3d0e3d135fcf5e127070c74c3632c8b4c/Flask-2.2.2-py3-none-any━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 101.5/101.5 kB 646.7 kB/s eta 0:00:00
Collecting werkzeug==2.2.3Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f6/f8/9da63c1617ae2a1dec2fbf6412f3a0cfe9d4ce029eccbda6e1e4258ca45f/Werkzeug-2.2.3-py3-none-━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 233.6/233.6 kB 736.4 kB/s eta 0:00:00
Collecting Jinja2>=3.0Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-an━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 134.9/134.9 kB 1.1 MB/s eta 0:00:00
Collecting itsdangerous>=2.0Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-n
Collecting click>=8.0Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 98.2/98.2 kB 245.1 kB/s eta 0:00:00
Collecting importlib-metadata>=3.6.0Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/79/9d/0fb148dc4d6fa4a7dd1d8378168d9b4cd8d4560a6fbf6f0121c5fc34eb68/importlib_metadata-8.6.1
Collecting MarkupSafe>=2.1.1Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/53/8f/f339c98a178f3c1e545622206b40986a4c3307fe39f70ccd3d9df9a9e425/MarkupSafe-3.0.2-cp39-cp
Collecting zipp>=3.20Downloading https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b7/1a/7e4798e9339adc931158c9d69ecc34f5e6791489d469f5e50ec15e35f458/zipp-3.21.0-py3-none-any
Installing collected packages: zipp, MarkupSafe, itsdangerous, click, werkzeug, Jinja2, importlib-metadata, flask
Successfully installed Jinja2-3.1.6 MarkupSafe-3.0.2 click-8.1.8 flask-2.2.2 importlib-metadata-8.6.1 itsdangerous-2.2.0 werkzeug-2.2.3 zipp-3.21.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a v[notice] A new release of pip is available: 23.0.1 -> 25.0.1
[notice] To update, run: pip install --upgrade pip
Removing intermediate container 89d60c12d112---> b1b335124c74
Step 5/6 : EXPOSE 5000---> Running in 3eb4ab776822
Removing intermediate container 3eb4ab776822---> 9c6f2706e83e
Step 6/6 : CMD ["python", "app.py"]---> Running in 28db9b48bcec
Removing intermediate container 28db9b48bcec---> b04f12e9fe5a
Successfully built b04f12e9fe5a
Successfully tagged my_flask_app:1.0
执行该命令后,Docker 会读取 Dockerfile 中的指令,逐步构建镜像。构建过程中,你会看到一系列的输出信息,显示每个步骤的执行情况。
4. 验证镜像是否构建成功
构建完成后,可以使用 docker images
命令来查看本地已有的镜像列表,确认 my_flask_app:1.0
镜像是否已经成功构建:
docker images | grep my_flask_app
my_flask_app 1.0 55d1bd61ae79 1 minutes ago 136MB
若输出中包含 my_flask_app:1.0
,则说明镜像构建成功。
5. 运行容器进行测试
使用 docker run
命令来基于构建好的镜像启动一个容器:
docker run -p 5000:5000 my_flask_app:1.0* Serving Flask app 'app'* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.* Running on all addresses (0.0.0.0)* Running on http://127.0.0.1:5000* Running on http://172.17.0.5:5000
-p
:用于将容器内部的端口映射到宿主机的端口。这里将容器的 5000 端口映射到宿主机的 5000 端口。my_flask_app:1.0
:指定要使用的镜像名称和标签。
启动容器后,你可以在浏览器中访问 http://localhost:5000
,若看到 Hello, Flask!
页面,或使用如下方式测试:
curl http://127.0.0.1:5000Hello, Flask!
则说明应用在容器中正常运行。
通过以上步骤,你就可以使用 Dockerfile 成功构建并运行一个 Docker 镜像。
附:
如果一个docker镜像已经关联构建了对应的docker容器,则直接删除该镜像会失败。
可能会报如下错误:
Error response from daemon: conflict: unable to remove repository reference "my_flask_app:1.0" (must force) - container faf944303195 is using its referenced image 34d1bd56ae78
这个错误提示表明你尝试删除的镜像 my_flask_app:1.0 正在被一个容器所使用,所以 Docker 不允许你直接删除该镜像。具体错误信息 container faf944303195 is using its referenced image 34d1bd56ae78 指出容器 ID 为 faf944303195 正在使用镜像 ID 为 34d1bd56ae78 的镜像,也就是 my_flask_app:1.0。
下面为几种解决这个问题的方法:
方法一:停止并删除使用该镜像的容器,然后再删除镜像
docker stop faf944303195 && docker rm faf944303195 && docker rmi my_flask_app:1.0
方法二:强制删除镜像(不推荐,有风险)
如果你确定不再需要使用该镜像以及相关的容器,可以使用 --force 或 -f 选项强制删除镜像。不过这种方法可能会导致一些不可预期的问题,比如残留的容器配置可能会影响后续操作。
docker rmi -f my_flask_app:1.0