这是我们将Java应用程序从开发者的电脑,真正推向全世界用户手中的“最后一公里”,也是现代软件开发中至关重要的一环,通常被称为DevOps的领域。我们将一步一步学习,如何将我们的应用打包、运行和管理。本课程的所有示例都将在Linux系统上进行,这些技术在Linux上是原生支持的。

第七部分:高级主题

第13章:容器化与部署

13.1 Docker

1. 核心概念:Docker解决了什么问题?

在Docker出现之前,有一个困扰所有程序员的经典难题:“这个问题在我的电脑上是好的啊!

  • 问题:一个应用在开发者的电脑(比如安装了Java 11, Ubuntu 22.04)上运行得好好的,但一部署到服务器(可能安装的是Java 8, CentOS 7)上就因为环境不一致而出错了。

  • Docker的解决方案:Docker通过一种叫做“容器化”的技术,将你的应用程序,连同它运行所需要的所有依赖环境(比如特定版本的Java、特定的库、特定的配置文件),一起打包成一个标准的、独立的、可移植的单元,我们称之为容器 (Container)

2. 虚拟机 vs. Docker容器(一个重要的对比)

好比说:你想在一个大房子(你的电脑)里,隔离出一个独立的空间来运行一个程序。

  • 虚拟机 (Virtual Machine):相当于你在房子里,用砖头水泥重新盖了一栋完整的、带地基的小房子。这栋小房子有自己独立的墙壁、水电系统,甚至独立的“户籍”(完整的操作系统)。它非常笨重,启动需要好几分钟。

  • Docker容器 (Container):相当于你在房子里放了一个轻便的、标准化的**“集装箱”。这个集装箱共享**大房子的地基和水电系统(共享主机的操作系统内核),里面只装了运行程序所必需的物品。它非常轻量,启动只需要几秒钟。

3. 一步一步学习Docker的核心组件

第一步:编写 Dockerfile (打包说明书)

Dockerfile是一个纯文本文件,里面写着构建Docker镜像的一步一步的指令

好比说:它就是一份制作“方便菜肴料理包”的食谱

Dockerfile

# Dockerfile

# 第一步:选择一个基础环境。我们从一个已经安装好Java 17的官方镜像开始。
FROM openjdk:17-slim

# 第二步:在容器内部创建一个工作目录
WORKDIR /app

# 第三步:将我们打包好的Java程序(一个.jar文件)复制到容器的工作目录里
# 第一个.代表本机当前目录,第二个.代表容器内的工作目录
COPY target/my-app.jar .

# 第四步:告诉容器,当它启动时,应该执行什么命令
CMD ["java", "-jar", "my-app.jar"]

这份“食谱”清晰地定义了我们的应用需要什么环境,以及如何运行它。

第二步:构建 Image (镜像)

镜像是根据Dockerfile(食谱)创建出来的一个只读的模板

好比说:镜像就是那份按照食谱制作好的、真空包装的“方便菜肴料理包”。你可以把这个料理包复制无数份,发给任何人。

命令(在包含Dockerfile的目录下运行):

Bash

# -t 表示给这个镜像起一个名字(tag),比如 my-java-app
# . 表示使用当前目录的Dockerfile
docker build -t my-java-app .

执行成功后,一个名为my-java-app的镜像就创建好了。

第三步:运行 Container (容器)

容器是镜像的一个运行实例

好比说:容器就是你拿出那份“料理包”(镜像),拆开包装,放进微波炉加热后,一份可以享用的、热气腾腾的饭菜。你可以用同一款料理包,加热出无数份一模一样的饭菜(运行多个容器)。

命令

Bash

# -d: 后台运行 (detached)
# -p 8080:8080: 将我们电脑的8080端口,映射到容器内部的8080端口
# --name: 给这个运行中的容器起个名字
# my-java-app: 我们要使用的镜像的名字
docker run -d -p 8080:8080 --name my-running-app my-java-app

执行后,你的Java应用就在一个完全隔离的容器环境中运行起来了!

第四步:Docker Hub (镜像超市)

我们上面FROM openjdk:17-slim中的 openjdk 镜像从哪里来?它来自 Docker Hub,这是一个官方的、公共的镜像注册中心,就像一个巨大的超市,你可以在里面找到几乎所有常用软件的官方“料理包”(镜像)。


13.2 Kubernetes (K8s) 基础

1. 核心概念:Docker之后,为什么还需要K8s?

Docker非常擅长在一台机器上打包和运行一个或几个容器。但是,当你的应用变成了一个由成百上千个容器组成的复杂微服务系统,需要运行在几十上百台服务器上时,新的问题出现了:

  • 如果一台服务器宕机了,上面的容器怎么办?

  • 如何平滑地更新一个正在运行的服务,而不让用户感觉到中断?

  • 当用户访问量激增时,如何自动增加容器的数量?

Kubernetes (简称K8s) 就是为了解决这些问题而生的。它是一个容器编排平台

