返回介绍

构建容器镜像

发布于 2025-01-02 21:54:00 字数 4960 浏览 0 评论 0 收藏 0

为 Microblog 创建容器的第一步是为它构建一个 镜像 。 容器镜像是用于创建容器的模板。 它包含容器文件系统的完整表示,以及与网络,启动选项等相关的各种设置。

为应用程序创建容器镜像的最基本方法是启动一个要使用的基本操作系统(Ubuntu,Fedora 等)容器,连接到运行在其中的 bash shell 进程,然后手动安装应用程序,可以参照我在 第十七章 中介绍的流程进行传统部署。 安装完所有内容后,你可以保存容器的快照,并生成容器镜像。 docker 命令支持这种类型的工作流,但我不打算讨论这种方法,因为它非常不便,每次需要生成新镜像时都必须手动安装应用程序。

更好的方法是通过脚本生成容器镜像。 创建脚本化容器镜像的命令是 docker build 。 该命令从一个名为 Dockerfile 的文件读取并执行构建指令(我需要创建这些指令)。 Dockerfile 基本上可以认为是一个安装程序脚本,它执行安装步骤来部署应用程序,以及一些容器特定的设置。

这是 Microblog 的一份基础的 Dockerfile :

Dockerfile : Microblog 的 Dockerfile。

FROM python:3.6-alpine

RUN adduser -D microblog

WORKDIR /home/microblog

COPY requirements.txt requirements.txt
RUN python -m venv venv
RUN venv/bin/pip install -r requirements.txt
RUN venv/bin/pip install gunicorn

COPY app app
COPY migrations migrations
COPY microblog.py config.py boot.sh ./
RUN chmod +x boot.sh

ENV FLASK_APP microblog.py

RUN chown -R microblog:microblog ./
USER microblog

EXPOSE 5000
ENTRYPOINT ["./boot.sh"]

Dockerfile 中的每一行都是一条命令。 FROM 命令指定将在其上构建新镜像的基础容器镜像。 这样一来,你从一个现有的镜像开始,添加或改变一些东西,并最终得到一个派生的镜像。 镜像由名称和标签来标记,它们之间用冒号分隔。 该标签用作版本控制机制,允许容器镜像提供多个版本。 我选择的镜像的名称是 python ,它是 Python 的官方 Docker 镜像。 该镜像的标签允许你指定解释器版本和基础操作系统。 3.6-alpine 标签选择安装在 Alpine Linux 上的 Python 3.6 解释器。 由于其体积小,Alpine Linux 发行版比起更常见的发行版(例如 Ubuntu)会更多地被使用。 你可以在 Python 镜像库 中查看 Python 镜像可用的标签。

RUN 命令在容器的上下文中执行任意命令。 这与你在 shell 提示符下输入命令相似。 adduser -D microblog 命令创建一个名为 microblog 的新用户。 大多数容器镜像都使用 root 作为默认用户,但以 root 身份运行应用程序并不是一个好习惯,所以我创建了自己的用户。

WORKDIR 命令设置将要安装应用程序的默认目录。 当我在上面创建 microblog 用户时,会自动创建了一个主目录,所以现在我将该目录设置为默认目录。 在 Dockerfile 中的任何剩余命令执行以及运行容器时,其当前目录为这个默认目录。

COPY 命令将文件从你的机器复制到容器文件系统。 该命令需要两个或更多参数,源文件/目录和目标文件/目录。 源文件必须与 Dockerfile 所在的目录相关。 目的地可以是绝对路径,也可以是相对于在之前的 WORKDIR 命令中设置的目录的路径。 在这第一个 COPY 命令中,我将 requirements.txt 文件复制到容器文件系统的 microblog 用户的主目录中。

容器中有了 requirements.txt 文件,我就可以使用 RUN 命令创建一个虚拟环境。 首先我创建它,然后在其中安装所有依赖。 由于依赖文件仅包含通用依赖项,因此我明确安装 gunicorn ,以将其用作 Web 服务器。 当然,我也可以在我的 requirements.txt 文件中添加 gunicorn。

