Docker Tools 深度实践:Portainer、Dockge、IDEA、私有仓库、GitLab 与服务器面板

欢迎你来读这篇博客。

前面几篇文章已经讲过 Docker 基础、Docker Compose、Dockerfile 和 Dockerfile 优化。这一篇专门聊 Docker 生态里的工具体系。

本文核心内容包括:

  • Docker Tools 的整体分层
  • Portainer:可视化 Docker 管理平台
  • Dockge:面向 Compose Stack 的轻量管理工具
  • IDEA 操作 Docker:开发阶段如何和 Docker 集成
  • Docker 私有仓库:Registry 与 Harbor
  • Docker 私服加固:认证、TLS、权限、扫描、备份
  • Docker 搭建 GitLab:自托管代码仓库与 CI/CD
  • Panel 类工具:1Panel、宝塔、CasaOS 等服务器面板的定位
  • 其他常用 Docker 工具:Lazydocker、ctop、dive、Trivy、Hadolint、Watchtower
  • 一套个人 / 团队 / 公司级 Docker 工具链选型建议

如果 Docker CLI 是手术刀,那么 Portainer、Dockge、1Panel 这些工具就是操作台。
操作台能提高效率,但刀还是那把刀,权限还是那个权限。尤其是任何能访问 /var/run/docker.sock 的工具,本质上都拥有非常高的宿主机控制能力,别当成普通网页后台随便暴露到公网。

一、Docker Tools 到底解决什么问题?

Docker 本身提供了完整的 CLI:

1
2
3
4
5
6
7
8
9
docker ps
docker images
docker run
docker logs
docker exec
docker build
docker push
docker network ls
docker volume ls

但是随着服务越来越多,CLI 会遇到几个问题:

  1. 容器状态不够直观。
  2. 日志查看不够集中。
  3. 多个 Stack 管理不方便。
  4. 多台服务器切换麻烦。
  5. 新人记不住复杂命令。
  6. 镜像仓库、权限、安全扫描需要平台化。
  7. 开发阶段需要 IDE 直接操作镜像和容器。
  8. 运维侧需要面板、监控、备份、审计。

所以 Docker Tools 的本质不是替代 Docker,而是把不同阶段的 Docker 能力包装成更适合人的入口。

可以按使用场景分层:

mindmap
  root((Docker Tools 生态))
    开发阶段
      IntelliJ IDEA Docker
      Docker Desktop
      Dev Containers
      Testcontainers
    本机/单机管理
      Portainer
      Dockge
      Lazydocker
      ctop
    镜像构建与质量
      Dockerfile
      BuildKit
      Hadolint
      Dive
      Docker Scout
      Trivy
    镜像分发
      Docker Registry
      Harbor
      GitLab Container Registry
    服务部署
      Docker CLI
      Docker Compose
      Portainer Stack
      Dockge Stack
    服务器面板
      1Panel
      宝塔面板
      CasaOS
      CapRover
    CI/CD
      GitLab
      GitLab Runner
      Jenkins
      Drone
      Woodpecker
    安全治理
      TLS
      RBAC
      镜像扫描
      镜像签名
      SBOM
      审计日志

不同工具解决的问题不一样,千万不要用错场景。

比如:

  • 你只是想看容器日志,用 Lazydocker 就够了。
  • 你想给新人一个图形化 Docker 管理页面,用 Portainer 更合适。
  • 你主要通过 Compose 管理服务,用 Dockge 很顺手。
  • 你要企业级镜像私服,用 Harbor,不要裸奔 Registry。
  • 你要在 Java 项目里构建、运行、调试容器,IDEA 的 Docker 插件很适合。
  • 你要管理整个 Linux 服务器、网站、数据库、容器、备份,用 1Panel 这类面板更像一站式入口。

二、Docker Tools 选型总览

先给一张总表。

工具 类型 核心用途 适合场景 注意点
Portainer Web 管理平台 管理 Docker、容器、镜像、网络、卷、Stack 单机 / 多环境可视化管理 挂 Docker Socket,权限很高
Dockge Compose Stack 管理 管理 compose.yaml 项目 自托管应用、家庭服务器、轻量运维 聚焦 Compose,不是完整 Docker 平台
IntelliJ IDEA Docker IDE 集成 构建镜像、运行容器、连接 Registry Java 开发、本地调试 Ultimate 功能更完整
Docker Registry 私有镜像仓库 简单存储和分发镜像 小团队、内网、测试 权限弱,需要自行加固
Harbor 企业级 Registry 镜像仓库、RBAC、扫描、复制、审计 公司私服、生产环境 部署维护成本高于 Registry
GitLab Docker 代码仓库 + CI/CD 自托管 GitLab 和 Runner 私有代码平台、流水线 资源占用高,升级要谨慎
1Panel 服务器面板 管理网站、数据库、容器、应用、备份 VPS、个人服务器、中小团队 面板暴露面大,要加固
Lazydocker TUI 终端可视化管理容器 开发机、服务器临时排查 不适合权限分配和团队平台
ctop TUI 监控 查看容器 CPU、内存、IO 快速定位资源占用 只解决观测,不解决管理
Dive 镜像分析 分析镜像层和体积浪费 Dockerfile 优化 构建阶段辅助工具
Trivy 安全扫描 扫镜像、文件系统、配置、K8s DevSecOps、CI/CD 扫描结果要结合修复策略
Hadolint Dockerfile Lint 检查 Dockerfile 反模式 代码规范、CI 不能替代真实构建和扫描
Watchtower 自动更新容器 自动拉新镜像并重启容器 个人服务、非关键服务 生产环境慎用自动更新

三、工具之间的关系图

flowchart LR
    DEV[开发者] --> IDEA[IntelliJ IDEA Docker]
    DEV --> CLI[Docker CLI]

    IDEA --> DOCKER[Docker Engine]
    CLI --> DOCKER

    DOCKER --> CONTAINERS[容器]
    DOCKER --> IMAGES[本地镜像]
    DOCKER --> NETWORKS[网络]
    DOCKER --> VOLUMES[数据卷]

    PORTAINER[Portainer] -->|Docker Socket / Agent| DOCKER
    DOCKGE[Dockge] -->|Compose Stack| DOCKER
    PANEL[1Panel / 服务器面板] --> DOCKER

    IMAGES --> REGISTRY[Registry / Harbor / GitLab Registry]
    REGISTRY --> CI[GitLab CI / Jenkins / Runner]
    CI --> DOCKER

    SCAN[Trivy / Docker Scout] --> REGISTRY
    LINT[Hadolint / Dive] --> IMAGES

这一张图说明了一个事实:

所有图形工具最后都绕不开 Docker Engine。

Portainer、Dockge、IDEA、1Panel 都只是入口。真正执行容器生命周期管理的还是 Docker Engine。


四、Portainer 深度实践

1. Portainer 是什么?

Portainer 是一个 Web UI 管理平台,用来管理容器环境。它可以管理:

  • Docker Standalone
  • Docker Swarm
  • Kubernetes
  • Podman,部分场景
  • 本地环境
  • 远程环境
  • 多节点环境

对于很多团队来说,Portainer 的价值在于:

  1. 把 Docker CLI 可视化。
  2. 降低新人操作门槛。
  3. 集中管理多个环境。
  4. 提供用户、团队、权限、环境隔离。
  5. 可以管理镜像、容器、网络、卷、Stack。
  6. 可以直接查看日志、进入控制台、重启服务。

2. Portainer 的基本架构

Portainer 主要分为两个部分:

flowchart LR
    USER[用户浏览器] --> PORTAINER[Portainer Server]
    PORTAINER -->|/var/run/docker.sock| LOCAL[本地 Docker Engine]
    PORTAINER -->|Portainer Agent| REMOTE1[远程 Docker Host 1]
    PORTAINER -->|Portainer Agent| REMOTE2[远程 Docker Host 2]
    PORTAINER -->|Kubernetes API| K8S[Kubernetes Cluster]

常见部署方式有两种:

  1. Server 直接挂载本机 Docker Socket。
  2. Server 连接多个 Agent 管理远程节点。

3. Portainer 安装

创建数据卷:

1
docker volume create portainer_data

启动 Portainer CE:

1
2
3
4
5
6
7
8
docker run -d \
--name portainer \
--restart=always \
-p 8000:8000 \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:sts

说明:

参数 说明
9443 Portainer Web HTTPS UI 端口
8000 Edge Agent 隧道端口,Edge 场景需要
/var/run/docker.sock Docker Engine 控制入口
portainer_data Portainer 数据库和配置数据
--restart=always 容器退出后自动重启

如果不需要 Edge 功能,可以不暴露 8000:

1
2
3
4
5
6
7
docker run -d \
--name portainer \
--restart=always \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:sts

访问:

1
https://服务器IP:9443

首次访问需要创建管理员账号。

4. Portainer 能管理什么?

进入 Portainer 之后,一般会看到这些模块:

模块 作用
Dashboard 总览容器、镜像、卷、网络
Containers 创建、启动、停止、重启、删除容器
Images 拉取、删除、构建镜像
Networks 创建和管理 Docker 网络
Volumes 创建和管理数据卷
Stacks 管理 Compose Stack
Registries 配置 Docker Hub、Harbor、私服
Users / Teams 用户和团队权限
Environments 管理不同 Docker / K8s 环境
Logs / Console 查看日志、进入容器终端

5. Portainer 管理容器示例

假设要通过 Portainer 创建一个 Redis:

也可以用 CLI 对照理解:

1
2
3
4
5
6
7
8
9
docker volume create redis-data

docker run -d \
--name redis \
--restart=unless-stopped \
-p 6379:6379 \
-v redis-data:/data \
redis:7 \
redis-server --appendonly yes

Portainer 页面上对应的是:

  • Image:redis:7
  • Container name:redis
  • Port mapping:6379 -> 6379
  • Volume:redis-data -> /data
  • Restart policy:unless-stopped
  • Command:redis-server --appendonly yes

看懂 CLI,再用 UI,才不会点成玄学。

6. Portainer 的安全边界

Portainer 最大的问题不是它不好用,而是它太好用了。
因为它挂载了:

1
-v /var/run/docker.sock:/var/run/docker.sock

这个 Docker Socket 的权限非常高。

只要攻击者拿到 Portainer 管理员权限,就可以:

  • 启动特权容器
  • 挂载宿主机根目录
  • 读取宿主机文件
  • 修改容器配置
  • 拉取恶意镜像
  • 停止业务容器
  • 进入数据库容器
  • 导出敏感数据

所以 Portainer 绝对不能裸奔公网。

7. Portainer 加固建议

7.1 网络层加固

推荐:

  • 只允许内网访问
  • 使用 VPN / WireGuard / Tailscale 访问
  • 使用 Nginx 反向代理 + HTTPS
  • 防火墙限制来源 IP
  • 不直接暴露 9443 到公网

UFW 示例:

1
2
3
4
5
6
7
8
9
10
11
12
# 默认拒绝入站
sudo ufw default deny incoming
sudo ufw default allow outgoing

# 允许 SSH
sudo ufw allow 22/tcp

# 只允许指定 IP 访问 Portainer
sudo ufw allow from 你的办公IP to any port 9443 proto tcp

sudo ufw enable
sudo ufw status

7.2 账号层加固

建议:

  • 管理员账号使用强密码
  • 启用 2FA,如果版本支持
  • 不共用管理员账号
  • 按团队分配权限
  • 离职人员及时删除账号
  • 定期审计用户和权限

7.3 Docker Socket 风险控制

如果是多节点,优先使用 Agent 模式,不要到处开放 Docker TCP API。

如果必须开放 Docker TCP API,要使用 TLS 认证,不要开放未加密的 2375

危险示例:

1
tcp://0.0.0.0:2375

这基本等于把宿主机 root 权限挂在互联网上,赛博自助餐,谁来谁吃。

推荐:

1
2
3
4
5
6
7
Unix Socket 本地访问

SSH Tunnel

TLS 保护的 Docker TCP

Portainer Agent

8. Portainer 备份与迁移

Portainer 的重要数据在 portainer_data 里。

备份:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env bash
set -e

BACKUP_DIR="/opt/backups/portainer"
DATE="$(date +%Y%m%d_%H%M%S)"
mkdir -p "${BACKUP_DIR}"

docker run --rm \
-v portainer_data:/data \
-v "${BACKUP_DIR}:/backup" \
alpine \
tar czf "/backup/portainer_data_${DATE}.tar.gz" -C /data .

echo "Portainer backup: ${BACKUP_DIR}/portainer_data_${DATE}.tar.gz"

恢复:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env bash
set -e

BACKUP_FILE="$1"

if [ -z "$BACKUP_FILE" ]; then
echo "Usage: ./restore-portainer.sh <backup-file>"
exit 1
fi

docker rm -f portainer || true
docker volume create portainer_data

docker run --rm \
-v portainer_data:/data \
-v "$(dirname "$BACKUP_FILE"):/backup" \
alpine \
sh -c "cd /data && tar xzf /backup/$(basename "$BACKUP_FILE")"

echo "Portainer data restored."

五、Dockge 深度实践

1. Dockge 是什么?

Dockge 是一个轻量、漂亮、响应式的 Docker Compose Stack 管理工具。

它的定位很明确:

管理 compose.yaml 文件,而不是取代整个 Docker 管理平台。

它适合:

  • 自托管应用管理
  • 家庭服务器
  • VPS 应用堆栈
  • 个人实验环境
  • 中小型服务编排
  • 喜欢 Compose 文件化管理的人

Dockge 的核心特点:

  • 管理 compose.yaml
  • 创建、编辑、启动、停止、重启、删除 Stack
  • Web 编辑 Compose 文件
  • Web Terminal
  • 实时输出 Pull / Up / Down 日志
  • 可以把 docker run 转换为 compose.yaml
  • 文件结构保留在磁盘,不绑架你的 Compose 文件

2. Dockge 和 Portainer 的区别

对比项 Portainer Dockge
定位 通用容器管理平台 Compose Stack 管理工具
管理对象 容器、镜像、网络、卷、Stack、环境 compose.yaml Stack
复杂度 更完整,也更重 更轻量
多用户权限 更强 相对简单
适合团队 更适合 更偏个人/小团队
文件控制 Stack 可以在平台里管理 强调文件保留在磁盘
使用体验 企业控制台风格 自托管应用面板风格

简单说:

  • 想全面管理 Docker:Portainer
  • 只想优雅管理 Compose Stack:Dockge

3. Dockge 安装

官方默认:

  • Stack 目录:/opt/stacks
  • Dockge 目录:/opt/dockge
  • 默认端口:5001

安装:

1
2
3
4
5
6
mkdir -p /opt/stacks /opt/dockge
cd /opt/dockge

curl https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml --output compose.yaml

docker compose up -d

访问:

1
http://服务器IP:5001

4. Dockge 的目录结构建议

推荐:

1
2
3
4
5
6
7
8
9
10
11
12
/opt/
├── dockge/
│ └── compose.yaml
└── stacks/
├── nginx/
│ └── compose.yaml
├── redis/
│ └── compose.yaml
├── mysql/
│ └── compose.yaml
└── gitlab/
└── compose.yaml