好比说

  • Docker:为你提供了标准化的集装箱

  • Kubernetes:是一整套现代化的、全自动的国际航运港口系统。它负责管理成千上万的集装箱,拥有庞大的船队(服务器集群),以及一个智能的“中央调度塔”。它能自动决定哪个集装箱该装上哪艘船,保证货物安全送达,如果哪艘船沉了,它会自动派新的船去完成任务。

2. 一步一步了解K8s的核心组件

第一步:Cluster (集群) - 整个港口

一个K8s集群由多个服务器节点(Nodes)组成。

  • Master Node: 主节点,港口的“中央调度塔”,负责管理和决策。

  • Worker Nodes: 工作节点,是真正停靠货轮、装卸集装箱(运行容器)的“码头”。

第二步:Pod - 最小的部署单元

在K8s中,你不会直接部署一个容器,而是部署一个Pod。Pod是K8s中最小的管理单元,它可以包含一个或多个紧密关联的容器。

好比说:Pod就像是码头上的一个标准泊位。这个泊位有自己独立的网络(IP地址)和存储空间,专门用来安放一个或一组集装箱。对于小白,你可以暂时简单地认为“一个Pod就约等于一个正在运行的容器实例”

第三步:Deployment - 部署管理器

你通常不会手动去创建Pod,而是通过创建一个Deployment来管理它们。

好比说Deployment就是港口的“货运经理”。你给经理下达一个指令:“我需要保证港口里随时有3个‘Web服务’集装箱正在运行”。

  • 部署: 经理会找3个空闲的泊位(Pods),把“Web服务”的集装箱放上去。

  • 自我修复: 如果其中一个码头(Worker Node)塌了,导致一个Pod消失了,经理会立刻发现,并自动在另一个健康的码头上启动一个新的Pod,以确保运行中的Pod数量始终是你期望的3个。

  • 滚动更新: 当你有了新版的“Web服务”镜像时,你只需要告诉经理更新。他会很聪明地:先启动一个新版Pod,等它正常运行后,再关闭一个旧版Pod,如此循环,直到所有Pod都更新完毕。整个过程服务不会中断。

第四步:Service - 服务的“统一门牌号”

Pod的生命是短暂的,它们会被销毁和重建,每次重建后IP地址都会变化。那么,其他服务如何找到它们呢?答案是Service

好比说Service就像是港口为“Web服务”这个功能,在工商局注册的一个永久不变的、唯一的电话总机号码。无论你内部有多少个具体的“Web服务”Pod在运行,它们的IP如何变化,其他服务都只需要拨打这个统一的总机号码,Service会自动把电话转接到一个当前健康的Pod上。


13.3 CI/CD (持续集成/持续部署) 概念

1. 核心概念

CI/CD 是一套流程和实践,旨在通过自动化,将软件从“开发完成”到“交付给用户使用”的过程变得更快速、更可靠。

好比说:CI/CD 就像是一家全自动的、从农场到餐桌的披萨餐厅

2. 一步一步理解CI/CD流水线

第一步:开发人员提交代码

厨师研发了一个新的披萨配方(写好了新功能代码),然后将配方提交到中央菜谱库(Git仓库)。

第二步:CI - 持续集成 (Continuous Integration)

这是流水线的前半段,核心是“构建与测试”。

  • 触发: 当Git仓库收到新的代码提交时,CI服务器(如Jenkins, GitLab CI/CD)会自动被触发。

  • 过程:

    1. 自动编译 (和面): CI服务器会拉取最新代码,并尝试编译它。如果代码有语法错误,编译就会失败,立刻通知厨师修改。

    2. 自动测试 (烤一个样品尝味道): 如果编译成功,CI服务器会运行一系列预先写好的自动化测试(单元测试、集成测试),确保新配方不仅自己味道对,而且没有把其他菜的味道搞坏。

    3. 自动打包 (制作料理包): 如果所有测试都通过,CI服务器就会执行打包操作。在我们的现代流程中,就是构建一个新的Docker镜像(制作一份标准的“披萨料理包”),并把它推送到镜像仓库中。

CI的价值:让问题在开发的早期阶段就被快速发现和修复。

第三步:CD - 持续交付/持续部署 (Continuous Delivery/Deployment)

这是流水线的后半段,核心是“发布”。

  • 持续交付 (Continuous Delivery)

    • 过程: CI成功构建出的“料理包”(Docker镜像),会被自动地部署到一个准生产环境(Staging Environment)中。

    • 好比说: 自动做好的披萨,被送到了出餐口的保温柜里,等待餐厅经理手动按下一个按钮,服务员才会把它端给顾客。

  • 持续部署 (Continuous Deployment)

    • 过程: 这是最高级的自动化。CI成功构建出的“料理包”,无需任何人工干预,会自动地被部署到正式的生产环境中,直接交付给最终用户。

    • 好比说: 披萨做好后,传送带自动把它送到餐桌上,全程无人操作。

    • 如何实现: CI/CD服务器(如Jenkins)会调用kubectl命令,去通知Kubernetes集群,使用刚刚构建好的新版Docker镜像,对相应的Deployment进行一次滚动更新。

总结: CI/CD 通过一条自动化的流水线,连接了开发 (Git)部署 (Kubernetes),极大地提高了软件交付的速度和质量,是现代DevOps文化的核心实践。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