Docker Hub 官方指南:镜像查找、拉取与推送 – wiki基地


Docker Hub 官方指南:镜像查找、拉取与推送——打造高效容器化开发部署流程

引言:Docker Hub——全球容器镜像的中心

在当今云原生和容器化的浪潮中,Docker 已经成为构建、发布和运行应用程序的行业标准。而 Docker Hub,作为 Docker 官方提供的云服务,无疑是其生态系统中最为核心的组成部分。它不仅是全球最大的公共容器镜像仓库,更是开发者们分享、发现和管理容器镜像的首选平台。可以将其类比为 GitHub 之于代码,Docker Hub 之于 Docker 镜像。

Docker Hub 为用户提供了以下核心功能:
1. 公共镜像仓库(Public Repositories): 允许任何人查找、拉取和使用海量的官方及社区维护的镜像。
2. 私有镜像仓库(Private Repositories): 允许用户存储私有镜像,只有授权用户才能访问,确保了企业或个人项目的安全性。
3. 自动化构建(Automated Builds): 与 GitHub、Bitbucket 等代码仓库集成,实现代码提交后自动构建 Docker 镜像并推送到 Docker Hub。
4. Webhooks: 在镜像被推送或更新时触发自定义操作,便于集成 CI/CD 流程。
5. 组织与团队管理: 支持企业级用户管理,实现团队协作。

本文将深入探讨 Docker Hub 的三大核心操作:镜像查找、镜像拉取与镜像推送,并提供详细的命令行示例、最佳实践和注意事项,帮助读者充分利用 Docker Hub 的强大功能,优化其容器化开发部署工作流。

第一章:理解 Docker 镜像与 Registry 的基础

在深入 Docker Hub 的操作之前,我们有必要简要回顾一下 Docker 镜像和 Registry 的基本概念。

1.1 Docker 镜像:应用程序的最小可执行单元

Docker 镜像是一个轻量级、独立、可执行的软件包,包含运行应用程序所需的一切:代码、运行时、系统工具、系统库和设置。它是一个只读的模板,可以用来创建 Docker 容器。镜像采用分层存储机制,每一层都代表对上一层的修改,这使得镜像的构建、共享和存储效率极高。

1.2 Docker Registry:镜像的存储与分发中心

Docker Registry 是存储和分发 Docker 镜像的服务器端应用程序。它允许用户上传(push)和下载(pull)镜像。Docker Hub 就是 Docker 官方提供的默认公共 Registry。除了 Docker Hub,还有各种云服务商提供的 Registry(如 AWS ECR, Azure ACR, Google GCR)以及企业内部私有 Registry(如 Harbor)。

当我们在 Docker CLI 中执行 docker pull <image_name> 命令时,如果没有指定 Registry 地址,Docker 客户端会默认从 Docker Hub 下载镜像。同样,当我们执行 docker push <image_name> 时,也默认推送到 Docker Hub。

第二章:镜像查找——定位所需资源

在 Docker Hub 上,有数百万个镜像可供选择。高效地查找所需的镜像,是使用 Docker Hub 的第一步。主要有两种查找方式:通过 Docker CLI 和通过 Docker Hub 官方网站。

2.1 通过 Docker CLI 查找镜像

docker search 命令允许您直接在终端中搜索 Docker Hub 上的公共镜像。

命令语法:
bash
docker search [OPTIONS] TERM

* TERM: 您要搜索的关键词,可以是应用程序名称、操作系统等。
* OPTIONS:
* --filter, -f: 根据特定条件过滤结果。
* --filter "stars=<number>": 过滤出星级(收藏数)大于等于指定数字的镜像。
* --filter "is-official=true": 仅显示官方镜像。
* --filter "is-automated=true": 仅显示自动化构建的镜像。
* --filter "is-trusted=true": 仅显示可信赖的镜像(现已废弃,被 “Verified Publisher” 和 “Official Images” 取代)。
* --limit: 限制返回结果的数量(默认为 25)。
* --format: 格式化输出。