这种结构的好处:

  1. 每个服务一个 Stack。
  2. 每个 Stack 都是独立 compose 文件。
  3. 可以用 Git 管理 /opt/stacks
  4. Dockge 不在时仍然可以使用 docker compose 命令。
  5. 迁移服务器更简单。

5. 用 Dockge 管理 Redis Stack

/opt/stacks/redis/compose.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
services:
redis:
image: redis:7
container_name: redis
restart: unless-stopped
ports:
- "6379:6379"
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis-data:/data
networks:
- app-net

networks:
app-net:
name: app-net

volumes:
redis-data:

CLI 启动:

1
2
cd /opt/stacks/redis
docker compose up -d

Dockge 里则可以通过 UI 管理这个 Stack。

6. Dockge 加固建议

Dockge 也会操作 Docker / Compose,因此同样要注意:

  • 不要直接暴露公网
  • 使用反向代理和 HTTPS
  • 限制访问 IP
  • 强密码
  • Stack 目录做好备份
  • 关键 Stack 不要随便让新人改
  • /opt/stacks 建议用 Git 版本管理

示例:

1
2
3
4
cd /opt/stacks
git init
git add .
git commit -m "init docker stacks"

以后每次改 Compose:

1
2
3
git diff
git add .
git commit -m "update redis stack"

这比“谁在面板里点了什么我不知道”要靠谱得多。


六、IntelliJ IDEA 操作 Docker

1. IDEA 为什么要集成 Docker?

对 Java 开发者来说,Docker 不只是部署工具,也是开发工具。

常见场景:

  • 本地快速启动 MySQL、Redis、Nacos、RabbitMQ
  • 直接在 IDEA 里构建 Docker 镜像
  • 运行 Dockerfile
  • 查看容器日志
  • 进入容器终端
  • 配置私有 Registry
  • 推送镜像
  • 使用远程 Docker Server
  • 调试容器中的应用

如果你是 Spring Boot 开发,IDEA + Docker 的组合非常适合本地开发环境标准化。

2. IDEA Docker 插件

IDEA 的 Docker 能力依赖 Docker 插件。

常见入口:

1
2
3
Settings / Preferences
-> Plugins
-> Docker

然后配置 Docker 连接:

1
2
3
Settings / Preferences
-> Build, Execution, Deployment
-> Docker

常见连接方式:

连接方式 场景
Docker Desktop Mac / Windows 本地开发
Unix Socket Linux 本地 Docker
TCP Socket 远程 Docker,不推荐裸奔
SSH 连接远程服务器 Docker,推荐
Docker Context 结合 CLI 上下文切换

3. IDEA 中常用 Docker 操作

在 IDEA 的 Services 窗口中通常可以:

  • 查看容器
  • 查看镜像
  • 查看网络
  • 查看数据卷
  • 拉取镜像
  • 构建镜像
  • 运行容器
  • 停止容器
  • 查看日志
  • 进入容器终端
  • 配置 Dockerfile Run Configuration

4. IDEA 构建 Spring Boot 镜像

项目结构:

1
2
3
4
demo/
├── Dockerfile
├── pom.xml
└── src/

Dockerfile:

1
2
3
4
5
6
7
8
9
FROM eclipse-temurin:17-jre

WORKDIR /app

COPY target/demo.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

先打包:

1
mvn clean package -DskipTests

IDEA 中可以右键 Dockerfile:

1
Run 'Dockerfile'

也可以创建 Dockerfile Run Configuration:

  • Dockerfile:./Dockerfile
  • Image tag:demo-app:1.0.0
  • Container name:demo-app
  • Bind ports:8080:8080
  • Environment variables:
    • SPRING_PROFILES_ACTIVE=dev

对应 CLI:

1
2
3
4
5
6
docker build -t demo-app:1.0.0 .
docker run -d \
--name demo-app \
-p 8080:8080 \
-e SPRING_PROFILES_ACTIVE=dev \
demo-app:1.0.0

5. IDEA 管理本地开发依赖

Java 项目常用依赖可以用 Docker 快速启动。

MySQL

1
2
3
4
5
6
7
docker run -d \
--name dev-mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=demo \
-v dev-mysql-data:/var/lib/mysql \
mysql:8.0

Redis

1
2
3
4
5
6
docker run -d \
--name dev-redis \
-p 6379:6379 \
-v dev-redis-data:/data \
redis:7 \
redis-server --appendonly yes

PostgreSQL

1
2
3
4
5
6
7
8
docker run -d \
--name dev-postgres \
-p 5432:5432 \
-e POSTGRES_USER=demo \
-e POSTGRES_PASSWORD=123456 \
-e POSTGRES_DB=demo_db \
-v dev-postgres-data:/var/lib/postgresql/data \
postgres:16

Nacos

1
2
3
4
5
6
docker run -d \
--name dev-nacos \
-p 8848:8848 \
-p 9848:9848 \
-e MODE=standalone \
nacos/nacos-server:latest

如果你正在做 Spring Cloud Alibaba,这种方式很适合本地验证。

6. IDEA 连接私有 Registry

IDEA 可以配置 Registry,用于:

  • 拉取私服镜像
  • 推送构建镜像
  • 查看仓库镜像

CLI 登录方式:

1
docker login registry.example.com

IDEA 内部通常也可以配置:

1
2
3
Docker
-> Registry
-> Add

填入:

  • Registry URL
  • Username
  • Password / Token

7. IDEA 远程 Docker 的安全建议

如果 IDEA 连接远程 Docker,推荐 SSH,不推荐裸 TCP。

危险:

1
tcp://server-ip:2375

推荐:

1
ssh://user@server-ip

如果必须 TCP,要使用 TLS:

1
tcp://server-ip:2376

开发机能控制远程 Docker,就意味着开发机可能间接控制服务器。权限链路要想清楚,不要为了图方便开一个 2375 放公网,图方便最后会变成图事故。


七、Docker 私有仓库:Registry 与 Harbor

1. 为什么需要 Docker 私服?

公共镜像仓库可以用 Docker Hub,但公司内部通常需要私有仓库。

原因:

  1. 内部业务镜像不能公开。
  2. CI/CD 需要统一推拉镜像。
  3. 生产环境需要控制镜像来源。
  4. 需要避免 Docker Hub 限流。
  5. 需要镜像版本治理。
  6. 需要漏洞扫描。
  7. 需要权限管理。
  8. 需要审计和追踪。

典型流程:

sequenceDiagram
    participant Dev as 开发者
    participant CI as CI/CD
    participant Reg as 私有镜像仓库
    participant Prod as 生产服务器

    Dev->>CI: 提交代码
    CI->>CI: 构建镜像
    CI->>Reg: docker push
    Prod->>Reg: docker pull
    Prod->>Prod: docker run / compose up

2. Registry 和 Harbor 的区别

对比项 Docker Registry / Distribution Harbor
定位 基础镜像仓库 企业级镜像仓库平台
UI 默认没有 有完整 Web UI
用户权限 弱,需要外部配合 项目、用户、角色、机器人账号
HTTPS 需要自行配置 安装时可配置
镜像扫描 无内置完整平台能力 可集成 Trivy 等扫描
复制同步 需要自行做 支持仓库复制策略
审计 更完整
适合场景 简单内网、小团队、测试 团队、公司、生产
部署复杂度 中等

建议:

  • 个人 / 临时环境:Registry
  • 小团队内网:Registry + Nginx + TLS + htpasswd
  • 正式公司环境:Harbor
  • 已经使用 GitLab:可考虑 GitLab Container Registry
  • 云上环境:可考虑云厂商镜像仓库

