Docker

2022年10月

Posted by franztao on October 26, 2022

intuition

实现可重现性的最后一步是将版本化代码和工件部署在可重现的环境中。这远远超出了为 Python 应用程序配置的虚拟环境,因为没有捕获系统级规范(操作系统、所需的隐式包等)。希望能够封装需要的所有需求,这样就没有外部依赖项会阻止其他人复制确定应用程序。

docker

实际上有相当多的系统级可重复性解决方案(VM、容器引擎等),但Docker容器引擎是迄今为止最受欢迎的几个关键优势:

  • 通过 Dockerfile 实现可重现性,并带有在特定系统中部署应用程序的明确说明。
  • 通过容器进行隔离,以免影响也可能在同一底层操作系统上运行的其他应用程序。
  • 以及更多优势,包括大小(每个应用程序不需要单独的操作系统)、速度、Docker Hub等。

将使用 Docker 以隔离、可重复和可扩展的方式在本地部署应用程序。一旦这样做了,任何安装了 Docker 引擎的机器都可以重现工作。但是,Docker 还有很多其他功能,您可以在dockerdocs中进行探索。

Architecture

在安装 Docker 之前,让看看容器引擎是如何在操作系统之上工作的,它可以是本地硬件或在云上管理的东西。

docker架构

Docker 容器引擎负责启动已配置的容器,其中_包含_应用程序及其依赖项(二进制文件、库等)。容器引擎非常高效,因为它不需要为每个容器化应用程序创建单独的操作系统。这也意味着容器可以通过 Docker 引擎共享系统的资源。

运行状态生命周期

设置

现在已准备好根据操作系统安装Docker安装后,可以启动 Docker 桌面,这将允许创建和部署容器化应用程序。

Docker 版本 20.10.8,构建 3967b7d

图片

第一步是构建一个包含应用程序及其所有指定依赖项的 docker 映像。可以使用概述一组指令的 Dockerfile 创建此映像。这些指令本质上是在彼此之上构建只读图像层来构建整个图像。让看看应用程序的Dockerfile和它创建的镜像层。

Dockerfile

将从创建一个 Dockerfile 开始:

将写入的第一行指定了要从FROMDockerfile中提取的基本映像。在这里,想使用基础镜像来运行基于 Python 的应用程序,特别是用于带有 slim 变体的 Python 3.7。由于只部署了一个 Python 应用程序,这个带有最少包的苗条变体满足了要求,同时保持了图像层的大小。

# Base image
FROM python:3.7-slim

接下来将安装应用程序依赖项。首先,将从本地文件系统中复制所需的文件,以便可以使用它们进行安装。或者,如果在一些远程基础设施上运行,可以从远程 git 主机中提取。获得文件后,可以使用RUN命令安装安装应用程序依赖项所需的包。一旦使用完这些包,可以删除它们以将图像层的大小保持在最小。