示例:

  1. 搜索 Nginx 相关镜像:
    bash
    docker search nginx

    输出示例:
    NAME DESCRIPTION STARS OFFICIAL AUTOMATED
    nginx Official build of Nginx. 18012 [OK]
    bitnami/nginx Bitnami NGINX Container Image 100 [OK]
    nginxinc/nginx-unprivileged Unprivileged NGINX Dockerfiles 51 [OK]
    jwilder/nginx-proxy Automated Nginx reverse proxy for docker co... 3042 [OK]
    richarvey/nginx-php-fpm Nginx with PHP-FPM 1075 [OK]
    ...

    • NAME: 镜像名称。格式通常为 [用户名/或组织名/]仓库名。官方镜像通常只有仓库名(如 nginx)。
    • DESCRIPTION: 镜像的简要描述。
    • STARS: 用户给该镜像的收藏数,通常星级越高代表越受欢迎或质量越好。
    • OFFICIAL: 如果显示 [OK],则表示是 Docker 官方镜像,具有高度的可靠性和安全性。
    • AUTOMATED: 如果显示 [OK],则表示该镜像是由 Docker Hub 自动化构建服务从 GitHub/Bitbucket 等代码仓库构建的,这通常意味着构建过程是透明可追溯的。
  2. 搜索星级大于 1000 的官方 Ubuntu 镜像:
    bash
    docker search --filter "stars=1000" --filter "is-official=true" ubuntu

    这会返回星级超过 1000 的所有官方 Ubuntu 镜像,尽管 Ubuntu 只有一个官方镜像,但这种过滤方式在更宽泛的搜索中很有用。

  3. 限制搜索结果:
    bash
    docker search --limit 5 redis

    这会返回关于 Redis 的前 5 个搜索结果。

docker search 的优缺点:
* 优点: 快速,直接在命令行中操作,适合已知大致名称的快速查找。
* 缺点: 信息量有限,无法查看完整的描述、README、标签(tag)列表等详细信息,也不支持更复杂的过滤和排序。

2.2 通过 Docker Hub 官方网站查找镜像

Docker Hub 网站(hub.docker.com)提供了更强大、更直观的镜像查找体验。

  1. 访问 Docker Hub 网站: 打开浏览器,导航到 hub.docker.com
  2. 使用搜索栏: 在页面顶部的搜索栏中输入您要查找的关键词(例如 python)。
  3. 浏览搜索结果: 搜索结果页面会显示匹配的镜像列表。这里的信息比 CLI 更丰富:
    • 官方镜像(Official Images): 通常排在最前面,带有绿色 “Official Image” 标识。这些镜像由 Docker 团队或其合作伙伴维护,提供最佳实践和安全性。
    • 已验证发布者(Verified Publisher): 带有蓝色 “Verified Publisher” 标识。这些镜像由经过 Docker 认证的商业实体发布,通常提供高质量、支持良好的产品。
    • 社区镜像(Community Images): 由个人或社区用户发布,数量最多,但质量参差不齐,使用时需谨慎评估。
    • 详细信息: 每个镜像条目会显示名称、简要描述、星级、下载量等。
  4. 点击镜像查看详情页: 点击感兴趣的镜像,进入其仓库详情页。在这里,您可以找到:
    • 完整的 README 文档: 详细介绍镜像的功能、用法、配置、环境变量等。这是使用镜像最重要的参考资料。
    • 标签(Tags)列表: 列出该镜像所有可用的版本(例如 latest, 3.9, 3.8-slim-buster)。选择合适的标签至关重要。
    • Dockerfiles: 某些自动化构建的镜像会提供其 Dockerfile 的链接,供用户审查其构建过程。
    • 安全扫描报告: 对于一些官方和验证发布者的镜像,Docker Hub 会提供安全漏洞扫描报告。
    • 构建历史: 查看镜像的构建来源和历史。

网站查找的优缺点:
* 优点: 提供最全面的信息,包括详细文档、所有版本标签、安全报告等,视觉化更友好,易于比较和选择。
* 缺点: 需要打开浏览器,不适合全命令行操作的用户。

