CentOS 7.9 离线部署 Harbor v2.14.4 私有镜像仓库与客户端安全加固指南

本指南根据真实的单机部署记录整理,详细展示了在 CentOS 7.9 上采用离线方式安装 Harbor v2.14.4 的完整实操步骤,并针对客户端登录时密码在本地以 Base64 存储所带来的安全隐患,提供了生产级的清除规范。


一、 部署前置条件审计

参考链接: https://goharbor.io/docs/2.14.0/install-config/installation-prereqs/

image

image

根据 Harbor 官方设计规范,单机运行环境必须满足 CPU 2 核、内存 4 GB 的要求,且必须提前部署好 Docker 引擎与 Docker Compose。

1. 验证 Docker 引擎与 Docker Compose 版本

在部署前,确认系统中的依赖版本:

[root@docker-harbor yum.repos.d]# docker --version
Docker version 26.1.4, build 5650f9b
[root@docker-harbor yum.repos.d]# 
[root@docker-harbor yum.repos.d]# docker compose version
Docker Compose version v2.27.1

二、 下载并解压 Harbor 离线安装包

离线安装包内集成了 Harbor 运行所需的全部核心组件镜像。

1. 解压安装包至目标路径 /usr/local/

[root@docker-harbor opt]# tar -zxvf harbor-offline-installer-v2.14.4.tgz -C /usr/local/
harbor/harbor.v2.14.4.tar.gz
harbor/prepare
harbor/LICENSE
harbor/install.sh
harbor/common.sh
harbor/harbor.yml.tmpl

三、 修改配置文件 harbor.yml

将模板配置文件复制为正式配置文件,并修改核心运行参数。

[root@docker-harbor harbor]# cp harbor.yml.tmpl harbor.yml

编辑 harbor.yml 后的关键配置内容如下:

# 1. 更改为你的宿主机物理 IP 地址(或者是可解析的内部域名)
hostname: 192.168.108.52

# 2. HTTP 服务配置(保持默认 80 端口,若冲突可改为其他端口如 8085)
http:
  port: 80

# 3. 生产环境建议配置 HTTPS。由于本次是开发联调 HTTP 环境,
# 必须【完全注释掉】整个 https 配置块(在每一行开头加 #):
#https:
#  # https port for harbor, default is 443
#  port: 443
#  # The path of cert and key buffer for nginx
#  certificate: /your/certificate/path
#  private_key: /your/private/key/path

# 4. 修改管理员初始密码(生产环境严禁使用默认的 Harbor12345)
harbor_admin_password: 1

# 5. 修改内部数据库密码(生产环境保持较高强度)
database:
  password: root123

# 6. 数据持久化存储路径(Harbor 产生的所有镜像、用户数据都存放在此)
data_volume: /data/harbor

四、 配置本地 Docker 客户端信任关系(HTTP 通道)

由于本次部署采用 HTTP 协议运行,而 Docker 客户端默认强制要求安全通道(HTTPS)。为了让客户端宿主机能够成功登录和推送,必须修改 /etc/docker/daemon.json 配置文件。

1. 修改客户端 /etc/docker/daemon.json 文件

[root@docker-harbor harbor]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": [
    "https://docker.1panel.live",
    "https://docker.m.daocloud.io",
    "https://dockerpull.com",
    "https://docker.anyhub.us.kg",
    "https://dhub.kubesre.xyz"
  ],
  "insecure-registries": [
    "192.168.108.52"
  ],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  },
  "storage-driver": "overlay2"
}

2. 客户端重启 Docker 服务使配置生效

[root@docker01 ~]# systemctl daemon-reload
[root@docker01 ~]# systemctl restart docker

五、 运行预处理与一键式安装

在执行安装前,先检查当前的本地镜像列表,确认处于纯净状态:

[root@docker-harbor harbor]# docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
[root@docker-harbor harbor]# 
[root@docker-harbor harbor]# ll
总用量 689316
-rw-r--r-- 1 root root      3646 5月   9 11:59 common.sh
-rw-r--r-- 1 root root 705799393 5月   9 11:59 harbor.v2.14.4.tar.gz
-rw-r--r-- 1 root root     14725 5月  26 11:25 harbor.yml
-rw-r--r-- 1 root root     14688 5月   9 11:59 harbor.yml.tmpl
drwxr-xr-x 2 root root        24 5月  26 13:13 input
-rwxr-xr-x 1 root root      1975 5月   9 11:59 install.sh
-rw-r--r-- 1 root root     11347 5月   9 11:59 LICENSE
-rwxr-xr-x 1 root root      2211 5月   9 11:59 prepare

1. 执行预处理脚本(生成相关配置与 docker-compose.yml 文件)

prepare 脚本在运行时会自动拉取一个辅助镜像来生成各组件配置:

