Bootstrap

模型部署工具01:Docker || 用Docker打包模型 Build Once Run Anywhere

Docker 是一个开源的容器化平台,可以让开发者和运维人员轻松构建、发布和运行应用程序。Docker 的核心概念是通过容器技术隔离应用及其依赖项,使得软件在不同的环境中运行时具有一致性。无论是开发环境、测试环境,还是生产环境,Docker 都能够提供高效、可靠的解决方案。

在本教程中,我们将详细介绍 Docker 的核心概念、安装方法,以及如何使用 Docker 进行容器化操作。

在这里插入图片描述


Docker 是什么?为什么值得学习?

Docker 是一种容器化技术,能够将应用程序及其依赖项打包到一个轻量级、独立的容器中运行。这使得应用能够无缝迁移到不同的环境中,而无需担心系统配置或依赖冲突。

官网与资源:

Docker 的亮点:

  • 轻量级:相比虚拟机,容器共享宿主操作系统,启动更快,占用更少资源。
  • 可移植性:一次构建,随处运行(Build Once, Run Anywhere)。
  • 高效开发:快速构建开发环境,方便团队协作。
  • 广泛生态:丰富的社区支持和镜像资源。
  • 自动化:支持 CI/CD 工作流,轻松集成自动化测试和部署。

应用场景(来自官方文档):

  1. 开发本地编写代码并共享:开发人员将代码容器化,确保在任何环境中一致运行,并分享给同事。
  2. 推送到测试环境进行测试:使用 Docker 将应用推送到测试环境进行自动化和手动测试。
  3. 修复 bug 并重新部署:开发人员修复 bug 后,重新构建镜像并推送到测试环境验证。
  4. 测试完成后推送到生产环境:测试通过后,将更新的镜像推送到生产环境,简单快速地部署。

Docker 的核心概念

1. Docker 守护进程(Docker Daemon)

  • 概念:Docker 守护进程是负责与容器进行交互的后台服务。它负责启动、停止、构建、拉取、推送容器镜像等操作,从某种程度上也可以理解为docker引擎。
  • 作用:它是整个 Docker 环境的核心,任何通过命令行执行的操作(如 docker rundocker ps)都由 Docker 守护进程处理。守护进程通常是通过 docker 命令启动的,并且运行在宿主机上。
  • 常见命令:
    • docker info:查看 Docker 守护进程的详细信息。
    • docker version:查看 Docker 的版本信息。

2.容器(Container)

  • 概念:容器是一种操作系统级的虚拟化技术,它并不创建完整的虚拟机,而是通过共享宿主机的操作系统内核来隔离每个容器的运行环境。你可以将它想象为一个轻量级的“沙盒”,每个沙盒内的应用和环境互不干扰,但是它们都使用宿主机的核心资源(CPU、内存、文件系统等)。
  • 工作方式:容器通过 namespacecgroups 技术实现隔离:
    • Namespace:提供了容器内进程的“隔离”,每个容器拥有独立的进程空间、网络空间、挂载点、用户空间等。
    • Cgroups:为每个容器分配并限制资源(如 CPU、内存、磁盘 I/O),确保容器不会消耗过多资源,影响宿主机或其他容器的运行。
  • 为什么重要:相比虚拟机(VM),容器不需要运行完整的操作系统,因此启动速度快,资源占用少,尤其适合微服务架构和需要弹性扩展的应用。

3. 镜像(Image)

  • 本质:镜像是容器的“模板”,是一个静态的文件系统,包括应用所需的所有文件、配置、依赖、库、环境变量等。镜像本身并不包含应用运行时的状态,它只是容器启动时的基准。每次你用镜像启动一个容器,它都会根据镜像创建一个新的实例,并且容器的所有更改(如文件修改)默认是在容器内进行的,直到你停止并删除该容器。

  • 工作方式:镜像是由多个层组成的,通常每一层代表 Dockerfile 中的一个指令。例如:

    • FROM ubuntu: 基于 Ubuntu 镜像。
    • RUN apt-get install ...: 安装依赖。
    • COPY . /app: 将应用代码复制到容器中。

    每一层都会被缓存,这样如果你修改 Dockerfile 中的某一层,Docker 只需要重新构建被修改的层,而不需要重新构建整个镜像,节省了大量的时间和计算资源。

  • 为什么重要:镜像是容器化的核心,它确保了你可以在任何地方(开发、测试、生产等)运行同样的应用环境,避免了“在我的机器上能运行”的问题。