2.3 查找镜像的最佳实践

  • 优先选择官方镜像(Official Images): 如果有官方镜像可用,始终优先选择它们。它们通常维护良好、安全可靠,并提供最佳实践。
  • 考虑已验证发布者(Verified Publisher)的镜像: 对于特定商业软件或服务,这些镜像通常由供应商官方提供,质量有保障。
  • 谨慎使用社区镜像: 对于社区镜像,务必仔细阅读其 README 文档,查看其构建历史和 Dockerfile(如果提供),并检查其星级和下载量。对于生产环境,尽量避免使用来源不明或长期未更新的镜像。
  • 选择合适的标签(Tag): 不要盲目使用 latest 标签,它可能指向一个不断变化的版本。对于生产环境,应锁定到具体的版本标签(如 python:3.9.10-slim-buster),以确保环境的可重现性。
  • 阅读 README 文档: 无论镜像来源如何,始终阅读其 README 文档,这是理解如何正确使用镜像的关键。

第三章:镜像拉取——获取所需资源

找到合适的镜像后,下一步就是将其从 Docker Hub 下载到本地机器,这个过程称为“镜像拉取(Image Pull)”。

3.1 docker pull 命令简介

docker pull 命令用于从 Docker Registry 下载镜像到本地镜像缓存。

命令语法:
bash
docker pull [OPTIONS] NAME[:TAG|@DIGEST]

* NAME: 镜像的名称,格式为 [用户名/或组织名/]仓库名
* TAG: 镜像的版本标签,用于指定特定版本的镜像。如果省略 TAG,Docker 会默认拉取 latest 标签的镜像。
* DIGEST: 镜像的摘要(content hash),可以用来精确地指定一个不可变的镜像版本。

docker pull 的工作原理:
当您执行 docker pull 命令时,Docker 客户端会联系 Docker Hub,获取指定镜像的清单(manifest)。清单包含了构成该镜像的所有层(layers)的信息。然后,Docker 客户端会逐层下载这些层,如果本地已经存在某些层,则会重用这些层,从而节省带宽和存储空间。下载完成后,这些层会被组合成一个完整的镜像,存储在本地的 Docker 镜像缓存中。

3.2 拉取官方镜像

官方镜像通常只有仓库名,没有用户名或组织名作为前缀。

示例:

  1. 拉取 Nginx 官方镜像的 latest 版本:
    bash
    docker pull nginx

    输出示例:
    Using default tag: latest
    latest: Pulling from library/nginx
    500589a8183d: Pull complete
    384a62145e14: Pull complete
    e17c0df6ac86: Pull complete
    ...
    Status: Downloaded newer image for nginx:latest
    docker.io/library/nginx:latest

    这里 library/nginx 是 Docker Hub 内部的官方镜像仓库路径。当您只写 nginx 时,Docker 客户端会自动解析到 library/nginx

  2. 拉取特定版本的 Ubuntu 官方镜像:
    bash
    docker pull ubuntu:22.04

    这将拉取 Ubuntu 22.04 版本的镜像。

  3. 拉取带有特定架构或 OS 信息的镜像(不常用,但了解有益):
    某些镜像可能针对不同的操作系统或架构提供不同的变体。例如 arm64v8/ubuntu。但通常,Docker 客户端会自动选择适合您当前系统的版本。

3.3 拉取用户/组织镜像

用户或组织发布的镜像,其名称通常会带有发布者前缀。

示例:

  1. 拉取 bitnami 组织发布的 Nginx 镜像的 1.24.0 版本:
    bash
    docker pull bitnami/nginx:1.24.0

  2. 拉取某个个人用户发布的名为 my-web-app 的镜像的 v1.0 版本:
    bash
    docker pull yourusername/my-web-app:v1.0

    请将 yourusername 替换为实际的 Docker Hub 用户名。

3.4 验证已拉取镜像

拉取完成后,您可以使用 docker images 命令查看本地已有的镜像列表。

bash
docker images

输出示例:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest a1a6d027f272 10 days ago 134MB
ubuntu 22.04 6806540d1656 2 weeks ago 77.8MB
bitnami/nginx 1.24.0 a0b2c3d4e5f6 3 months ago 150MB

* REPOSITORY: 镜像的仓库名称。
* TAG: 镜像的版本标签。
* IMAGE ID: 镜像的唯一 ID。
* CREATED: 镜像创建的时间。
* SIZE: 镜像的大小。

