Docker 实战系列(二):Docker 打包进阶篇:设置系统时区、多阶段构建与非 root 用户优化
上一篇文章中我们手动构建了一个简单的 Python 项目镜像,体验了 Docker 最底层的构建流程。
本篇将继续“纯手撸”思路,介绍进阶优化技巧:
✅ 设置容器时区为上海
✅ 使用多阶段构建优化镜像体积
✅ 避免使用 root 用户,提升容器安全性
一、设置容器时区为上海(Asia/Shanghai)
Alpine 默认不包含时区信息,我们需要安装并配置:
1.1 修改基础镜像 Dockerfile
这是我们原来的基础镜像 Dockerfile:
# 文件:python-base/Dockerfile
FROM alpine:latest
# 安装 python、pip 和时区包
RUN apk add --no-cache python3 py3-pip tzdata
# 设置时区为上海
ENV TZ=Asia/Shanghai
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
# 创建运行目录
WORKDIR /opt/app
CMD ["python3"]
1.2 重新构建基础镜像
cd python-base
docker build -t mypython-base:1.1 .
🔁 **注意版本号要更新!**比如从
mypython-base:1.0
升级为mypython-base:1.1
二、多阶段构建(multi-stage build)
多阶段构建的核心思想是:构建与运行分离。
例如有些构建需要额外依赖(如 gcc、make、dev headers),但这些工具在运行阶段并不需要,可以从最终镜像中去掉,减小体积。
我们用一个包含 C 扩展的 Python 包来模拟:比如 cryptography
。
2.1 示例:使用多阶段构建的应用 Dockerfile
# 文件:myapp/Dockerfile
# -------- 阶段1:构建依赖(包含构建工具)--------
FROM mypython-base:1.1 as builder
# 安装构建依赖包
RUN apk add --no-cache gcc musl-dev libffi-dev openssl-dev
WORKDIR /build
COPY requirements.txt .
# 安装依赖到临时目录(非全局)
RUN pip3 install --prefix=/python_deps -r requirements.txt
# -------- 阶段2:运行镜像 --------
FROM mypython-base:1.1
# 拷贝构建好的依赖到最终镜像
COPY --from=builder /python_deps /usr/local
WORKDIR /opt/app
COPY . .
EXPOSE 8080
CMD ["python3", "app.py"]
2.2 构建最终应用镜像
docker build -t myflask-app:2.0 .
体积更小、更安全、不带编译工具。
三、使用非 root 用户运行服务
默认情况下,Docker 中的进程以 root 身份运行,带来安全隐患。我们可以添加普通用户并切换运行身份:
3.1 修改应用镜像 Dockerfile
# 在 myflask-app Dockerfile 第二阶段中添加这些命令
# 添加一个非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# 切换到该用户
USER appuser
# (保持 WORKDIR 在 /opt/app,不需要 chown,Alpine 默认用户有权限)
注意:不能将 WORKDIR 设置为
/root
,因为该用户没有权限。
重新构建并运行:
docker build -t myflask-app:2.1 .
docker run -d -p 8080:8080 myflask-app:2.1
四、完整目录结构参考
最终你的目录结构可能如下:
project/
├── python-base/
│ └── Dockerfile # 构建带时区的 Python 基础镜像
├── myapp/
│ ├── app.py
│ ├── requirements.txt
│ └── Dockerfile # 多阶段构建 + 非 root 优化
五、小结:进阶优化清单
六、后续可扩展方向
你还可以继续优化:
- 使用
.dockerignore
排除不必要文件(如.git
、pycache
) - 集成
healthcheck
检测容器健康状态 - 将镜像发布到 DockerHub 或私有仓库
- 在 Kubernetes 中部署该容器
结语
💬 重点提醒 :喜欢请加关注哦 !
📣 更多原创内容、技术干货,欢迎关注「键上江湖」公众号,与你一键相逢!