4. Dockerfile

  • 本质:Dockerfile 是定义镜像构建过程的脚本。它的每一条指令(如 RUN, COPY, ADD)告诉 Docker 如何一步步地构建镜像,如何设置基础环境、安装依赖、配置应用等。
  • 工作方式:Dockerfile 是由一系列命令(如 FROM, RUN, COPY 等)组成的,每个命令会在一个新的镜像层上执行。每个层都有自己的缓存,这就是 Docker 构建加速的秘密所在。比如,如果你修改了 Dockerfile 的 RUN 指令,Docker 只会重建该层及其之后的所有层,而不会重新构建之前的层。
  • 为什么重要:Dockerfile 实现了镜像的自动化构建,保证了镜像的一致性和可重复性。通过 Dockerfile,团队可以轻松分享和复现环境配置,从而大大减少了环境配置不一致的风险。

5. Docker Hub 和 镜像仓库

  • 本质:Docker Hub 是一个官方的公共镜像仓库,提供了大量的预构建镜像供开发者使用,如官方的 Python 镜像、Nginx 镜像等。你也可以将自己的镜像推送到 Docker Hub,或使用私有仓库(如使用 GitLab 自带的镜像仓库)进行管理。
  • 工作方式:你可以从 Docker Hub 下载预构建镜像(例如 docker pull ubuntu)或将本地构建的镜像推送到 Docker Hub(例如 docker push my-image)。Docker Hub 支持版本控制,可以管理镜像的不同版本。
  • 为什么重要:Docker Hub 是镜像的共享中心,它提供了一个非常便利的途径来获取和分发镜像。对于团队合作,能够快速共享应用镜像,是 Docker 的一大优势。

6. 卷(Volumes)和持久化存储

  • 本质:容器是临时性的,每次删除容器后,容器内的数据会丢失。因此,容器本身并不适合存储持久化数据。为了持久化存储,Docker 提供了卷(Volumes)。卷是 Docker 管理的存储空间,可以将数据存储在宿主机或网络存储中,容器可以通过挂载卷来访问持久化数据。
  • 工作方式:通过 docker volume 命令,你可以创建一个卷,并将它挂载到容器上。容器对卷的读写会被保存在宿主机的文件系统中,容器删除后,卷中的数据依然存在。
  • 为什么重要:持久化存储是许多应用的关键要求(例如数据库、日志文件等)。卷保证了即使容器被删除,数据依然可以被保存,并且在多个容器之间共享。

7. Docker Compose

  • 本质:Docker Compose 是一个用于定义和管理多容器应用的工具。通过一个 docker-compose.yml 文件,你可以在一个地方定义多个服务、它们之间的依赖关系、网络配置等,然后用 docker-compose up 一键启动整个应用。
  • 工作方式:Compose 文件使用 YAML 格式定义服务、网络、卷等配置。例如,你可以在一个 Compose 文件中定义 Web 服务和数据库服务,并指定它们如何互相通信。
  • 为什么重要:在微服务架构中,通常一个应用会由多个容器组成(如 Web 服务器、数据库、缓存等),手动启动和管理这些容器会非常繁琐。Docker Compose 提供了一种简便的方式来管理这些多容器应用。