接下来的三个 COPY 命令从顶级目录中复制 app 包,含有数据库迁移的 migrations 目录以及中的 microblog.py 和 config.py 脚本。 我还复制了一个新文件, boot.sh ,我将在下面讨论它。

RUN chmod 命令确保将这个新的 boot.sh 文件正确设置为可执行文件。 如果你使用的是基于 Unix 的文件系统,并且你的源文件已被标记为可执行文件,则复制的文件将会已是可执行的。 我显式地对其进行授权,是因为在 Windows 上很难设置可执行位。 如果你正在使用 Mac OS X 或 Linux,你可能不需要这个步骤,但有了它也不会有什么问题。

ENV 命令在容器中设置环境变量。我需要设置 FLASK_APP ,它是 flask 命令所依赖的。

下面的 RUN chown 命令将存储在 /home/microblog 中的所有目录和文件的所有者设置为新的 microblog 用户。 尽管我在 Dockerfile 的顶部附近创建了该用户,但所有命令的默认用户仍为 root ,因此所有这些文件的属主都需要切换到 microblog 用户,以便在容器启动时该用户可以正确运行这些文件。

下一行中的 USER 命令使得这个新的 microblog 用户成为任何后续指令的默认用户,并且也是容器启动时的默认用户。

EXPOSE 命令配置该容器将用于服务的端口。 这是必要的,以便 Docker 可以适当地在容器中配置网络。 我选择了标准的 Flask 端口 5000,但这其实可以是任意端口。

最后, ENTRYPOINT 命令定义了容器启动时应该执行的默认命令。 这是启动应用程序 Web 服务器的命令。 为了保持良好的代码组织逻辑,我决定为此创建一个单独的脚本,正是我之前复制到容器的 boot.sh 文件。 这里是这个脚本的内容:

boot.sh :Docker 容器启动脚本。

#!/bin/sh
source venv/bin/activate
flask db upgrade
flask translate compile
exec gunicorn -b :5000 --access-logfile - --error-logfile - microblog:app

这是一个相当标准的启动脚本,与 第十七章第十八章 的部署启动十分类似。 激活虚拟环境,执行迁移框架升级数据库,编译语言翻译,最后用 gunicorn 运行服务器。

请注意 gunicorn 命令之前的 exec 。 在 shell 脚本中, exec 触发正在运行脚本的进程被给定的命令来替换掉,而不是将这个命令作为新进程启动。 这很重要,因为 Docker 会将容器的生命与其上运行的第一个进程关联起来。 在像这样的情况下,启动进程不是容器的主进程,你需要确保主进程取代启动进程,以确保容器不会提前停止。

Docker 的一个有趣的方面是容器写入 stdoutstderr 的任何内容都将被捕获并存储为容器的日志。 出于这个原因, -access-logfile--error-logfile 都配置为 - ,它将日志发送到标准输出,以便它们作为日志由 Docker 存储。

Dockerfile 写好后,我现在可以构建容器镜像了:

$ docker build -t microblog:latest .

我给 docker build 命令的 -t 参数设置了新容器镜像的名称和标签。 . 表示容器构建的基础目录,这就是 Dockerfile 所在的目录。 构建过程将执行 Dockerfile 中的所有命令并创建镜像,该镜像将存储在你自己的机器上。

你可以使用 docker images 命令获取本地镜像的列表:

$ docker images
REPOSITORY    TAG          IMAGE ID        CREATED              SIZE
microblog     latest       54a47d0c27cf    About a minute ago   216MB
python        3.6-alpine   a6beab4fa70b    3 months ago         88.7MB

此列表将包含你的新镜像以及它的基础镜像。 每当你对应用程序进行更改后,都可以通过再次运行 build 命令来更新容器镜像。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文