从零开始:Java项目在华为云主机上的Docker化实践指南
1. 为什么要把Java项目塞进“集装箱”?聊聊容器化的那些事儿
大家好,我是老张,一个在Java和云原生领域摸爬滚打了十来年的老码农。今天咱们不聊那些高深莫测的理论,就说说一个特别实在的问题:你辛辛苦苦写好的Java项目,怎么才能像乐高积木一样,在任何地方都能快速、稳定地搭起来运行?答案就是容器化,而Docker就是目前最趁手的“集装箱”工具。
我见过太多团队,开发环境跑得好好的,一上测试环境就报错,到了生产环境更是各种依赖缺失、端口冲突、环境变量不对。每次部署都像开盲盒,运维和开发互相甩锅,心累得很。容器化就是为了解决这个痛点。你可以把容器想象成一个标准化的“集装箱”,里面不仅装着你的Java应用(JAR包或WAR包),还把运行它所需要的所有东西——比如特定版本的JDK、系统库、配置文件——全都打包在一起。这个集装箱在任何支持Docker的“码头”(比如华为云主机、你自己的服务器、甚至同事的笔记本电脑)上,都能以完全相同的方式启动和运行。
这次,我们就以华为云主机作为我们的“码头”,手把手带你走一遍将一个Spring Boot电商项目装进Docker“集装箱”,并把它存放到华为云的专属仓库——SWR(容器镜像服务) 里的全过程。整个过程就像一次清晰的物流操作:准备货物(项目)、制造集装箱(构建镜像)、贴上标签、存入云仓库。跟着做下来,你不仅能得到一个随时可用的镜像,更能彻底理解这套流程背后的逻辑。咱们这就开始。
2. 启程前的准备:领取你的云主机与创建镜像仓库
工欲善其事,必先利其器。在开始打包我们的Java项目之前,我们需要两样核心资源:一台可以操作的“工作台”(云主机),和一个存放成品“集装箱”的“云仓库”(SWR)。
2.1 第一步:申请并登录你的华为云主机
首先,你需要有一个华为云账号。如果还没有,去官网注册一个,完成实名认证,这个过程很简单。登录后,在控制台找到“开发者空间”或直接搜索“云主机ECS”。我们这次实验,可以直接使用华为云为开发者提供的免费体验资源,规格选择“鲲鹏通用计算增强型”这类,4核8G的Ubuntu系统就完全够用。点击“领取”或“购买”(注意选择免费套餐),几分钟后,一台崭新的云主机就准备好了。
云主机启动后,找到远程连接方式。华为云提供了多种方式,对于新手,我推荐使用控制台提供的“VNC远程登录”或者“CloudShell”,这能让你直接看到一个网页版的桌面或命令行终端,免去了配置SSH密钥的麻烦。登录进去后,你看到的就是一个纯净的Ubuntu Linux系统,这就是我们接下来的主战场。
2.2 第二步:创建你的专属镜像仓库组织
我们的“集装箱”造好后,得有个地方统一管理。华为云的容器镜像服务(SWR) 就是干这个的。它类似于Docker官方的Hub,但更安全、速度也更快(毕竟在国内)。
回到华为云控制台,搜索“容器镜像服务 SWR”并进入。首先,你需要选择一个区域,比如“北京四”。接下来是关键一步:创建组织。这个“组织”可以理解为你的个人或团队仓库的命名空间。点击“创建组织”,起一个名字,比如就用你名字的拼音 zhang_san,或者项目名 e-commerce-team。记住,这个名字在区域内必须是唯一的。
创建成功后,点击页面上方的“登录指令”,你会看到一行长长的命令,类似 docker login -u cn-north-4@xxxxx -p xxxxx swr.cn-north-4.myhuaweicloud.com。先把这个命令复制下来,存到记事本里,我们稍后会用到它。这个指令就是Docker客户端连接华为云SWR仓库的“钥匙”。
3. 在云主机上搭建Docker工作台
现在,我们已经在云主机里面了。接下来要做的,就是在这个纯净的系统里,安装我们制造“集装箱”的流水线——Docker引擎。
3.1 安装Docker CE(社区版)
打开终端(在桌面右键通常有“Open Terminal Here”选项),我们一行行命令来操作。别怕命令行,我会解释每一步在干嘛。
首先,更新系统的软件包列表,确保我们获取的是最新的安装源信息:
sudo apt-get update
接着,安装一些让apt能通过HTTPS协议下载软件的必要工具:
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
过程中可能会弹出一些配置对话框,直接按回车(Enter)确认默认选项即可。
然后,添加Docker的官方GPG密钥。这就像给软件加了一个防伪签名,确保我们下载的Docker是正版且未被篡改的。这里我们使用阿里云的镜像源,速度更快:
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg
接下来,告诉系统去哪里下载Docker软件。同样是添加阿里云的Docker仓库源:
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
命令中的 $(lsb_release -cs) 会自动获取你当前Ubuntu系统的版本代号(如jammy)。
再次更新软件源列表,这次它已经包含了新加的Docker仓库:
sudo apt-get update
现在,终于可以安装Docker引擎了:
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
安装完成后,启动Docker服务,并让它开机自启:
sudo systemctl start docker
sudo systemctl enable docker
最后,验证一下安装是否成功。运行 sudo docker version 能看到客户端和服务端的版本信息,或者运行 sudo docker run hello-world,如果能看到这个经典镜像输出的欢迎信息,恭喜你,Docker工作台已经就绪!
3.2 配置国内镜像加速器
直接从Docker官方Hub拉取基础镜像(比如我们后面要用到的ubuntu:22.04)可能会比较慢。我们可以配置一个国内的镜像加速器,这相当于给下载通道加了个“加速代理”。
创建或修改Docker的守护进程配置文件:
sudo vim /etc/docker/daemon.json
按 i 进入编辑模式,将以下内容粘贴进去。这里我集合了几个常用的国内镜像地址:
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://docker.mirrors.ustc.edu.cn"
]
}
按 Esc 键,然后输入 :wq 保存并退出vim。
最后,重启Docker服务让配置生效:
sudo systemctl daemon-reload
sudo systemctl restart docker
这样,后续拉取镜像的速度会快很多。
4. 准备你的Java项目:从代码到可执行包
Docker环境准备好了,现在轮到我们的“货物”——Java项目上场了。为了演示,我们使用一个准备好的Spring Boot电商Demo项目。你可以在云主机上直接克隆它。
4.1 获取并编译项目代码
在终端中,我们可以使用git克隆项目代码。如果没有安装git,先运行 sudo apt-get install -y git。
cd /home/developer/Desktop
git clone https://gitcode.com/CaseDeveloper/E-Commerce-Java-Docker.git
cd E-Commerce-Java-Docker
这个项目已经是一个Maven项目。我们需要将它编译打包成可执行的JAR文件。同样,如果系统没有Maven,需要安装:
sudo apt-get install -y maven
然后进行编译打包:
mvn clean package -DskipTests
命令执行成功后,你会在 target/ 目录下找到生成的 E-Commerce-Java-1.0-SNAPSHOT.jar 文件。这就是我们Java应用的核心“货物”。
重要的一步:验证JAR包。在把它塞进集装箱前,我们得先确认它本身是好的。在桌面目录下运行它试试:
java -jar /home/developer/Desktop/E-Commerce-Java-Docker/target/E-Commerce-Java-1.0-SNAPSHOT.jar
如果看到Spring Boot的启动日志,应用在某个端口(比如8080)成功启动,就说明JAR包没问题。按 Ctrl+C 停止它。这一步非常关键,避免把一个有问题的应用打包,到时候在容器里排查更麻烦。
5. 编写“集装箱”说明书:Dockerfile详解
Docker镜像是通过一个名为 Dockerfile 的文本文件构建出来的。这个文件就像一份详细的“集装箱制造说明书”,告诉Docker每一步该做什么。我们来逐行编写和理解它。
5.1 创建启动脚本
为了让容器启动时能运行我们的Java应用,我们先创建一个简单的Shell脚本。在项目根目录下(和target目录同级):
vim start.sh
按 i 编辑,输入以下内容:
#!/bin/bash
echo "=== 电商应用启动中 ==="
java -jar /app/E-Commerce-Java-1.0-SNAPSHOT.jar
echo "=== 应用启动完成 ==="
按 Esc,然后 :wq 保存。这个脚本很简单,就是输出日志并执行Java命令。别忘了给它加上可执行权限:chmod +x start.sh。
5.2 编写核心Dockerfile
现在来编写最重要的Dockerfile。
vim Dockerfile
我们将写入以下内容,我会加上详细注释:
# 第一行:指定基础镜像。我们从一个干净的Ubuntu 22.04系统开始构建。
FROM ubuntu:22.04
# 设置环境变量,避免安装过程中交互式提示(如时区选择)中断构建
ENV DEBIAN_FRONTEND=noninteractive
# 更新软件源并安装JDK 17。我们项目用的是Java 17。
RUN apt-get update && \
apt-get install -y openjdk-17-jdk-headless && \ # 安装无头版JDK,更轻量
apt-get clean && \ # 清理安装缓存,减小镜像体积
rm -rf /var/lib/apt/lists/* # 删除软件列表,进一步精简
# 在容器内创建一个工作目录
WORKDIR /app
# 将我们本地编译好的JAR包和启动脚本,复制到容器的/app目录下
COPY target/E-Commerce-Java-1.0-SNAPSHOT.jar /app/
COPY start.sh /app/
# 声明容器运行时对外暴露的端口。我们的Spring Boot应用默认跑在8080端口。
EXPOSE 8080
# 指定容器启动时默认执行的命令。这里执行我们的启动脚本。
CMD ["/bin/bash", "/app/start.sh"]
按 Esc,然后 :wq 保存。
我来解释一下这个设计思路:我们选择了 ubuntu:22.04 作为基础镜像,虽然它比一些超精简镜像(如Alpine)体积大,但兼容性更好,遇到奇怪依赖问题的概率更低,对新手更友好。然后,我们在里面安装了项目所需的精确的JDK版本(17)。最后,把我们的应用文件复制进去,并设定启动命令。这样构建出来的镜像,就是一个包含了完整运行时环境的独立单元。
6. 动手构建你的第一个Docker镜像
“说明书”写好了,原料(JAR包)也备齐了,现在开动流水线,制造我们的第一个“集装箱”吧!
6.1 执行构建命令
确保终端当前目录在包含 Dockerfile 和 target/ 的文件夹下。执行构建命令:
sudo docker build -t e-commerce-java:1.0 .
这个命令分解一下:
sudo:因为Docker守护进程需要root权限。docker build:构建镜像的指令。-t e-commerce-java:1.0:给构建出来的镜像打一个标签(Tag)。-t是tag的缩写,e-commerce-java是镜像名,1.0是版本号。名字和版本你可以自定义。.:这个点非常重要!它代表构建上下文(context) 的路径是当前目录。Docker会在构建时将这个目录下的所有文件(除了.dockerignore声明的)打包发送给Docker引擎。所以,如果你的目录里有大量无关文件(比如日志、IDE配置),构建会变慢,镜像也会无谓变大。最佳实践是保持上下文目录整洁。
命令运行后,你会看到Docker逐层执行Dockerfile里的指令:拉取基础镜像、运行更新命令、安装JDK、复制文件……每一步都会生成一个临时的“层”,并缓存起来。如果后续Dockerfile没有改动,这些层可以直接复用,这就是Docker构建速度快的原因。
6.2 验证本地镜像
构建完成后,运行以下命令查看本地已有的镜像:
sudo docker images
你应该能看到一个名为 e-commerce-java,标签为 1.0 的镜像,以及它的镜像ID、创建时间和大小。
光看还不够,我们得跑起来试试。在本地运行这个容器:
sudo docker run -d -p 8080:8080 --name my-ecommerce-app e-commerce-java:1.0
-d:让容器在后台运行(detached mode)。-p 8080:8080:端口映射。将容器内部的8080端口映射到云主机的8080端口。这样,你访问云主机的公网IP:8080,就能访问到容器里的应用了。--name my-ecommerce-app:给这个运行的容器实例起个名字,方便管理。
运行后,可以用 sudo docker ps 查看容器状态,用 sudo docker logs my-ecommerce-app 查看启动日志。如果一切正常,你的Java应用就已经在Docker容器里欢快地运行起来了!
7. 将镜像推送到华为云SWR仓库
本地测试没问题,这个“集装箱”就算合格了。接下来,我们要把它存放到华为云的SWR“云仓库”里,这样任何有权限的人或环境(比如另一台云主机、或者Kubernetes集群)都能拉取并运行它。
7.1 登录到华为云SWR
还记得我们在第二步保存的那个“登录指令”吗?现在用它。在终端里执行你复制的那个命令,它大概长这样:
sudo docker login -u cn-north-4@ABCDEFG -p xxxxxxxxxxxxx swr.cn-north-4.myhuaweicloud.com
执行后,如果输出 Login Succeeded,就表示登录成功。这个登录信息会保存在本地,一段时间内无需重复登录。
7.2 给本地镜像打上SWR标签
在推送到远程仓库前,必须按照SWR的命名规则给本地镜像重新打一个标签。规则是:[镜像仓库地址]/[组织名称]/[镜像名称:版本]。
- 镜像仓库地址:就是登录命令里最后的那个域名,例如
swr.cn-north-4.myhuaweicloud.com。 - 组织名称:你在SWR控制台创建的组织名,比如
zhang_san。 - 镜像名称和版本:可以沿用本地的,也可以修改。
执行打标签命令:
sudo docker tag e-commerce-java:1.0 swr.cn-north-4.myhuaweicloud.com/zhang_san/e-commerce-java:v1.0
这个命令并没有创建新镜像,只是给已有的镜像(通过镜像ID指向)新增了一个符合SWR格式的别名。执行 sudo docker images,你会看到同一个镜像ID对应了两个不同的标签。
7.3 执行推送
最后一步,推送镜像到云端:
sudo docker push swr.cn-north-4.myhuaweicloud.com/zhang_san/e-commerce-java:v1.0
Docker会分层上传镜像的各个部分。上传速度取决于你的网络和镜像大小。完成后,回到华为云SWR控制台,进入你的组织,就能在“镜像仓库”里看到刚刚推送的 e-commerce-java 镜像及其 v1.0 版本了。
8. 从SWR拉取并运行镜像:完成闭环
推送成功,整个流程就形成了一个闭环。为了验证仓库里的镜像是真的可用,我们可以在同一台云主机(或者任何一台装了Docker并能访问华为云的主机)上,尝试从SWR拉取并运行它。
首先,删除或停止我们本地运行的容器和镜像(模拟一个干净的环境):
sudo docker stop my-ecommerce-app && sudo docker rm my-ecommerce-app
sudo docker rmi e-commerce-java:1.0
sudo docker rmi swr.cn-north-4.myhuaweicloud.com/zhang_san/e-commerce-java:v1.0
然后,直接从SWR拉取镜像:
sudo docker pull swr.cn-north-4.myhuaweicloud.com/zhang_san/e-commerce-java:v1.0
拉取成功后,用同样的方式运行它:
sudo docker run -d -p 8080:8080 --name app-from-swr swr.cn-north-4.myhuaweicloud.com/zhang_san/e-commerce-java:v1.0
访问应用,功能应该和之前完全一样。这意味着,你的应用已经成功实现了容器化,并且拥有了一个云上的、可分发、可版本管理的“家”。以后在任何地方部署,只需要一条 docker run 命令,配合正确的镜像地址即可,彻底告别了“在我机器上是好的”这种魔咒。
走完这一整套流程,你可能已经感受到了容器化带来的秩序感。但这只是第一步,在实际项目中,你还会遇到如何管理多个环境配置、如何优化镜像体积、如何结合CI/CD流水线自动构建和推送等更深入的问题。不过别担心,掌握了今天这个从零到一的完整实践,你已经有了解决那些问题最坚实的基础。下次部署Java应用时,不妨就从给自己造一个“集装箱”开始吧。
更多推荐
所有评论(0)