3.5 拉取镜像的注意事项

  • 网络连接: 确保您的机器有稳定的网络连接,以便从 Docker Hub 下载镜像。
  • 磁盘空间: 镜像可能占用较大的磁盘空间,请确保有足够的可用空间。
  • 代理设置: 如果您在需要代理的环境中,请确保 Docker 客户端已正确配置代理。
  • latest 标签的陷阱: 如前所述,latest 标签并不总是指向最新发布的版本,而是指向仓库作者在推送时指定的“最新”版本。在生产环境中,应尽量避免使用 latest,而应明确指定版本号标签。
  • 镜像安全: 即使是来自知名来源的镜像,也应定期进行安全扫描。Docker Desktop 和许多第三方工具都提供了镜像漏洞扫描功能。

第四章:镜像推送——分享与部署您的成果

当您构建了自己的 Docker 镜像并希望与他人分享、部署到生产环境或进行备份时,就需要将镜像推送到 Docker Hub。这涉及到构建镜像、为镜像打标签以及执行推送操作。

4.1 前提条件:登录 Docker Hub

在推送镜像之前,您必须登录到 Docker Hub。如果未登录,或者登录凭证过期,推送操作将失败。

登录命令:
bash
docker login

系统会提示您输入 Docker Hub 的用户名和密码。成功登录后,您的凭证会被存储在本地(通常是 ~/.docker/config.json 文件中)。

bash
Username: your_docker_hub_username
Password:
Login Succeeded

4.2 镜像推送的工作流程

推送镜像到 Docker Hub 通常遵循以下步骤:

  1. 构建或准备镜像: 您需要有一个本地 Docker 镜像。这通常通过 docker build 命令从 Dockerfile 构建,或者通过 docker commit 命令从运行中的容器创建。
  2. 为镜像打标签(Tag): 这是最关键的一步。您必须为本地镜像打上一个符合 Docker Hub 命名规范的标签。
  3. 推送镜像: 使用 docker push 命令将打好标签的镜像上传到 Docker Hub。

4.3 步骤一:构建或准备镜像

方法一:通过 Dockerfile 构建镜像(推荐)

创建一个 Dockerfile 文件,例如:
“`dockerfile

Dockerfile

FROM ubuntu:22.04
LABEL maintainer=”Your Name your.email@example.com

RUN apt-get update && apt-get install -y \
nginx \
curl \
–no-install-recommends && \
rm -rf /var/lib/apt/lists/*

COPY index.html /var/www/html/index.html

EXPOSE 80

CMD [“nginx”, “-g”, “daemon off;”]
以及一个简单的 `index.html` 文件:html





My Custom Nginx

Hello from My Custom Nginx!

This is a custom Docker image pushed to Docker Hub.


“`

在包含 Dockerfileindex.html 的目录下执行构建命令:
bash
docker build -t my-custom-nginx:1.0 .

* -t: 为构建的镜像指定名称和标签。这里我们暂时给它一个本地名称 my-custom-nginx:1.0
* .: 指定 Dockerfile 的上下文路径,表示当前目录。

方法二:通过 docker commit 创建镜像(不推荐用于生产)

此方法是从一个运行中的容器创建新镜像。例如,您启动一个 Ubuntu 容器,安装一些软件,然后提交更改。
“`bash

1. 启动一个容器

docker run -it –name my_container ubuntu:22.04 bash

2. 在容器内部进行操作 (例如安装 nginx)

apt-get update && apt-get install -y nginx

3. 退出容器

exit

4. 提交容器更改为新镜像

docker commit my_container my-nginx-image:v1.0
“`
这种方式难以重现,且不透明,通常不推荐用于生产环境。

4.4 步骤二:为镜像打标签(Tag)

这是将本地镜像与 Docker Hub 仓库关联的关键步骤。您需要使用 docker tag 命令,将本地镜像重新标记为 [你的Docker Hub用户名]/[仓库名]:[标签] 的格式。

命令语法:
bash
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

* SOURCE_IMAGE[:TAG]: 本地已有的镜像名称和标签(如 my-custom-nginx:1.0)。
* TARGET_IMAGE[:TAG]: 目标仓库的完整名称和标签,格式为 [用户名]/[仓库名]:[标签]

示例:
继续上面的例子,假设您的 Docker Hub 用户名是 yourusername
bash
docker tag my-custom-nginx:1.0 yourusername/my-custom-nginx:1.0

现在,您的本地镜像 my-custom-nginx:1.0 有了一个新的别名 yourusername/my-custom-nginx:1.0。您可以通过 docker images 命令看到:

bash
docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
yourusername/my-custom-nginx 1.0 a1b2c3d4e5f6 5 minutes ago 200MB
my-custom-nginx 1.0 a1b2c3d4e5f6 5 minutes ago 200MB
...

两个条目的 IMAGE ID 是相同的,因为它们指向的是同一个镜像。

重要提示:
* 命名空间: [用户名]/[仓库名] 是您的个人或组织仓库的命名空间。对于个人用户,就是 您的用户名/仓库名
* 仓库名: 仓库名(my-custom-nginx)在您的用户名下必须是唯一的。
* 标签(Tag): 选择一个有意义的标签。latest 标签是默认值,但建议使用语义化版本号(如 1.0.0, 1.0.1)或描述性标签(如 dev, prod, feature-branch)。

4.5 步骤三:推送镜像到 Docker Hub

现在,您可以使用 docker push 命令将打好标签的镜像推送到 Docker Hub。

命令语法:
bash
docker push NAME[:TAG]

* NAME[:TAG]: 您刚才为镜像打上的目标标签,即 [用户名]/[仓库名]:[标签]

示例:
bash
docker push yourusername/my-custom-nginx:1.0

输出示例:
The push refers to repository [docker.io/yourusername/my-custom-nginx]
e1f2g3h4i5j6: Pushed
k7l8m9n0o1p2: Pushed
...
1.0: digest: sha256:abcdef... size: 2345

推送过程会显示每个层(layer)的上传进度。如果某个层已经存在于 Docker Hub 上(因为镜像共享层),它就不会被重新上传。

推送完成后,您可以登录 Docker Hub 网站,在您的个人资料下找到 my-custom-nginx 仓库,并查看 1.0 标签的镜像是否已经成功上传。

4.6 私有仓库与公共仓库

当您在 Docker Hub 上创建一个新的仓库时,可以选择将其设置为 公共(Public)私有(Private)
* 公共仓库: 任何人都可以查找、拉取和使用其中的镜像。
* 私有仓库: 只有您(或您授权的团队成员)登录后才能拉取和推送。这是存储敏感镜像或企业内部镜像的理想选择。

在推送时,无论仓库是公共还是私有,命令都是一样的,Docker Hub 会根据您的登录凭证和仓库设置进行验证。

4.7 镜像推送的最佳实践

  • 保持 Dockerfile 精简: 构建的镜像越小越好。移除不必要的依赖、构建工具和缓存文件。使用多阶段构建(Multi-stage builds)是实现此目标的强大方法。
  • 优化镜像层: 合理组织 Dockerfile 中的指令,将不经常变化的指令放在前面,以便利用 Docker 的缓存机制。尽量合并 RUN 指令以减少层数。
  • 使用 .dockerignore: 类似于 .gitignore.dockerignore 文件可以排除构建上下文中的不必要文件,从而减小构建上下文的大小,加速构建过程,并避免将敏感文件意外打包到镜像中。
  • 选择有意义的标签: latest 标签应谨慎使用。对于生产环境,始终使用具体的、不变的版本标签。
  • 编写清晰的 README: 为您的镜像仓库提供详细的 README 文档,说明镜像的用途、如何使用、配置选项、环境变量、暴露的端口、维护者信息等。这对于其他用户(或未来的您)理解和使用镜像至关重要。
  • 安全性:
    • 不要在镜像中包含敏感信息: 密码、API 密钥等不应硬编码在 Dockerfile 或镜像中。应通过环境变量、Docker Secrets 或 Kubernetes Secrets 在运行时注入。
    • 定期更新基础镜像: 使用最新的官方基础镜像,以获取最新的安全补丁。
    • 进行漏洞扫描: 利用 Docker Hub 的内置扫描功能或第三方工具(如 Snyk, Trivy)扫描镜像是否存在已知漏洞。
  • 自动化构建: 考虑将 Docker Hub 与您的代码仓库(如 GitHub, Bitbucket)集成,实现自动化构建。这样,每次代码提交,Docker Hub 都会自动构建新镜像并更新。

第五章:高级概念与最佳实践

除了基础的查找、拉取和推送,了解一些高级概念和最佳实践能让您更高效、安全地使用 Docker Hub。

5.1 镜像标签策略

