跨开发、质量保证、用户验收测试和生产环境推广Docker镜像的最佳实践

11

我们的应用程序使用Docker Swarm作为编排器,并进行容器化。我想了解如何将Docker镜像从Dev、QA、UAT推广到生产环境。例如,如果我在Dev中创建了一个名为test:10的镜像(10是由Jenkins生成的构建编号),我该如何将相同的镜像推广到QA、UAT和生产环境?我们目前使用NEXUS作为Docker仓库。我的问题是如何拉取与Dev环境中使用的完全相同的镜像。有人能帮忙吗?


你能详细说明为什么 docker pull org/test:10 无法工作吗?镜像在构建后是不可变的,所以应该很简单。 - meatspace
是的,如果我手动运行此命令,它应该可以工作。我的要求是,如果在 Dev 环境中有 5 个微服务正在运行,我需要自动将 Dev 环境中存在的镜像推广到 QA 环境。 - arun Kaliappan
@meatspace的图像标签是可变的,它们可以更改为引用任何不可变的图像校验和。 - Matt
@arunKaliappan 这不是一个Docker或Nexus的问题,你可能需要一个适合于你的持续部署流水线的Jenkins作业,以允许某人输入版本或查询源环境。如果没有关于你的环境和Jenkins部署的具体描述,很难给出具体的答案。 - Matt
1
你解决了这个问题吗? - Mostafa Hussein
4个回答

8
您可以通过重新标记您的镜像并推送,将一个docker镜像仓库中的镜像推广到另一个仓库中:
docker build -t my-test .
docker tag my-test your-image-repository-dev/test:10
docker login "your-image-repository-url"
docker push your-image-repository-dev/test:10
# ... deploy/test your image in dev
docker pull your-image-repository-dev/test:10
docker tag your-image-repository-dev/test:10 \
           your-image-repository-qa/test:10
docker push your-image-repository-qa/test:10

您将在QA Docker图像存储库中拥有相同的图像。这对于已通过基本级别的单元/功能/用户接受测试的图像是有意义的,这些测试与未通过测试的图像不同!关键概念在于重新标记和推送图像的时间点。此外,针对每个Docker图像存储库指定图像拉取凭据可以帮助您限制实际可到达特定环境的图像。
上述策略的替代方法是,您可能没有单独的Docker图像存储库,而是选择改变图像名称而不是存储库。在这种情况下,您可以执行以下操作。
docker build -t my-test .
docker tag my-test your-image-repository/test:10
docker login "your-image-repository-url"
docker push your-image-repository/test:10
# ... deploy/test your image in dev
docker pull your-image-repository/test:10
docker tag your-image-repository/test:10 \
           your-image-repository/test-qa:10
docker push your-image-repository/test-qa:10

0
关键是在您的图像标签中使用某种形式的元数据来指示图像对应于部署过程的哪个步骤。有许多潜在的方法可以做到这一点,但也许首先看看 SemVer,因为它是一个被广泛使用并且有良好文档支持的选项。

https://semver.org/

在semver中需要注意的主要事项是版本中使用了-标记,这表示某些内容是“预发布”版本。

有了这个想法,很容易区分生产和非生产图像:

  • 生产版本:nginx:1.2.3
  • 非生产版本:nginx:1.2.3-10

从那里开始,如果需要,您可以通过使用“点分隔的预发布标识符”进一步分解非生产版本

  • dev:nginx:1.2.3-dev.10
  • qa:nginx:1.2.3-qa.10
  • uat:nginx:1.2.3-uat.10

还有其他标记方法可供使用,但SemVer有良好的文档记录,广泛应用,并且解决了问题。


0

我想知道您是否能够详细说明为什么将每个环境放在单独的容器存储库中是最佳实践,而不是像@Swiss所描述的那样使用单独的标签。 - XZen
将环境分离至少在生产和非生产环境之间是有益的,但如果您可以为每个环境管理一个环境,则会更有帮助。
  • 将注册表保持靠近拉取应用/服务
  • 生产注册表的高可用性
  • 清理旧的或未使用的镜像
- samdinesh

0
解决这个问题的一种方法是使用CI/CD工具,例如Jenkins或一些CI/CD bash脚本,并采用一种标记策略。正如您所知,您可以以不同的方式标记相同的图像。例如,您可以将构建的图像ID标记为0000,并多次标记如下:
Day 1:
| TAG         | IMAGE ID |
| test:10     | 00000000 |
| test:dev-latest | 00000001 |
| test:qa-latest  | 00000001 |
| test:prod-latest| 00000001 |    

Day 2:
| TAG             | IMAGE ID |
| test:10         | 00000000 |
| test:11         | 00000001 |
| test:dev-latest | 00000001 |
| test:qa-latest  | 00000001 |
| test:prod-latest| 00000001 |

你的编排器可以一直等待新的镜像被标记。从理论上讲,这种方法是有用的。然而,根据你的容器编排器具体的特性,你可以稍微调整这种方法来使用那些特定的功能。例如,镜像拉取策略、推出和回滚功能、实现蓝/绿策略的功能等。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接