Docker 进阶实战系列(一):容器镜像安全,最小镜像与非 Root 运行

Docker 进阶实战系列(一):容器镜像安全,最小镜像与非 Root 运行

复制代码
# Docker进阶实战系列(一):容器镜像安全,最小镜像与非Root运行

> 本系列承接上一阶段 Docker Compose 实战,聚焦生产环境容器进阶能力,每篇短小精炼,主打实操落地。
> 前置知识:掌握基础Docker命令、Dockerfile编写、Compose基础使用。

## 前言
很多新手写Dockerfile习惯直接用`ubuntu`、`centos`或者完整`openjdk`大镜像,并且容器内全程用root用户运行。
这种做法有两大隐患:
1. 镜像体积巨大,包含大量无用依赖,漏洞多,被攻击面大
2. 容器内root权限,一旦服务被入侵,攻击者拿到root权限,会横向影响宿主机

本篇我们解决两个核心问题:**制作最小化镜像** + **容器禁止使用root运行**。

## 一、什么是最小镜像?
常见镜像体积对比(参考)
- ubuntu 基础镜像:~70MB
- alpine 基础镜像:~5MB
- 自己打包的带全套工具的Java镜像:几百MB
- 多阶段构建的Java最小镜像:几十MB

核心手段:**多阶段构建(multi-stage build)**
> 构建阶段:下载依赖、编译代码;运行阶段:只拷贝编译产物,不带编译器、源码、包管理器。

## 二、实战1:多阶段构建 SpringBoot 最小镜像
项目目录

demo/

├── Dockerfile

└── target/demo.jar

复制代码
`Dockerfile`
```dockerfile
# 阶段1:编译构建(只在构建时生效,最终镜像不会保留这一层)
FROM maven:3.8-openjdk-17 AS builder
WORKDIR /app
COPY pom.xml .
# 提前下载依赖,缓存优化
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests

# 阶段2:运行镜像,使用轻量alpine jre
FROM openjdk:17-jre-alpine
WORKDIR /app
# 从构建阶段拷贝打好的jar包,其余构建内容全部丢弃
COPY --from=builder /app/target/*.jar app.jar
# 新增普通用户,不使用root
RUN addgroup -g 1001 appgroup && adduser -G appgroup -g "app user" -u 1001 -s /bin/sh -D appuser
# 切换到普通用户
USER appuser
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]

构建命令

复制代码
docker build -t spring-mini:v1 .
# 查看镜像大小
docker images | grep spring-mini

对比:传统单阶段构建镜像体积会大很多,多阶段构建直接剥离编译环境。

三、实战 2:镜像漏洞扫描(trivy)

生产上线前,必须扫描镜像高危漏洞。Trivy 是轻量容器漏洞扫描工具。

安装 & 扫描命令

复制代码
# 安装trivy(Linux)
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh

# 扫描本地镜像
trivy image spring-mini:v1

扫描结果重点看:CRITICAL(严重)、HIGH(高危)漏洞。

alpine 镜像的漏洞数量远小于 ubuntu/centos 基础镜像。

四、为什么不要容器 root?

默认容器内进程是 root,如果服务存在代码执行漏洞,攻击者拿到容器 root。

在开启特权模式情况下,可以逃逸拿到宿主机权限。

最佳实践:业务容器一律使用普通用户运行。

额外限制:docker-compose 强制非 root

在 compose 文件中指定用户 ID,进一步约束

复制代码
services:
  demo-app:
    image: spring-mini:v1
    # 指定uid,和Dockerfile创建用户保持一致
    user: "1001:1001"
    ports:
      - "8080:8080"

五、额外避坑清单

  1. alpine 使用 musl libc,部分二进制程序(如某些 glibc 编译程序)会无法运行,这时改用debian-slim
  2. 非 root 用户没有权限绑定 1024 以下端口(80、443),业务服务尽量监听 1024 以上端口,前端由 Nginx 代理
  3. 不要在镜像内保存密钥、密码、token!敏感配置通过环境变量 / Secret 注入
  4. 不要使用latest标签,固定版本,防止拉取镜像时意外更新

小结

  • 多阶段构建:分离编译环境和运行环境,减小镜像体积,减少漏洞
  • 业务容器强制使用普通用户运行,降低容器逃逸风险
  • 上线前使用 Trivy 扫描镜像高危漏洞

下一篇预告:Docker 进阶实战系列(二):容器日志驱动与日志轮转,防止日志打满宿主机磁盘

相关推荐
Xudde.1 小时前
CVE-2026-24061漏洞复现
学习·安全
天衍四九-1 小时前
Docker进阶实战系列(二):容器日志深度治理|驱动配置、自动切割、磁盘爆满彻底解决
docker·容器·eureka
howdoyoudo2026062 小时前
当新案例冲击旧框架:分类系统的宿命与修正路径
大数据·网络·数据库·人工智能·安全·ai·分类
ccstuck2 小时前
AI安全系列:开源RAG系统测试
人工智能·安全·开源·ai安全
sbjdhjd2 小时前
云安全 | Docker 容器逃逸复盘(一):从隔离边界到运行时链路,如何确认自己身处容器
网络安全·docker·云原生·容器·kubernetes·云计算·云安全
溪语流沙2 小时前
【Web全栈进阶】PostgreSQL上手:Docker跑库 + 把早报站从SQLite迁过去
前端·docker·postgresql
Cheney Pan2 小时前
第13篇 监控安全与权限治理
安全·prometheus
MicrosoftCloud12 小时前
用户权限 04|/etc/sudoers 安全配置:从最小授权到「别把 ALL 随便给人」
运维·安全·ubuntu·sudo·sudoers
梦想不只是梦与想12 小时前
docker-compose.yml
docker·docker-compose·docker run