一个良好的镜像标签策略至关重要,它能帮助您管理不同版本的应用程序,并确保部署的可预测性。
* 语义化版本控制 (Semantic Versioning): MAJOR.MINOR.PATCH (e.g., 1.2.3). 这是最推荐的方式,清晰表达版本兼容性。
* 长期支持 (LTS) 标签: 例如 ubuntu:22.04, node:16-lts
* Git Commit SHA / Build ID: 对于 CI/CD 流程,可以使用 Git commit SHA 或 CI/CD 系统生成的构建 ID 作为标签,实现精确溯源。例如 youruser/app:a1b2c3d
* 环境标签: youruser/app:dev, youruser/app:staging, youruser/app:prod。不建议直接在生产环境中使用 devstaging 镜像。

5.2 官方镜像与验证发布者

再次强调,理解这两种镜像的重要性:
* 官方镜像: 由 Docker 团队或其合作方维护,遵循严格的构建标准和安全准则。它们通常是作为应用程序的基础镜像(如 ubuntu, nginx, mysql, python)的黄金标准。
* 验证发布者镜像: 由经过 Docker 验证的商业公司提供,通常是其产品的官方容器化版本。这些镜像通常有专业的支持和维护。

在使用任何镜像之前,优先检查其来源和可信度。

5.3 镜像安全性与漏洞扫描

Docker Hub 提供了一些基础的镜像安全扫描功能,可以检测镜像中已知的 CVE(Common Vulnerabilities and Exposures)。
* 利用 Docker Hub 扫描: 在镜像仓库详情页,可以看到安全扫描结果。
* 使用 docker scan 命令: Docker Desktop 集成了 Snyk 扫描工具,可以直接在命令行对本地镜像进行扫描:
bash
docker scan yourusername/my-custom-nginx:1.0

* 集成到 CI/CD: 在自动化构建流程中加入镜像安全扫描步骤,确保只有通过安全检查的镜像才能被推送或部署。
* 最小化攻击面: 只安装运行应用程序所需的组件,移除不必要的工具和库,可以显著减少潜在的漏洞。

5.4 Docker 内容信任 (Docker Content Trust, DCT)

Docker Content Trust 允许对镜像进行数字签名,以验证发布者的身份并确保镜像在传输过程中没有被篡改。当 DCT 被启用时,Docker 客户端只会拉取和运行带有受信任密钥签名的镜像。
* 启用 DCT: 设置环境变量 DOCKER_CONTENT_TRUST=1
* 发布者需要配置签名密钥。
虽然增加了复杂性,但在对安全性要求极高的场景下,DCT 是非常重要的防护措施。

5.5 Docker Hub 组织与团队

对于企业或团队协作,Docker Hub 提供了组织(Organizations)功能。
* 创建组织: 允许您在 Docker Hub 上创建一个团队空间。
* 团队与权限: 在组织内创建团队,并为团队成员分配不同级别的权限(如只读、读写、管理)。这使得管理大量镜像和用户变得更加简单和安全。

总结:Docker Hub——容器世界的桥梁

Docker Hub 作为 Docker 生态系统的核心,为全球开发者提供了一个无与伦比的平台,用于容器镜像的查找、拉取与推送。从最基本的 docker search 到复杂的多阶段构建和自动化推送,它支撑着现代容器化应用的整个生命周期。

通过本文的详细指南,您应该已经全面掌握了 Docker Hub 的三大核心操作:
* 查找:利用 docker search 命令和 Docker Hub 网站高效定位所需镜像。
* 拉取:使用 docker pull 命令获取官方、用户或组织发布的镜像,并了解其工作原理和注意事项。
* 推送:遵循 docker login -> docker build -> docker tag -> docker push 的流程,将您的自定义镜像安全地分享出去。

同时,我们强调了最佳实践的重要性,包括选择可信镜像源、采用合理的标签策略、优化镜像大小、增强安全性以及充分利用 Docker Hub 的组织管理功能。

掌握 Docker Hub 的使用,是迈向高效、安全和可扩展容器化之路的关键一步。随着云原生技术的不断演进,Docker Hub 也将继续发挥其作为容器镜像中心的关键作用,赋能开发者构建更强大、更可靠的应用程序。希望这篇指南能助您在 Docker 的世界中乘风破浪!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部