8. 网络(Networking)

  • 本质:容器虽然在不同的沙盒中运行,但它们通常需要进行相互通信。Docker 提供了多种网络模式来满足不同场景的需求。容器间的网络连接和外部世界的通信可以通过 Docker 的网络配置来实现。网络在容器的互联互通中扮演着关键角色,确保容器能够在隔离的环境中安全有效地进行通信。
  • 工作方式:Docker 支持几种网络模式:
    • bridge(桥接网络):默认模式,适用于容器与宿主机之外的容器通信。容器连接到一个虚拟的桥接网络,通过桥接网络与其他容器或外部通信。
    • host(宿主机网络):容器直接使用宿主机的网络接口,适用于对网络性能有较高要求的场景。
    • overlay(叠加网络):用于跨多个 Docker 主机的容器之间的通信,适合容器集群部署,如使用 Docker Swarm 或 Kubernetes 时的容器通信。
    • none(无网络):容器没有网络访问能力,适合特定安全需求的应用。
  • 为什么重要:容器的网络配置决定了它们如何互相交互以及与外部系统的连接方式。正确的网络配置确保了应用的高效、可扩展和安全。尤其在分布式架构中,网络管理至关重要。

如何安装 Docker?

Docker 支持 Windows、macOS 和 Linux 操作系统。以下是安装步骤:

1. 在 Linux 上安装 Docker

  1. 更新系统包索引:

    sudo apt update
    
  2. 安装必要的依赖:

    sudo apt install apt-transport-https ca-certificates curl software-properties-common
    
  3. 添加 Docker 官方 GPG 密钥和仓库:

    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
    
  4. 安装 Docker:

    sudo apt update
    sudo apt install docker-ce
    
  5. 验证安装:

    docker --version
    

2. 在 Windows 或 macOS 上安装 Docker

  1. 下载 Docker Desktop:

  2. 安装并启动 Docker Desktop:

    • 按照安装向导完成安装。
    • 启动 Docker Desktop 后,确保 Docker 处于运行状态。
  3. 验证安装: 打开终端,运行以下命令:

    docker --version
    

Docker 的基础使用

以下是使用 Docker 的常见操作:

1. 拉取镜像

从 Docker Hub 下载镜像:

docker pull ubuntu

2. 运行容器

从镜像启动容器:

docker run -it ubuntu
  • -it:交互模式。
  • ubuntu:镜像名称。

3. 查看运行中的容器

列出当前正在运行的容器:

docker ps

4. 停止容器

停止一个运行中的容器:

docker stop <container_id>

5. 删除容器

删除已停止的容器:

docker rm <container_id>

6. 查看镜像列表

列出所有本地镜像:

docker images

7. 删除镜像

删除一个镜像:

docker rmi <image_id>

**Dockerfile **

常见指令,参考官方文档:

  1. FROM - 指定构建镜像时所用的基础镜像。构建过程会基于该镜像进行扩展。
  2. WORKDIR - 设置容器内的工作目录,后续的文件操作和命令执行都将在该目录中进行。
  3. COPY - 将宿主机的文件或目录复制到镜像的指定路径。
  4. RUN - 在构建镜像时执行指定的命令,如安装依赖包或执行脚本。
  5. ENV - 设置环境变量,这些变量将在容器内运行时可用。
  6. EXPOSE - 向外界声明容器内部监听的端口,用于网络通信。
  7. USER - 设置容器内后续指令执行的默认用户,通常用于提升安全性,避免使用 root 用户。
  8. CMD [“”, “”] - 定义容器启动时默认执行的命令。这个命令在容器启动时自动运行。

举一个例子:

# 使用 Python 3.9 作为基础镜像
FROM python:3.9-slim

# 设置工作目录为 /app
WORKDIR /app

# 复制宿主机的 src 文件夹到镜像中的 /app/src
COPY ./src /app/src

# 安装 curl 和其他依赖
RUN apt-get update && apt-get install -y curl

# 设置环境变量,指定应用的运行环境
ENV APP_ENV=production

# 声明容器会监听 8080 端口
EXPOSE 8080

# 设置容器内默认用户为 appuser
USER appuser