八、搭建 Docker Registry 私服

1. 最简单的 Registry

仅适合本机测试:

1
2
3
4
5
6
docker run -d \
--name registry \
--restart=always \
-p 5000:5000 \
-v registry-data:/var/lib/registry \
registry:3

测试:

1
2
3
4
docker pull alpine:latest
docker tag alpine:latest localhost:5000/alpine:latest
docker push localhost:5000/alpine:latest
docker pull localhost:5000/alpine:latest

2. 局域网 HTTP Registry

如果在内网使用 HTTP,需要 Docker 客户端配置 insecure registry。

服务端:

1
2
3
4
5
6
docker run -d \
--name registry \
--restart=always \
-p 5000:5000 \
-v /opt/registry/data:/var/lib/registry \
registry:3

客户端 /etc/docker/daemon.json

1
2
3
{
"insecure-registries": ["registry.lan:5000"]
}

重启 Docker:

1
sudo systemctl restart docker

推送:

1
2
docker tag demo-app:1.0.0 registry.lan:5000/backend/demo-app:1.0.0
docker push registry.lan:5000/backend/demo-app:1.0.0

注意:

HTTP Registry 只能用于内网测试或隔离环境。生产不要这么干。

3. Registry + htpasswd + TLS

生产至少要有:

  • HTTPS
  • 账号密码
  • 数据持久化
  • 防火墙
  • 备份
  • 访问审计

目录结构:

1
2
3
4
5
6
7
/opt/registry/
├── auth/
│ └── htpasswd
├── certs/
│ ├── domain.crt
│ └── domain.key
└── data/

创建目录:

1
2
mkdir -p /opt/registry/{auth,certs,data}
cd /opt/registry

生成 htpasswd:

1
2
3
docker run --rm \
--entrypoint htpasswd \
httpd:2 -Bbn testuser testpassword > /opt/registry/auth/htpasswd

这里 -B 表示使用 bcrypt。
很多人漏掉这个参数,结果登录怎么都不成功,然后开始怀疑人生。其实人生没问题,是命令少了参数。

放入证书:

1
2
/opt/registry/certs/domain.crt
/opt/registry/certs/domain.key

启动 Registry:

1
2
3
4
5
6
7
8
9
10
11
12
13
docker run -d \
--name registry \
--restart=always \
-p 5000:5000 \
-v /opt/registry/data:/var/lib/registry \
-v /opt/registry/auth:/auth \
-v /opt/registry/certs:/certs \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:3

登录:

1
docker login registry.example.com:5000

推送:

1
2
docker tag demo-app:1.0.0 registry.example.com:5000/backend/demo-app:1.0.0
docker push registry.example.com:5000/backend/demo-app:1.0.0

拉取:

1
docker pull registry.example.com:5000/backend/demo-app:1.0.0

4. 使用 Nginx 反向代理 Registry

更常见的生产形式:

flowchart LR
    CLIENT[Docker Client] -->|HTTPS 443| NGINX[Nginx]
    NGINX -->|HTTP 5000 / 内网| REGISTRY[Docker Registry]
    REGISTRY --> DATA[(Registry Data)]

Registry 只监听本机:

1
2
3
4
5
6
docker run -d \
--name registry \
--restart=always \
-p 127.0.0.1:5000:5000 \
-v /opt/registry/data:/var/lib/registry \
registry:3

Nginx 配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
listen 443 ssl;
server_name registry.example.com;

ssl_certificate /etc/nginx/certs/registry.crt;
ssl_certificate_key /etc/nginx/certs/registry.key;

client_max_body_size 0;
chunked_transfer_encoding on;

location /v2/ {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

proxy_read_timeout 900;
}
}

这种方式可以把 TLS、限流、访问控制、日志审计放在 Nginx 层。

5. Registry 垃圾回收

Registry 删除 tag 后,blob 不一定立即释放空间,需要垃圾回收。

基本思路:

  1. 停止写入。
  2. 执行 garbage-collect。
  3. 重启 Registry。

示例:

1
docker exec -it registry registry garbage-collect /etc/docker/registry/config.yml

更稳妥的方式是先停止 Registry 或进入只读模式,避免 GC 时还有 push 写入。

6. Registry 备份

备份数据目录:

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env bash
set -e

SRC="/opt/registry/data"
BACKUP_DIR="/opt/backups/registry"
DATE="$(date +%Y%m%d_%H%M%S)"

mkdir -p "${BACKUP_DIR}"

tar czf "${BACKUP_DIR}/registry-data-${DATE}.tar.gz" -C "${SRC}" .

echo "Backup created: ${BACKUP_DIR}/registry-data-${DATE}.tar.gz"

恢复:

1
2
tar xzf registry-data-20260607_120000.tar.gz -C /opt/registry/data
docker restart registry

九、Harbor:企业级 Docker 私服

1. Harbor 是什么?

Harbor 是一个企业级的云原生制品仓库,常用于管理容器镜像和 OCI Artifact。它在基础 Registry 之上增加了很多企业需要的能力:

  • Web UI
  • 项目管理
  • 用户与角色权限
  • Robot Account
  • 镜像漏洞扫描
  • 镜像复制
  • 策略管理
  • 审计日志
  • LDAP / OIDC 集成
  • 镜像保留策略
  • 镜像签名 / 信任相关能力
  • 多租户项目隔离

如果公司要搭 Docker 私服,通常不建议只上裸 Registry,Harbor 更像正解。

2. Harbor 核心概念

概念 说明
Project 项目,镜像命名空间和权限边界
Repository 仓库,例如 backend/demo-app
Artifact 镜像或其他 OCI 制品
Tag 镜像标签
User 用户
Robot Account 给 CI/CD 使用的机器人账号
Scanner 漏洞扫描器,例如 Trivy
Replication 镜像复制策略
Retention 镜像保留策略
Audit Log 审计日志

3. Harbor 部署流程

标准流程:

flowchart TB
    A[准备服务器] --> B[安装 Docker]
    B --> C[安装 Docker Compose 插件]
    C --> D[下载 Harbor Installer]
    D --> E[配置 HTTPS 证书]
    E --> F[编辑 harbor.yml]
    F --> G[执行 install.sh]
    G --> H[登录 Web UI]
    H --> I[创建项目和用户]
    I --> J[配置 Robot Account 和扫描策略]

典型安装步骤:

1
2
3
4
5
6
# 下载 Harbor 安装包,具体版本以官方 Release 为准
wget https://github.com/goharbor/harbor/releases/download/vX.Y.Z/harbor-online-installer-vX.Y.Z.tgz

tar xzf harbor-online-installer-vX.Y.Z.tgz
cd harbor
cp harbor.yml.tmpl harbor.yml

编辑 harbor.yml

1
2
3
4
5
6
7
8
9
10
hostname: harbor.example.com

https:
port: 443
certificate: /opt/certs/harbor.crt
private_key: /opt/certs/harbor.key

harbor_admin_password: ChangeMe_StrongPassword

data_volume: /data/harbor

安装:

1
./install.sh

如果要带漏洞扫描:

1
./install.sh --with-trivy

4. Harbor 使用流程

登录:

1
docker login harbor.example.com

打标签:

1
docker tag demo-app:1.0.0 harbor.example.com/backend/demo-app:1.0.0

推送:

1
docker push harbor.example.com/backend/demo-app:1.0.0

拉取:

1
docker pull harbor.example.com/backend/demo-app:1.0.0

5. Harbor 项目设计建议