[root@docker-harbor harbor]# ./prepare 
prepare base dir is set to /usr/local/harbor
Unable to find image 'goharbor/prepare:v2.14.4' locally
v2.14.4: Pulling from goharbor/prepare
f32f037feefe: Pull complete 
e34bbabc02a3: Pull complete 
faf1b33ed1a8: Pull complete 
b91c718b5fa7: Pull complete 
1116081300ad: Pull complete 
ef5d174761cf: Pull complete 
761cf74ab8dd: Pull complete 
8233664f654d: Pull complete 
b26c3fa7e43e: Pull complete 
b262e20f3e99: Pull complete 
afd79f2f0542: Pull complete 
fa0d23a6af75: Pull complete 
Digest: sha256:fe2df00ba5c1a468748a2c995f539acb224c8c0ea5a17a3256211cf558511244
Status: Downloaded newer image for goharbor/prepare:v2.14.4
WARNING:root:WARNING: HTTP protocol is insecure. Harbor will deprecate http protocol in the future. Please make sure to upgrade to https
Generated configuration file: /config/portal/nginx.conf
Generated configuration file: /config/log/logrotate.conf
Generated configuration file: /config/log/rsyslog_docker.conf
Generated configuration file: /config/nginx/nginx.conf
Generated configuration file: /config/core/env
Generated configuration file: /config/core/app.conf
Generated configuration file: /config/registry/config.yml
Generated configuration file: /config/registryctl/env
Generated configuration file: /config/registryctl/config.yml
Generated configuration file: /config/db/env
Generated configuration file: /config/jobservice/env
Generated configuration file: /config/jobservice/config.yml
copy /data/secret/tls/harbor_internal_ca.crt to shared trust ca dir as name harbor_internal_ca.crt ...
ca file /hostfs/data/secret/tls/harbor_internal_ca.crt is not exist
copy  to shared trust ca dir as name storage_ca_bundle.crt ...
copy None to shared trust ca dir as name redis_tls_ca.crt ...
Generated and saved secret to file: /data/secret/keys/secretkey
Successfully called func: create_root_cert
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir
[root@docker-harbor harbor]# echo $?
0

2. 执行一键安装脚本

[root@docker-harbor harbor]# ./install.sh

(省略其中镜像解压与加载日志)

后端组件编排运行日志:

[Step 5]: starting Harbor ...
[+] Running 10/10
 ✔ Network harbor_harbor        Created                                                                                                                                               0.2s 
 ✔ Container harbor-log         Started                                                                                                                                               1.0s 
 ✔ Container harbor-db          Started                                                                                                                                               2.8s 
 ✔ Container registryctl        Started                                                                                                                                               2.9s 
 ✔ Container registry           Started                                                                                                                                               2.3s 
 ✔ Container harbor-portal      Started                                                                                                                                               2.5s 
 ✔ Container redis              Started                                                                                                                                               2.8s 
 ✔ Container harbor-core        Started                                                                                                                                               3.5s 
 ✔ Container nginx              Started                                                                                                                                               4.7s 
 ✔ Container harbor-jobservice  Started                                                                                                                                               4.7s 
✔ ----Harbor has been installed and started successfully.----

六、 客户端双向验证与镜像推拉测试

1. Web 界面访问

  • 访问地址http://192.168.108.52
  • 管理员凭证
    • 用户名:admin
    • 密码:1(按实际 harbor.yml 配置)
  • 登录后,默认会存在公共项目 library

bd8ccefbab4ffd03b3a58eddb8e2075c

f9943dadff79b098f4d3312656740ccc

2. 客户端登录测试(暴露认证文件的安全隐患)

在外部客户端 docker01 上登录刚才建好的 Harbor:

[root@docker01 ~]# docker login 192.168.108.52 -u admin -p 1
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

此时查看本地的 Docker 配置文件,会发现用户的登录密钥以 Base64 格式写入了配置文件:

[root@docker01 ~]# cat /root/.docker/config.json 
{
	"auths": {
		"192.168.108.52": {
			"auth": "YWRtaW46MQ=="
		}
	}
}

安全警示:通过 Base64 解码,可以直接还原出登录明文密码

[root@docker01 ~]# echo YWRtaW46MQ== | base64 -d | more
admin:1

3. 镜像打标与推送验证

首先查看 docker01 上的本地镜像列表:

[root@docker01 ~]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED        SIZE
myalpine-from-nginx   latest    71df513817bd   16 hours ago   8.45MB
myalpine-copy         latest    a7279f99ec85   16 hours ago   8.45MB
myalpine-multi        latest    dcef87b9cd8c   16 hours ago   8.45MB
nginx                 latest    7aaca76c508f   3 days ago     161MB
mysql                 latest    094aec64961b   13 days ago    950MB
myalpine              latest    d7ba821f5b31   5 weeks ago    8.45MB
hello-world           latest    e2ac70e7319a   2 months ago   10.1kB

myalpine:latest 重新标记并推送到 Harbor 的 library 项目下:

# 重新打上符合 Harbor 格式的标签
[root@docker01 ~]# docker tag myalpine:latest 192.168.108.52/library/myalpine:3.1.12

# 推送镜像至私有镜像仓库
[root@docker01 ~]# docker push 192.168.108.52/library/myalpine:3.1.12
The push refers to repository [192.168.108.52/library/myalpine]
29df493baa13: Pushed 
3.1.12: digest: sha256:1f7a06dd52c2e70166fa1ba43fc6166ed163b22cfb241163b64674be55003037 size: 527

16e8e66887284c358aa184362e6368dc


七、 核心加固:推完即登出,规避本地残留密码

由于在多用户共享的服务器或构建机上运行 docker login 后会残留 base64 格式的配置凭证,极易导致凭证外泄。因此,标准的安全操作规程要求我们在推送/拉取任务完毕后,务必在宿主机上执行登出(logout)清理。

1. 确认当前保留了凭证:

[root@docker01 ~]# cat /root/.docker/config.json 
{
	"auths": {
		"192.168.108.52": {
			"auth": "YWRtaW46MQ=="
		}
	}
}
[root@docker01 ~]# 
[root@docker01 ~]# echo YWRtaW46MQ== | base64 -d | more
admin:1

2. 强制执行登出并检查清理状态:

[root@docker01 ~]# docker logout 192.168.108.52
Removing login credentials for 192.168.108.52

[root@docker01 ~]# cat /root/.docker/config.json
{
	"auths": {}
}

登出成功后,本地配置文件中的 "auths" 节点已被清空,排除了在宿主机被越权提权的隐患。该项操作对于企业生产环境及自动化 CI 构建机的安全审计具有重要实践意义。

posted on 2026-05-26 13:56  LeeHang  阅读(16)  评论(0)    收藏  举报