Docker技术系列文章,第二篇——深入理解 Docker 镜像
Docker技术系列文章,第二篇——深入理解 Docker 镜像
在 Docker 的生态系统中,镜像是构建和运行容器的基石。深入理解 Docker 镜像的工作原理、构建方式以及管理方法,对于高效使用 Docker 进行应用开发和部署至关重要。本文将带你深入探索 Docker 镜像的奥秘。
Docker 镜像分层机制
什么是镜像分层
Docker 镜像采用分层存储的架构。简单来说,一个镜像由多个只读层叠加而成。当我们创建一个容器时,Docker 会在镜像的最上层添加一个可写层,所有对容器的修改(如创建文件、修改文件等)都发生在这个可写层上。
分层机制的优势
- 共享资源:多个镜像可以共享相同的基础层。例如,多个基于 Ubuntu 的镜像可以共享 Ubuntu 基础镜像的层,这大大节省了磁盘空间。
- 提高构建效率:当我们构建一个新的镜像时,如果只对某一层进行了修改,Docker 只需要更新这一层,而不需要重新构建整个镜像。
实例说明
下面通过一个简单的例子来展示镜像分层。我们以一个基于 Ubuntu 的镜像为例,假设这个镜像有三层:
- 第一层:包含基本的操作系统文件,如内核文件、启动脚本等。
- 第二层:安装了一些常用的软件包,如vim、curl等。
- 第三层:配置了一些环境变量和应用程序的初始化脚本。
当我们基于这个镜像创建一个容器时,Docker 会在这三层之上添加一个可写层。如果我们在容器中创建一个新文件,这个文件就会被存储在可写层中。如果我们修改了第二层中的某个文件,Docker 会将修改后的文件复制到可写层中,而不会直接修改原来的只读层。
我们可以通过docker image history
命令查看镜像的分层历史。例如,对于ubuntu镜像:
docker image history ubuntu
输出结果类似如下:
这里每一行代表一个镜像层,CREATED BY字段显示了创建该层时执行的命令,SIZE字段显示了该层的大小。
构建自定义镜像
Dockerfile 介绍
Dockerfile 是一个文本文件,其中包含了一系列指令,用于自动化构建镜像。通过编写 Dockerfile,我们可以精确地定义镜像的内容和配置。
Dockerfile 基本语法
FROM:指定基础镜像。例如:
FROM ubuntu:latest
这行指令表示我们的自定义镜像将基于最新版本的 Ubuntu 镜像构建。
RUN:在镜像构建过程中执行命令。例如:
RUN apt-get update && apt-get install -y vim curl
这行指令会在基础镜像上更新软件包索引,并安装vim和curl软件包。注意,这里使用了
&&
符号,确保只有在apt-get update
成功执行后才会执行apt-get install
。WORKDIR:设置工作目录。例如:
WORKDIR /app
这行指令将在镜像中创建一个/app目录,并将其设置为工作目录。后续的指令(如COPY、RUN等)如果没有指定绝对路径,将在这个工作目录下执行。
COPY:将本地文件复制到镜像中。例如:
COPY . /app
这行指令会将当前目录下的所有文件(
.
表示当前目录)复制到镜像的/app目录中。CMD:指定容器启动时要执行的命令。例如:
CMD ["python", "app.py"]
这行指令表示当基于这个镜像创建的容器启动时,会执行
python app.py
命令。注意,CMD指令只能在 Dockerfile 中出现一次,如果出现多次,只有最后一次有效。
构建镜像示例
假设我们有一个简单的 Python Flask 应用,目录结构如下:
myapp/
├── app.py
├── requirements.txt
└── templates/
└── index.html
其中,app.py
是应用的主程序,requirements.txt
列出了应用所需的依赖包,templates
目录包含了 HTML 模板文件。
我们可以编写如下的 Dockerfile 来构建这个应用的镜像:
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
在上述 Dockerfile 中:
- 第一行指定了基础镜像是 Python 3.9 的精简版镜像。
- 接着设置了工作目录为
/app
。 - 然后将
requirements.txt
文件复制到工作目录,并使用pip
安装依赖包。 - 再将整个应用目录复制到工作目录。
- 之后通过
EXPOSE
指令声明容器将在 5000 端口上提供服务。 - 最后指定容器启动时执行
python app.py
命令来运行 Flask 应用。
编写好 Dockerfile 后,我们可以在包含 Dockerfile 的目录下执行以下命令来构建镜像:
docker build -t myapp:latest .
这里 -t
选项用于指定镜像的标签,格式为 [仓库名]:[标签名]
。myapp
是仓库名,latest
是标签名,.
表示当前目录,即 Dockerfile 所在的目录。
构建过程中,Docker 会按照 Dockerfile 中的指令依次执行,输出构建日志。当构建完成后,我们可以通过 docker images
命令查看新构建的镜像:
docker images
输出结果中应该会看到 myapp:latest
镜像。
镜像管理
镜像标签
镜像标签用于标识镜像的版本和用途。我们可以使用 docker tag
命令为镜像添加标签。例如,将 myapp:latest
镜像标记为 myapp:v1.0
:
docker tag myapp:latest myapp:v1.0
这样我们就可以通过不同的标签来管理同一个镜像的不同版本。
推送镜像至仓库
当我们构建好镜像后,可以将其推送到镜像仓库中,以便在其他环境中使用。Docker 官方提供了 Docker Hub 作为公共的镜像仓库,同时我们也可以搭建自己的私有镜像仓库。
要将镜像推送到 Docker Hub,首先需要登录到 Docker Hub:
docker login
输入你的 Docker Hub 账号和密码后,登录成功。然后使用 docker push
命令推送镜像。例如,推送 myapp:latest
镜像:
docker push myapp:latest
如果你的镜像仓库地址不是 Docker Hub,需要在镜像标签中指定完整的仓库地址。例如,将镜像推送到私有仓库 myregistry.com
:
docker tag myapp:latest myregistry.com/myapp:latest
docker push myregistry.com/myapp:latest
拉取镜像
从镜像仓库拉取镜像的命令是 docker pull
。例如,拉取 myapp:latest
镜像:
docker pull myapp:latest
如果镜像仓库需要认证,在拉取之前需要先登录。
以上就是本文的内容了,大体上对 Docker 镜像分层机制、自定义镜像构建以及镜像管理进行了初步的介绍。希望各位读者继续加油,学无止境!