不要把所有镜像都扔在一个项目里。

推荐按组织或业务划分:

1
2
3
4
5
6
7
library/
backend/
frontend/
middleware/
devops/
ai/
test/

示例:

1
2
3
4
harbor.example.com/backend/order-service:1.0.0
harbor.example.com/backend/pay-service:1.0.0
harbor.example.com/frontend/admin-web:1.0.0
harbor.example.com/middleware/custom-nginx:1.25.0

6. Harbor 权限建议

角色 权限
管理员 平台管理,不用于 CI
项目管理员 管理项目用户和策略
开发者 push / pull
访客 pull
Robot Account CI/CD push / pull

CI/CD 不要用管理员账号。
应该创建 Robot Account,只赋予某个项目的 push/pull 权限。

7. Harbor 保留策略

镜像越堆越多,磁盘很快爆。

建议配置保留策略:

  • 每个仓库保留最近 10 个 release tag
  • 保留最近 30 天内的构建镜像
  • 删除无 tag 镜像
  • dev/test 项目更激进
  • prod 项目更保守

Tag 设计建议:

1
2
3
4
5
6
1.0.0
1.0.1
20260607-1430
git-a1b2c3d
main-a1b2c3d
release-20260607

不要所有镜像都叫:

1
latest

latest 很方便,也很会制造悬案。


十、Docker 私服加固

Docker 私服是供应链入口,一旦被污染,后面所有服务器都会拉到有问题的镜像。

私服安全不是锦上添花,而是底线。

1. 加固总览

mindmap
  root((Docker 私服加固))
    传输安全
      HTTPS
      禁止公网 HTTP
      证书自动续期
    认证授权
      用户认证
      Robot Account
      最小权限
      禁止共享账号
    网络隔离
      内网访问
      VPN
      防火墙
      IP 白名单
    镜像安全
      漏洞扫描
      签名
      SBOM
      禁止高危镜像部署
    数据安全
      数据卷备份
      对象存储
      灾备恢复
    审计治理
      Push/Pull 日志
      登录日志
      操作审计
      告警

2. 必须启用 HTTPS

生产环境:

1
http://registry.example.com

不推荐。

应该:

1
https://registry.example.com

如果用自签证书,客户端需要信任 CA。

Linux Docker 客户端证书路径:

1
/etc/docker/certs.d/registry.example.com/ca.crt

如果带端口:

1
/etc/docker/certs.d/registry.example.com:5000/ca.crt

然后重启 Docker:

1
sudo systemctl restart docker

3. 禁止匿名 push

匿名 pull 在某些内网基础镜像仓库可以接受,但匿名 push 基本不应该存在。

Registry 要加 htpasswd。
Harbor 要使用项目权限。
GitLab Registry 要绑定项目和 token。

4. CI/CD 使用机器人账号

不要在流水线里写:

1
2
DOCKER_USERNAME: admin
DOCKER_PASSWORD: admin-password

推荐:

1
robot$backend-ci

权限:

  • 只允许 push/pull backend 项目
  • 不允许管理用户
  • 不允许删除项目
  • 定期轮换 token

5. 镜像扫描

常见扫描工具:

  • Harbor 内置 Trivy
  • Trivy CLI
  • Docker Scout
  • Grype
  • Clair

Trivy 扫描示例:

1
trivy image harbor.example.com/backend/demo-app:1.0.0

只输出高危和严重漏洞:

1
2
3
trivy image \
--severity HIGH,CRITICAL \
harbor.example.com/backend/demo-app:1.0.0

CI 中失败策略:

1
2
3
4
trivy image \
--exit-code 1 \
--severity CRITICAL \
harbor.example.com/backend/demo-app:1.0.0

6. Dockerfile Lint

Hadolint 示例:

1
docker run --rm -i hadolint/hadolint < Dockerfile

常见能查出的问题:

  • 未固定基础镜像版本
  • apt-get updateapt-get install 拆开
  • 没有清理 apt 缓存
  • 使用 root 用户
  • Shell 写法不规范

7. 镜像签名与 SBOM

建议生产环境逐步引入:

  • SBOM:知道镜像里有什么
  • 签名:知道镜像是谁构建的
  • Provenance:知道镜像如何构建
  • Admission Policy:不合规镜像不能部署

生成 SBOM:

1
docker sbom demo-app:1.0.0

或:

1
syft demo-app:1.0.0

Cosign 签名示意:

1
cosign sign harbor.example.com/backend/demo-app:1.0.0

验证:

1
cosign verify harbor.example.com/backend/demo-app:1.0.0

8. Registry 防火墙示例

只允许 CI 和生产服务器访问私服:

1
2
3
4
5
6
7
8
9
10
11
12
13
sudo ufw default deny incoming
sudo ufw default allow outgoing

# SSH
sudo ufw allow 22/tcp

# 只允许 CI 服务器访问 Harbor
sudo ufw allow from 10.0.1.10 to any port 443 proto tcp

# 只允许生产服务器网段访问 Harbor
sudo ufw allow from 10.0.2.0/24 to any port 443 proto tcp

sudo ufw enable

9. 私服备份策略

需要备份:

  • 镜像数据
  • 数据库
  • 配置文件
  • 证书
  • 用户权限配置
  • Harbor 的 harbor.yml
  • Registry 的 authcertsdata

备份频率建议:

环境 频率
个人测试 手动
小团队 每日
生产 每日 + 关键发布前
重要企业环境 定时快照 + 异地备份

十一、Docker 搭建 GitLab

1. 为什么用 Docker 搭 GitLab?

GitLab 是自托管代码仓库和 DevOps 平台,常用于:

  • Git 仓库管理
  • Issue
  • Merge Request
  • CI/CD
  • Container Registry
  • Wiki
  • Code Review
  • Runner 管理

用 Docker 搭 GitLab 的好处:

  • 部署相对简单
  • 升级和迁移更清晰
  • 配置、日志、数据目录独立挂载
  • 方便备份
  • 适合中小团队自托管

缺点也明显:

  • GitLab 比较吃资源
  • 升级要按路径来,不能瞎跳版本
  • 配置错误容易影响 SSH Clone、HTTPS、Runner
  • 数据备份必须认真做
  • Docker 方式不适合随便在 Windows Docker Desktop 上生产使用

2. GitLab Docker 目录规划

推荐:

1
2
3
4
/srv/gitlab/
├── config/
├── logs/
└── data/

创建:

1
2
sudo mkdir -p /srv/gitlab/{config,logs,data}
sudo chmod -R 755 /srv/gitlab

3. 使用 Docker Engine 启动 GitLab

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export GITLAB_HOME=/srv/gitlab

docker run -d \
--hostname gitlab.example.com \
--publish 443:443 \
--publish 80:80 \
--publish 2222:22 \
--name gitlab \
--restart always \
--volume $GITLAB_HOME/config:/etc/gitlab \
--volume $GITLAB_HOME/logs:/var/log/gitlab \
--volume $GITLAB_HOME/data:/var/opt/gitlab \
--shm-size 256m \
gitlab/gitlab-ce:18.10.1-ce.0

这里把宿主机 2222 映射到容器 22,避免和宿主机 SSH 端口冲突。

4. 配置 external_url 和 SSH 端口

编辑:

1
sudo vim /srv/gitlab/config/gitlab.rb

配置:

1
2
3
external_url 'https://gitlab.example.com'

gitlab_rails['gitlab_shell_ssh_port'] = 2222

重新配置:

1
2
docker exec -it gitlab gitlab-ctl reconfigure
docker restart gitlab

访问:

1
https://gitlab.example.com

SSH Clone 地址会类似:

1
ssh://git@gitlab.example.com:2222/group/project.git

5. GitLab 初始 root 密码

首次启动后查看:

1
docker exec -it gitlab cat /etc/gitlab/initial_root_password

注意该文件通常会在一段时间后被清理,首次登录后应立即修改 root 密码。

6. GitLab 日志查看

容器日志:

1
docker logs -f gitlab

GitLab 内部状态:

1
docker exec -it gitlab gitlab-ctl status

查看 GitLab 内部日志:

1
docker exec -it gitlab gitlab-ctl tail

7. GitLab 备份

创建备份:

1
docker exec -t gitlab gitlab-backup create

备份文件一般在:

1
/srv/gitlab/data/backups

还需要备份配置和密钥:

1
2
sudo tar czf gitlab-config-$(date +%Y%m%d_%H%M%S).tar.gz \
-C /srv/gitlab config

完整备份脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env bash
set -e

BACKUP_DIR="/opt/backups/gitlab"
DATE="$(date +%Y%m%d_%H%M%S)"
mkdir -p "${BACKUP_DIR}"

echo "Create GitLab application backup..."
docker exec -t gitlab gitlab-backup create

echo "Backup config..."
tar czf "${BACKUP_DIR}/gitlab-config-${DATE}.tar.gz" -C /srv/gitlab config

echo "Backup logs optionally..."
tar czf "${BACKUP_DIR}/gitlab-logs-${DATE}.tar.gz" -C /srv/gitlab logs