# 设置容器启动时执行的默认命令
CMD ["python", "app.py"]
  1. FROM python:3.9-slim: 从 python:3.9-slim 镜像开始构建。
  2. WORKDIR /app: 将 /app 设置为工作目录,后续的操作都在此目录内进行。
  3. COPY ./src /app/src: 将本地的 src 目录复制到容器的 /app/src 目录。
  4. RUN apt-get update && apt-get install -y curl: 在镜像构建时更新包管理器并安装 curl
  5. ENV APP_ENV=production: 设置环境变量 APP_ENVproduction
  6. EXPOSE 8080: 声明容器会监听 8080 端口。
  7. USER appuser: 设置容器运行时的默认用户为 appuser
  8. CMD [“python”, “app.py”]: 设置容器启动时默认执行 python app.py

Docker Compose

  1. version - 定义 Docker Compose 文件的版本,确保 Compose 文件的语法和功能与 Docker 版本兼容。
  2. services - 定义一个或多个服务,每个服务都会在单独的容器中运行,服务可以通过构建或拉取镜像来运行。
  3. image - 指定服务使用的 Docker 镜像。如果镜像不存在,Docker Compose 会自动从 Docker Hub 拉取。
  4. build - 用于从 Dockerfile 构建镜像,而不是直接使用现有镜像。context 是构建的上下文目录,可以指定构建上下文和 Dockerfile 文件。
  5. container_name - 为容器指定一个自定义名称,而不是默认生成的随机名称。这样便于容器的管理和访问。
  6. ports - 配置容器与主机之间的端口映射。通过 "host-port:container-port" 形式,将容器端口映射到主机端口。
  7. volumes - 挂载主机目录或容器卷到容器内,用于持久化数据或共享文件。
  8. environment - 设置环境变量,这些变量将在容器运行时可用,通常用于配置容器内的应用程序。
  9. networks - 配置服务连接的网络,可以定义自定义网络,并将服务连接到这些网络。
  10. depends_on - 指定服务的依赖关系,确保依赖服务在当前服务之前启动。
  11. restart - 配置容器退出后的重启策略。常见策略有 no(不重启)、always(总是重启)和 on-failure(仅在失败时重启)。
  12. command - 设置容器启动时执行的命令,覆盖默认的容器命令。
  13. scale - 设置服务的实例数量,允许在 Compose 中管理多个相同服务的实例。
version: '3.8'  # 使用的 Docker Compose 版本

services:  # 定义服务列表
  web:  # 服务名为 web
    image: python:3.9-slim  # 使用的基础镜像是 python:3.9-slim
    container_name: my-web-app  # 容器名为 my-web-app
    ports:  # 配置端口映射
      - "5000:5000"  # 将容器的 5000 端口映射到主机的 5000 端口
    volumes:  # 挂载主机目录到容器内
      - ./app:/app  # 将当前目录下的 app 文件夹挂载到容器的 /app 目录
    environment:  # 设置环境变量
      - APP_ENV=production  # 设置 APP_ENV 环境变量为 production
    command: python app.py  # 设置容器启动时默认执行的命令
    restart: always  # 容器退出后自动重启

具体解释:

  1. version: ‘3.8’ - 使用 Docker Compose 的版本 3.8,这是定义配置格式版本的指令。
  2. services - 定义了一个或多个服务,每个服务都可以在 Docker Compose 文件中进行配置和管理。
  3. web - 服务的名称,通常是应用程序或容器的名字。
  4. image: python:3.9-slim - 使用的基础镜像是 python:3.9-slim,即 Python 3.9 的精简版本。
  5. container_name: my-web-app - 定义了容器的名称,在启动后可以用这个名称来引用该容器。
  6. ports: “5000:5000” - 将容器的 5000 端口映射到主机的 5000 端口,这样你可以通过访问主机的 5000 端口来与容器内的应用进行交互。
  7. volumes: ./app:/app - 将宿主机当前目录下的 app 文件夹挂载到容器的 /app 目录,这样容器内的应用就可以访问主机上的代码和数据。
  8. environment: APP_ENV=production - 设置环境变量 APP_ENVproduction,在容器运行时,应用可以使用这个变量来确定运行环境。
  9. command: python app.py - 容器启动时执行的命令,默认会执行 python app.py 启动应用。
  10. restart: always - 容器退出时会自动重启,确保服务持续运行。

Docker 的高级功能

目前自己的理解还不够,等以后有机会再补充。

;