在现代云原生应用的开发和部署过程中,容器化技术已经成为主流,而 Kubernetes(K8s)则是容器编排的绝对领导者。为了高效地管理和分发容器镜像,拥有一个可靠的私有镜像仓库是每个开发者和运维工程师不可或缺的工具。Docker 和 Harbor 作为业内广泛使用的容器技术和私有镜像仓库解决方案,为 K8s 环境中的镜像管理提供了强大的支持。
本文将带你一步步完成在 K8s 环境下搭建 Docker 和 Harbor 私有镜像仓库的过程。从安装 Docker 到配置 Harbor,涵盖了所有关键步骤,并通过详细的操作说明帮助你顺利搭建起一个高效、安全的镜像仓库,进一步提升容器化应用的开发和部署效率。无论你是 Docker 和 K8s 新手,还是已有一定经验的开发者,本文都将为你提供宝贵的指导和实用的技巧。
让我们通过一个例子来理解 Java 应用、Docker 和 Kubernetes (K8s) 之间的关系。我们可以将它们类比为 “餐厅经营” 的不同角色。
Java 应用 = 厨师
想象你经营一家餐厅,你的目标是为顾客提供美味的菜肴。Java 应用就像是你餐厅里的厨师,他负责烹饪所有的菜肴(即完成应用的业务逻辑)。你可以为不同的菜肴设计不同的菜谱(Java 代码),厨师需要根据顾客的需求(请求)来选择合适的菜肴制作方法,烹饪并提供给顾客。
例如,如果顾客点了一份牛排,你的厨师会根据菜谱调配好所有的配料(依赖库和框架),并根据要求控制火候,最终烹饪出一份完美的牛排(业务功能)。然而,不同的厨师(不同的 Java 应用实例)可能会有不同的技巧和风格,但最终都会做出同样的菜肴(业务逻辑)。
Docker = 厨房
那么,Docker 就像是你的厨房。它提供了一个固定的、标准化的烹饪环境,确保无论厨师是谁,都能在相同的条件下烹饪出相同的菜肴。厨房里有烤箱、锅具、刀具等必要的工具和配料,确保每个厨师都能在同样的条件下顺利工作。
通过 Docker,你的 Java 应用(厨师)可以在任何地方“工作”——无论是高档餐厅的厨房,还是你临时搭建的小厨房(不同的服务器和操作系统)。Docker 就是将这些环境标准化,使得无论厨房的规模和位置如何变化,菜肴(Java 应用)都能如期而至,不会因为环境不同而发生变化。
比如,你将一个 Java 应用(厨师) 用 Docker 包装起来(厨房),这个厨房可以在任何地方开设,甚至是街头小摊(不同的服务器环境)。而这个厨房内的所有工具和食材(依赖、库和环境)都已经准备好,厨师只需要按照菜谱来操作。
Kubernetes = 餐厅管理系统
接下来,当你不仅仅经营一家餐厅,而是要管理整个餐饮帝国(多个应用实例)时,Kubernetes 就像是你餐厅的智能管理系统。
假设你的餐饮帝国里有多家餐厅,且每家餐厅都有数名厨师(多个 Docker 容器实例)。你需要一个系统来协调这些厨师,确保每家餐厅都有足够的厨师应对订单需求,并且如果某个厨师因故障而无法继续工作,能自动调派其他厨师代替他。
Kubernetes 就是这个管理系统,它不仅帮助你确保每家餐厅有足够的厨师来应付忙碌的高峰期,还能根据顾客数量(流量)自动调整厨师的数量。如果某家餐厅的厨师不小心生病了,Kubernetes 会自动派一个备用厨师去替代,确保餐厅不会因为人手不足而出现问题。
具体到技术层面,Kubernetes 会做以下几件事:
- 调度和部署:它知道哪个餐厅需要更多的厨师,哪个餐厅可以减少厨师。
- 负载均衡:它确保顾客(请求)能够被平均地分配到不同的厨师那里,避免某个厨师超负荷工作。
- 自动扩展和收缩:如果某个餐厅突然迎来大量顾客(流量),Kubernetes 会自动派遣更多的厨师过去;如果需求下降,它也会减少厨师的数量。
- 容错和恢复:如果某个厨师无法工作,Kubernetes 会自动指派一个新的厨师替代他,保证餐厅的正常运作。
现在,实战开始~~~
1. 关闭防火墙和 SELinux
在开始之前,确保关闭防火墙和 SELinux,以免影响 Docker 和 Harbor 的运行。
# 停止并禁用防火墙
systemctl stop firewalld
systemctl disable firewalld
# 临时关闭 SELinux
setenforce 0
# 永久禁用 SELinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
2. 安装 Docker
接下来,安装 Docker 及其依赖包。
# 安装依赖包
yum -y install yum-utils device-mapper-persistent-data lvm2
# 添加 Docker 官方仓库
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装 Docker
yum -y install docker-ce docker-ce-cli containerd.io
由于网络原因,直接访问 https://download.docker.com
可能会比较慢或者不稳定。因此,很多用户会选择使用国内的镜像源来加速下载和安装 Docker。
你可以根据自己的网络环境和需求选择合适的镜像源:
3. 阿里云镜像源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4. 配置 Docker
编辑 Docker 配置文件,确保 Docker 使用正确的 cgroup 驱动和支持非安全的私有仓库。
# 编辑 Docker 配置文件
vim /etc/docker/daemon.json
# 添加以下内容,并根据实际情况修改 IP 地址
{"exec-opts": ["native.cgroupdriver=systemd"],"registry-mirrors": ["https://mirror.ccs.tencentyun.com"],"insecure-registries": ["你的访问IP:PORT"]
}
5. 启动 Docker 服务
重载配置并启动 Docker 服务。
# 重载 Docker 配置
systemctl daemon-reload
# 启动 Docker
systemctl start docker
# 设置 Docker 开机自启
systemctl enable docker
6. 上传和安装 Docker Compose 与 Harbor 安装包
从提供的链接下载 Docker Compose 和 Harbor 安装包,并上传到服务器上。
# 授予 Docker Compose 执行权限
chmod +x docker-compose
# 移动到 /usr/bin 目录
mv docker-compose /usr/bin
# 解压 Harbor 安装包
tar zxvf harbor-offline-installer-v2.3.4.tgz -C /usr/local/
# 进入 Harbor 安装目录
cd /usr/local/harbor
7. 配置 Harbor
复制 Harbor 配置模板,并根据你的需求编辑 harbor.yml
文件。
# 复制配置文件模板
cp harbor.yml.tmpl harbor.yml
# 编辑 harbor.yml 配置文件
vim harbor.yml
8. 准备并安装 Harbor
执行 ./prepare
检查环境准备情况,然后执行 ./install.sh
安装 Harbor。
# 执行准备步骤
cd /usr/local/harbor
./prepare
# 查看返回的结果,若为 0,则没有错误
echo $?
# 执行安装
./install.sh
如果一切顺利,执行完成后你将看到一系列绿色的 done
提示,表示安装成功。
- 确保关闭防火墙和 SELinux,以免影响 Docker 和 Harbor。
- 安装 Docker,并正确配置。
- 下载并上传 Docker Compose 和 Harbor 离线安装包。
- 配置 Harbor 的
harbor.yml
文件后执行安装。
9. 访问
http://IP:PORT
用户名:admin
密码:Harbor12345
10. 配置 Spring Boot 项目
bootstrap.yml
文件内容: (用于指定服务端口)
server:port: 8080 # 默认端口,可以不写
Dockerfile
文件内容: (在 pom.xml
中指定了打包文件名为 app
)
FROM openjdk:8u221-jre
# 设置工作目录
WORKDIR /tmp
# 将 Spring Boot JAR 文件添加到容器中
COPY spring-boot-docker-1.0.jar /app/app.jar
# 暴露端口(假设 Spring Boot 应用默认使用 8080 端口)
EXPOSE 8080
# 设置容器启动时的命令
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/app.jar"]
11. 构建 Docker 镜像
- 首先,确保将 JAR 包和
Dockerfile
文件上传到服务器的同一目录下。 - 使用以下命令构建 Docker 镜像:
构建成功后,执行以下命令查看已创建的镜像:
docker build -t spring-boot-docker .
成功后执行下 docker images,可以看到我们刚创建的镜像:
12. 运行 Docker 容器
使用以下命令来运行镜像并启动容器:
docker run -d -p 8080:8080 --name spring-boot-container spring-boot-docker
13. 参数说明
-d
:表示后台运行容器(detached mode)。-p 8080:8080
:将容器的 8080 端口映射到主机的 8080 端口,确保容器的应用可以通过主机的 8080 端口访问。--name spring-boot-container
:为容器指定一个名称(你可以根据需要修改容器名称)。spring-boot-docker
:这是你在构建镜像时指定的镜像名称,表示运行这个镜像创建容器。
14. 验证 Docker 容器运行
如果一切顺利,您的 Spring Boot 应用将在 Docker 容器中运行,并可以通过 http://<host-ip>:8080
访问。您可以通过以下命令检查容器的状态:
docker ps
这个命令会列出正在运行的容器,应该能看到类似于下面的输出:
15. 访问你的应用
如果你的 Spring Boot 应用在 8080
端口上监听,访问 http://localhost:8080
就能看到应用运行的结果。
16. 查看容器日志
如果您想查看容器的输出日志,可以使用以下命令:
docker logs spring-boot-container
这将显示容器的运行日志,可以帮助你排查应用是否成功启动。
17. 停止并删除容器(如果需要)
如果你需要停止并删除容器,可以使用以下命令:
docker stop spring-boot-container
docker rm spring-boot-container
将 docker build -t spring-boot-docker .
构建的镜像推送到 Harbor
18. 登录到 Harbor
首先,使用 docker login
命令登录到您的 Harbor 仓库。假设您的 Harbor 地址是 harbor.example.com
,可以使用以下命令:
# 登录用户
docker login -u admin -p Harbor12345 81.70.252.90
# 下面是退出
docker logout
19. 为镜像打标签
- 假设您的 Harbor 地址是
81.70.252.90:8090
,您的项目名称是myproject
,您希望将镜像标记为latest
版本。可以使用以下命令:
docker tag spring-boot-docker 81.70.252.90:8090/myproject/spring-boot-docker:latest
这将把 spring-boot-docker
镜像标记为 81.70.252.90:8090/myproject/spring-boot-docker:latest
,其中:
* 81.70.252.90:8090
是您的 Harbor 服务器地址和端口。
* myproject
是您在 Harbor 中创建的项目名称。
* spring-boot-docker
是镜像的名称。
* latest
是标签,表示这是最新版本。
- 确认镜像已成功打上标签:
您可以使用以下命令查看当前的镜像列表和标签:
docker images
应该能看到 81.70.252.90:8090/myproject/spring-boot-docker
和 latest
标签。
20. 推送镜像到 Harbor
- 确保您已经登录到 Harbor 仓库:
如果还没有登录到 Harbor,使用以下命令进行登录:
docker login -u admin -p Harbor12345 81.70.252.90:8090
在命令中,admin
是您的用户名,Harbor12345
是密码,81.70.252.90:8090
是 Harbor 地址。输入密码后,Docker 会验证您的凭证。
- 推送镜像到 Harbor:
使用 docker push
命令将镜像推送到 Harbor。假设您已经为镜像打上了标签 81.70.252.90:8090/myproject/spring-boot-docker:latest
,则可以运行以下命令:
docker push 81.70.252.90:8090/myproject/spring-boot-docker:latest
这将把镜像推送到 Harbor 仓库中的 myproject
项目,并标记为 latest
版本。
- 等待推送完成:
推送镜像的过程可能需要一些时间,具体取决于镜像的大小和网络速度。在命令行中,您将看到类似以下的输出,表示推送的进度:
- 验证推送成功:
可以通过以下命令验证镜像是否成功推送到 Harbor:
docker images
或者,可以登录到 Harbor 的 Web 界面,查看您的项目是否包含新的镜像。
使用 Kubernetes (k8s) 启动 81.70.252.90:8090/myproject/spring-boot-docker:latest
的镜像,你可以创建一个 Kubernetes Deployment 配置文件,并通过 kubectl
来部署它。
21. 创建 Deployment 配置文件
你需要创建一个 YAML 文件(比如 spring-boot-deployment.yaml
),描述如何在 Kubernetes 中运行你的容器。
以下是一个基本的 Deployment
配置示例:
apiVersion: apps/v1
kind: Deployment
metadata:name: spring-boot-deployment
spec:replicas: 1 # 设置要运行的副本数selector:matchLabels:app: spring-boottemplate:metadata:labels:app: spring-bootspec:containers:- name: spring-boot-containerimage: 81.70.252.90:8090/myproject/spring-boot-docker:latest # 镜像地址ports:- containerPort: 8080 # 这里假设应用监听 8080 端口,可以根据需要修改
22. 使用 kubectl 应用配置文件
将这个配置文件保存为 spring-boot-deployment.yaml
,然后使用 kubectl
命令将其应用到 Kubernetes 集群中:
kubectl apply -f spring-boot-deployment.yaml
这会启动一个 Deployment,Kubernetes 会按照配置运行你的容器镜像。如果你希望运行多个副本,只需修改 replicas
的数量即可。
23. 验证 Deployment 状态
你可以使用以下命令检查部署的状态:
kubectl get deployments
kubectl get pods
如果一切正常,你应该能看到相应的 pod 正在运行。
24. 暴露服务
如果你希望能够通过外部访问到你的应用,可以使用 Kubernetes 的 Service
来暴露端口。可以在同一个 YAML 文件中添加 Service
配置:
apiVersion: v1
kind: Service
metadata:name: spring-boot-service
spec:selector:app: spring-bootports:- protocol: TCPport: 80 # 外部访问端口targetPort: 8080 # 容器内部监听端口type: LoadBalancer # 或者使用 NodePort,根据需求选择
然后再次应用这个文件:
这样,你就可以通过 Kubernetes 的负载均衡器(如果使用的是云服务)或节点端口访问你的 Spring Boot 应用。
25.小提示
- 确保你的 Kubernetes 集群能够访问
81.70.252.90:8090
镜像仓库,如果是私有仓库,你可能需要创建一个Secret
来存储认证信息。
创建 Secret 的命令:kubectl create secret docker-registry my-registry-key \--docker-server=81.70.252.90:8090 \--docker-username=<your-username> \--docker-password=<your-password> \--docker-email=<your-email>
然后在 Deployment 配置中引用这个 Secret:
spec:imagePullSecrets:- name: my-registry-key
这样 Kubernetes 就可以从私有仓库拉取镜像了。