echo "Copy backup files..."
cp /srv/gitlab/data/backups/* "${BACKUP_DIR}/" || true

echo "GitLab backup done: ${BACKUP_DIR}"

8. GitLab 升级

升级思路:

  1. 查看当前版本。
  2. 阅读官方升级路径。
  3. 备份数据。
  4. 拉取目标版本镜像。
  5. 停止旧容器。
  6. 使用同样 volume 启动新版本。
  7. 检查日志。
  8. 执行健康检查。

不要从很老版本直接跳到最新版本。
GitLab 升级是有路径要求的,越是生产越不能“勇敢试试”。勇敢是美德,但数据库迁移不吃这一套。

拉取指定版本:

1
docker pull gitlab/gitlab-ce:18.10.1-ce.0

重建容器时保留 volume:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
docker rm -f gitlab

docker run -d \
--hostname gitlab.example.com \
--publish 443:443 \
--publish 80:80 \
--publish 2222:22 \
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
--shm-size 256m \
gitlab/gitlab-ce:18.10.1-ce.0

9. GitLab Runner Docker 部署

GitLab Runner 用于执行 CI/CD Job。

创建配置目录:

1
sudo mkdir -p /srv/gitlab-runner/config

启动 Runner:

1
2
3
4
5
6
docker run -d \
--name gitlab-runner \
--restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest

注册 Runner:

1
docker exec -it gitlab-runner gitlab-runner register

需要输入:

  • GitLab URL
  • Registration Token / Authentication Token
  • Runner 名称
  • Executor 类型,例如 docker
  • 默认镜像,例如 docker:stablemaven:3.9-eclipse-temurin-17

10. Runner 挂 Docker Socket 的风险

Runner 常见写法会挂载:

1
-v /var/run/docker.sock:/var/run/docker.sock

这表示 CI Job 可以控制宿主机 Docker。

风险:

  • 恶意流水线可以启动特权容器
  • 可以挂载宿主机目录
  • 可以读取宿主机敏感文件
  • 可以影响同一台机器上的其他容器

建议:

  1. Runner 使用独立机器。
  2. 不要和生产业务容器混跑。
  3. Runner 权限最小化。
  4. 对项目开放 Runner 要谨慎。
  5. 重要环境使用隔离 Runner。
  6. 对外部贡献者 MR 不要直接跑高权限 Runner。

11. GitLab + Harbor + Docker 部署流程

sequenceDiagram
    participant Dev as 开发者
    participant GitLab as GitLab
    participant Runner as GitLab Runner
    participant Harbor as Harbor
    participant Server as Docker 服务器

    Dev->>GitLab: Push 代码
    GitLab->>Runner: 触发 Pipeline
    Runner->>Runner: mvn package / npm build
    Runner->>Runner: docker build
    Runner->>Harbor: docker login / push
    Server->>Harbor: docker pull
    Server->>Server: docker run / compose up

.gitlab-ci.yml 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
stages:
- build
- image

variables:
IMAGE_NAME: harbor.example.com/backend/demo-app
IMAGE_TAG: $CI_COMMIT_SHORT_SHA

maven-build:
stage: build
image: maven:3.9-eclipse-temurin-17
script:
- mvn clean package -DskipTests
artifacts:
paths:
- target/*.jar

docker-build:
stage: image
image: docker:stable
services:
- docker:dind
script:
- echo "$HARBOR_PASSWORD" | docker login harbor.example.com -u "$HARBOR_USERNAME" --password-stdin
- docker build -t $IMAGE_NAME:$IMAGE_TAG .
- docker push $IMAGE_NAME:$IMAGE_TAG

注意:docker:dind 和 Docker Socket 两种方式各有取舍,生产要结合 Runner 隔离、安全和缓存设计。


十二、Panel 类工具:1Panel、宝塔、CasaOS

1. Panel 类工具是什么?

Panel 类工具是服务器运维面板,目标不是只管理 Docker,而是管理整台服务器。

常见能力:

  • 网站管理
  • Nginx / OpenResty 管理
  • 数据库管理
  • Docker 容器管理
  • 应用商店
  • 文件管理
  • 计划任务
  • 证书管理
  • 防火墙
  • 备份恢复
  • 监控告警
  • SSH / 终端
  • 日志查看

Docker 管理只是其中一部分。

2. 1Panel

1Panel 是现代化、开源的 Linux 服务器运维管理面板,比较适合:

  • 个人 VPS
  • 小团队服务器
  • 自托管服务
  • 应用商店部署
  • Docker 容器管理
  • 网站和证书管理
  • 数据库管理
  • 备份恢复

它强调:

  • Web UI 管理服务器
  • Docker 和容器管理
  • 应用商店
  • 防火墙
  • 备份恢复
  • 审计和安全能力
  • 大模型 / Agent 相关部署能力

3. 1Panel 安装

官方快速安装方式通常类似:

1
bash -c "$(curl -sSL https://resource.1panel.pro/v2/quick_start.sh)"

安装后访问:

1
http://服务器IP:端口/安全入口

如果忘记入口或账号信息:

1
1pctl user-info

4. 1Panel 适合做什么?

场景 是否适合
个人 VPS 管理 很适合
自托管应用部署 适合
管理网站和证书 适合
部署数据库 适合,但生产要注意备份
Docker 容器查看和管理 适合
企业复杂权限治理 要评估
大规模多主机容器平台 不适合,建议 Kubernetes / 专业平台
生产核心数据库面板化运维 谨慎

5. 1Panel 和 Portainer 的区别

对比项 1Panel Portainer
定位 Linux 服务器面板 容器管理平台
管理范围 网站、数据库、文件、容器、防火墙、备份 Docker/K8s/环境/容器资源
Docker 深度 中等 更深入
运维入口 一站式服务器管理 容器平台管理
适合用户 VPS 用户、自托管用户 Docker 用户、团队运维
安全重点 面板入口和系统权限 Docker Socket 和环境权限

简单说:

  • 你要管整台服务器:1Panel
  • 你要管 Docker 环境:Portainer
  • 你要管 Compose Stack:Dockge

6. Panel 类工具加固

Panel 工具危险点:

  1. 暴露 Web 管理入口。
  2. 能操作文件系统。
  3. 能操作数据库。
  4. 能操作 Docker。
  5. 可能能执行终端命令。
  6. 管理权限过大。

加固建议:

mindmap
  root((Panel 加固))
    网络
      不直接公网暴露
      防火墙白名单
      VPN访问
      HTTPS
    账号
      强密码
      2FA
      定期更换
      禁止共享
    系统
      最小开放端口
      定期更新
      备份
      审计日志
    Docker
      不随便挂宿主机目录
      不运行未知镜像
      不滥用 privileged
      检查数据卷

UFW 示例:

1
2
3
4
5
6
7
sudo ufw default deny incoming
sudo ufw default allow outgoing

sudo ufw allow 22/tcp
sudo ufw allow from 你的办公IP to any port 面板端口 proto tcp

sudo ufw enable

7. 宝塔、CasaOS、CapRover 简单对比

工具 更适合
1Panel 现代 Linux 面板、自托管、Docker、网站、数据库
宝塔面板 传统网站运维、PHP/Nginx/MySQL 管理
CasaOS 家庭服务器、NAS、自托管应用
CapRover 类 Heroku 的应用部署体验
Portainer Docker / Kubernetes 容器管理
Dockge Compose Stack 管理

选择不要盲目跟风。
你需要的是工具,不是赛博驾驶舱。按钮越多,误操作空间也越大。


十三、其他常用 Docker Tools

1. Lazydocker

Lazydocker 是一个终端 UI 工具,可以在终端里查看:

  • 容器列表
  • 服务状态
  • 日志
  • 资源占用
  • 镜像
  • 数据卷
  • Compose 服务

安装示例:

1
brew install lazydocker

Linux 可以使用安装脚本或二进制文件。

运行:

1
lazydocker

适合:

  • 开发机
  • 服务器排查
  • 不想敲一堆 docker logs -f 的人

不适合:

  • 团队权限管理
  • 多用户 Web 平台
  • 审计治理

2. ctop

ctop 类似容器版 top。

安装:

1
brew install ctop

运行:

1
ctop

可以快速看:

  • CPU
  • 内存
  • 网络
  • IO
  • 容器状态

适合临时排查资源占用。

3. Dive

Dive 用来分析镜像层。

安装后:

1
dive demo-app:1.0.0

它可以看到:

  • 每一层做了什么
  • 哪些文件被添加
  • 哪些文件被删除
  • 镜像浪费空间
  • Dockerfile 哪一步导致镜像变胖

适合 Dockerfile 优化。

4. Hadolint

Hadolint 是 Dockerfile Linter。

使用 Docker 运行:

1
docker run --rm -i hadolint/hadolint < Dockerfile

CI 示例:

1
2
3
4
dockerfile-lint:
image: hadolint/hadolint:latest-debian
script:
- hadolint Dockerfile

5. Trivy

Trivy 是常用的云原生安全扫描工具,可以扫描:

  • 容器镜像
  • 文件系统
  • Git 仓库
  • Kubernetes 配置
  • IaC 配置
  • SBOM

扫描镜像:

1
trivy image nginx:latest

扫描本地项目:

1
trivy fs .

只看严重漏洞:

1
trivy image --severity CRITICAL,HIGH demo-app:1.0.0

CI 阻断:

1
trivy image --exit-code 1 --severity CRITICAL demo-app:1.0.0

6. Docker Scout

Docker Scout 是 Docker 官方的镜像安全分析工具,可以用于查看镜像组成和漏洞情况。

示例:

1
2
3
docker scout quickview demo-app:1.0.0
docker scout cves demo-app:1.0.0
docker scout recommendations demo-app:1.0.0

适合:

  • Docker Desktop 用户
  • Docker Hub / Docker 官方生态
  • 镜像漏洞分析
  • 修复建议

7. Watchtower

Watchtower 可以自动检查镜像更新,并重启容器。

示例:

1
2
3
4
5
docker run -d \
--name watchtower \
--restart=unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower

但生产环境慎用。

原因:

  • 自动更新可能引入不兼容版本
  • 数据库类服务不适合随便更新
  • 更新失败可能导致业务中断
  • 没有完整测试就上线,很刺激,也很危险

更推荐:

  • 个人服务:可以用 Watchtower
  • 测试环境:可以用
  • 生产环境:走 CI/CD、灰度、回滚流程

8. Docker Context

Docker Context 用来管理多个 Docker endpoint。

查看:

1
docker context ls

创建 SSH Context:

1
2
docker context create prod \
--docker "host=ssh://deploy@prod-server"

切换:

1
docker context use prod

执行:

1
docker ps

切回默认:

1
docker context use default

这比直接开 Docker TCP 2375 安全很多。


十四、推荐工具链组合

1. 个人开发者

推荐:

1
2
3
4
5
6
7
Docker Desktop / Docker Engine
+ IDEA Docker 插件
+ Lazydocker
+ Dive
+ Hadolint
+ Trivy
+ Dockge

适合:

  • 本地开发
  • 自托管小服务
  • 学习 Docker
  • 管理几个 Compose Stack

2. 个人 VPS / HomeLab

推荐:

1
2
3
4
5
6
7
1Panel
+ Dockge
+ Portainer 可选
+ Nginx Proxy Manager / Caddy
+ Uptime Kuma
+ Watchtower 谨慎使用
+ Trivy 定期扫描

适合:

  • 个人博客
  • 网盘
  • 监控
  • Git 服务
  • 轻量数据库
  • 自托管 AI 服务

3. 小团队

推荐:

1
2
3
4
5
6
7
8
GitLab / Gitea
+ GitLab Runner / Drone
+ Harbor
+ Portainer
+ Dockge
+ Trivy
+ Hadolint
+ Nginx / Traefik

适合:

  • 内部业务服务
  • 自动构建镜像
  • 私有镜像仓库
  • 可视化容器管理
  • 简单 DevOps 流程

4. 公司生产环境

推荐:

1
2
3
4
5
6
7
8
9
Harbor
+ GitLab CI / Jenkins
+ Trivy / Docker Scout / Grype
+ SBOM / Cosign
+ Prometheus / Grafana
+ Loki / ELK
+ Portainer BE 或 Kubernetes 平台
+ 严格网络隔离
+ 标准 CI/CD 发布

此时就不要迷信“一个面板管天下”。
生产环境要的是标准化、审计、权限、回滚、灾备,不是按钮够不够多。


十五、一套完整 Docker Tools 实战架构

适合中小团队的架构:

flowchart TB
    DEV[开发者 IDEA / Docker CLI] --> GIT[GitLab]
    GIT --> RUNNER[GitLab Runner]
    RUNNER -->|docker build| IMAGE[业务镜像]
    IMAGE -->|docker push| HARBOR[Harbor 私有仓库]

    HARBOR -->|漏洞扫描| TRIVY[Trivy Scanner]
    HARBOR -->|镜像拉取| SERVER[Docker 服务器]

    PORTAINER[Portainer] --> SERVER
    DOCKGE[Dockge] --> SERVER
    PANEL[1Panel] --> SERVER

    SERVER --> APP1[业务容器]
    SERVER --> APP2[Redis / MySQL]
    SERVER --> APP3[Nginx / Gateway]

    MONITOR[Prometheus / Grafana / Uptime Kuma] --> SERVER
    LOG[Loki / ELK] --> SERVER

流程说明

  1. 开发者在 IDEA 中开发代码。
  2. 提交到 GitLab。
  3. GitLab Runner 执行测试和构建。
  4. 构建 Docker 镜像。
  5. 使用 Robot Account 推送到 Harbor。
  6. Harbor 做漏洞扫描和权限控制。
  7. 服务器从 Harbor 拉取镜像。
  8. Portainer / Dockge / CLI 管理运行状态。
  9. 监控和日志系统负责观测。
  10. 面板类工具负责服务器基础运维。

十六、常用脚本合集

1. 安装 Portainer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env bash
set -e

docker volume create portainer_data

docker rm -f portainer || true

docker run -d \
--name portainer \
--restart=always \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:sts

echo "Portainer installed: https://SERVER_IP:9443"

2. 安装 Dockge

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env bash
set -e

mkdir -p /opt/stacks /opt/dockge
cd /opt/dockge

if [ ! -f compose.yaml ]; then
curl https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml --output compose.yaml
fi

docker compose up -d

echo "Dockge installed: http://SERVER_IP:5001"

3. 部署 Registry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env bash
set -e

REGISTRY_DIR="/opt/registry"

mkdir -p "${REGISTRY_DIR}/data"

docker rm -f registry || true

docker run -d \
--name registry \
--restart=always \
-p 5000:5000 \
-v "${REGISTRY_DIR}/data:/var/lib/registry" \
registry:3

echo "Registry started on port 5000"

4. Registry 生成 htpasswd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env bash
set -e

USER_NAME="$1"
PASSWORD="$2"

if [ -z "$USER_NAME" ] || [ -z "$PASSWORD" ]; then
echo "Usage: ./create-registry-user.sh <username> <password>"
exit 1
fi

mkdir -p /opt/registry/auth

docker run --rm \
--entrypoint htpasswd \
httpd:2 -Bbn "$USER_NAME" "$PASSWORD" >> /opt/registry/auth/htpasswd

echo "User added: ${USER_NAME}"

5. Docker 登录私服

1
2
3
4
5
6
7
8
#!/usr/bin/env bash
set -e

REGISTRY="harbor.example.com"
USERNAME="$1"
PASSWORD="$2"

echo "$PASSWORD" | docker login "$REGISTRY" -u "$USERNAME" --password-stdin

6. 构建并推送镜像到 Harbor

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env bash
set -e

APP_NAME="demo-app"
VERSION="${1:-$(date +%Y%m%d%H%M%S)}"
REGISTRY="harbor.example.com"
PROJECT="backend"
IMAGE="${REGISTRY}/${PROJECT}/${APP_NAME}:${VERSION}"

docker build -t "${IMAGE}" .
docker push "${IMAGE}"

echo "Pushed: ${IMAGE}"

7. 安装 GitLab

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env bash
set -e

GITLAB_HOME="/srv/gitlab"
GITLAB_HOST="gitlab.example.com"
GITLAB_IMAGE="gitlab/gitlab-ce:18.10.1-ce.0"

sudo mkdir -p "${GITLAB_HOME}/config" "${GITLAB_HOME}/logs" "${GITLAB_HOME}/data"

docker rm -f gitlab || true

docker run -d \
--hostname "${GITLAB_HOST}" \
--publish 443:443 \
--publish 80:80 \
--publish 2222:22 \
--name gitlab \
--restart always \
--volume "${GITLAB_HOME}/config:/etc/gitlab" \
--volume "${GITLAB_HOME}/logs:/var/log/gitlab" \
--volume "${GITLAB_HOME}/data:/var/opt/gitlab" \
--shm-size 256m \
"${GITLAB_IMAGE}"

echo "GitLab starting..."
echo "Open: https://${GITLAB_HOST}"

8. GitLab 备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env bash
set -e

BACKUP_DIR="/opt/backups/gitlab"
DATE="$(date +%Y%m%d_%H%M%S)"

mkdir -p "${BACKUP_DIR}"

docker exec -t gitlab gitlab-backup create

tar czf "${BACKUP_DIR}/gitlab-config-${DATE}.tar.gz" -C /srv/gitlab config
cp /srv/gitlab/data/backups/* "${BACKUP_DIR}/" || true

echo "GitLab backup done: ${BACKUP_DIR}"

9. 容器安全检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env bash
set -e

echo "== Containers using privileged mode =="
docker ps -q | xargs -r docker inspect \
--format '{{.Name}} privileged={{.HostConfig.Privileged}}' | grep true || true

echo "== Containers mounting docker.sock =="
docker ps -q | xargs -r docker inspect \
--format '{{.Name}} {{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}' \
| grep docker.sock || true

echo "== Containers with host network =="
docker ps -q | xargs -r docker inspect \
--format '{{.Name}} network={{.HostConfig.NetworkMode}}' | grep host || true

10. 镜像扫描脚本

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env bash
set -e

IMAGE="$1"

if [ -z "$IMAGE" ]; then
echo "Usage: ./scan-image.sh <image>"
exit 1
fi

trivy image --severity HIGH,CRITICAL "$IMAGE"

十七、常见问题

1. Portainer 和 Dockge 能同时装吗?

可以。

建议:

  • Portainer 管容器、镜像、网络、卷、权限。
  • Dockge 管 Compose Stack。
  • 不要两边同时编辑同一个 Stack,容易混乱。

2. Portainer 能不能替代命令行?

不能完全替代。

图形化工具适合日常操作,但排错、自动化、CI/CD 还是离不开命令行。

3. 私有 Registry 和 Harbor 选哪个?

个人和测试环境:

1
Registry

正式团队和生产环境:

1
Harbor

如果公司要权限、扫描、审计、复制、项目隔离,直接 Harbor。

4. GitLab 是否适合 Docker 部署?

适合中小团队和自托管场景。

但要注意:

  • 内存和磁盘要给够
  • 版本要固定
  • 数据要备份
  • 升级要按路径
  • Runner 要隔离

5. 1Panel 能不能替代 Portainer?

不完全能。

1Panel 是服务器管理面板,Portainer 是容器管理平台。
如果你的核心诉求是 Docker 管理,Portainer 更专业;如果你要同时管网站、证书、数据库、文件、计划任务,1Panel 更方便。

6. Docker Socket 为什么危险?

因为 Docker Socket 可以控制 Docker Engine。
控制 Docker Engine 后,可以启动容器挂载宿主机目录,例如:

1
2
3
docker run --rm -it \
-v /:/host \
alpine sh

这意味着可以读取甚至修改宿主机文件。

所以挂载 Docker Socket 的工具都要按高权限系统对待。


十八、最终建议

如果你是个人开发者:

1
IDEA Docker + Docker CLI + Lazydocker + Dockge

如果你是个人服务器:

1
1Panel + Dockge + Uptime Kuma + Nginx Proxy Manager

如果你是小团队:

1
GitLab + GitLab Runner + Harbor + Portainer + Trivy

如果你是公司生产环境:

1
Harbor + CI/CD + 镜像扫描 + SBOM + 签名 + 权限隔离 + 日志审计 + 备份灾备

不要为了“看起来高级”堆工具。
Docker 工具链的核心不是面板越多越好,而是:

  1. 权限边界清楚。
  2. 部署流程可重复。
  3. 镜像来源可信。
  4. 数据可以恢复。
  5. 出问题能排查。
  6. 升级可以回滚。
  7. 新人可以接手。

最后记住一句话:

Docker 工具是方向盘,不是安全带。
真正的安全来自权限控制、网络隔离、镜像治理、备份恢复和规范流程。

参考资料


Docker Tools 深度实践:Portainer、Dockge、IDEA、私有仓库、GitLab 与服务器面板
https://allendericdalexander.github.io/2026/06/07/devops/cri/docker-tools-deep-dive-blog/
作者
AtLuoFu
发布于
2026年6月7日
许可协议