# Install dependencies
WORKDIR /mlops
COPY setup.py setup.py
COPY requirements.txt requirements.txt
RUN apt-get update \
    && apt-get install -y --no-install-recommends gcc build-essential \
    && rm -rf /var/lib/apt/lists/* \
    && python3 -m pip install --upgrade pip setuptools wheel \
    && python3 -m pip install -e . --no-cache-dir \
    && python3 -m pip install protobuf==3.20.1 --no-cache-dir \
    && apt-get purge -y --auto-remove gcc build-essential

接下来准备复制所需的文件以实际运行应用程序。

# Copy
COPY tagifai tagifai
COPY app app
COPY data data
COPY config config
COPY stores stores

# Pull assets from S3
RUN dvc init --no-scm
RUN dvc remote add -d storage stores/blob
RUN dvc pull

由于应用程序 (API) 需要打开 PORT 8000,因此需要在 Dockerfile 中指定以公开它。

# Export ports
EXPOSE 8000

构建镜像的最后一步是指定从镜像构建容器时要运行的可执行文件。对于应用程序,希望使用 gunicorn 启动 API,因为这个 Dockerfile 可用于将服务大规模部署到生产环境中。

# Start app
ENTRYPOINT ["gunicorn", "-c", "app/gunicorn.py", "-k", "uvicorn.workers.UvicornWorker", "app.api:app"]

在 Dockerfile 中有更多命令可供使用,例如使用环境变量 ( ENV ) 和参数 ( ARG )、命令参数 ( CMD )、指定卷 ( VOLUME )、设置工作目录 ( WORKDIR ) 等等,所有这些你都可以通过官方文档来探索。

构建镜像

编写完 Dockerfile 后,就可以使用build命令构建映像了,该命令允许添加标签并指定要使用的 Dockerfile 的位置。

docker build -t tagifai:latest -f Dockerfile .

可以像这样检查所有构建的图像及其属性:

docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
tagifai      latest    02c88c95dd4c   23 minutes ago   2.57GB

还可以根据其唯一 ID 删除任何或所有图像。

docker rmi <IMAGE_ID>              # remove an image
docker rmi $(docker images -a -q)  # remove all images

运行容器

一旦构建了镜像,就可以使用该镜像运行一个容器,运行命令允许指定镜像、端口转发等。

docker run -p 8000:8000 --name tagifai tagifai:latest

一旦容器运行起来,就可以使用 API,感谢共享的端口(8000):

curl -X 'POST' \
  'http://localhost:8000/predict' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "texts": [
    {
      "text": "Transfer learning with transformers for text classification."
    }
  ]
}'

可以像这样检查所有容器(运行或停止):

docker ps     # running containers
docker ps -a  # stopped containers
容器 ID 图像命令创建状态端口名称
ee5f1b08abd5 tagifai:latest "gunicorn -c config..." 19 分钟前 Created 0.0.0.0:8000->8000/tcp tagifai

还可以根据容器的唯一 ID 停止和删除任何或所有容器:

docker stop <CONTAINER_ID>      # stop a running container
docker rm <CONTAINER_ID>        # remove a container
docker stop $(docker ps -a -q)  # stop all containers
docker rm $(docker ps -a -q)    # remove all containers

如果应用程序需要多个容器用于不同的服务(API、数据库等),那么可以使用 docker compose功能一次将它们全部启动,并使用Kubernetes (K8s)等容器编排系统来扩展和管理它们。如果专门部署 ML 工作流,可以使用KubeFlow 之类的工具包来帮助管理和扩展。

调试

如果在构建镜像层时遇到错误,调试问题的一种非常简单的方法是使用迄今为止构建的镜像层运行容器。可以通过.Dockerfile重建镜像(因为改变了 Dockerfile)并运行容器:

docker build -t tagifai:latest -f Dockerfile .
docker run -p 8000:8000 -it tagifai /bin/bash

一旦容器运行起来,就可以像在本地机器上一样使用应用程序,但现在它可以在任何可以运行 Docker 容器引擎的操作系统上重现。已经介绍了从 Docker 部署应用程序所需的内容,但 Docker 还有更多内容,您可以在docs中进行探索。

生产

Dockerfile通常是数据科学家或 ML 工程师交付给他们的 DevOps 团队以部署和扩展他们的服务的最终工件,并进行了一些更改:

  • 数据assert将从远程存储位置(例如 S3)中提取。
  • 模型工件将从远程模型注册表加载。
  • 代码将从远程存储库(例如 GitHub)通过git clone.

所有这些更改都将涉及使用正确的凭据(通过encrypted secrets,甚至可以通过CI/CD 工作流自动部署。但是,当然,还有后续职责,例如监控

更多干货,第一时间更新在以下微信公众号:

您的一点点支持,是我后续更多的创造和贡献

转载到请包括本文地址 更详细的转载事宜请参考文章如何转载/引用

本文主体源自以下链接:

@article{madewithml,
    author       = {Goku Mohandas},
    title        = {   Made With ML },
    howpublished = {\url{https://madewithml.com/}},
    year         = {2022}
}