文章目录
一、Dockerfile到底是个啥?(新人必看)
每次看到同事三行命令就能部署好服务,是不是羡慕得不行?悄悄告诉你,他们的秘密武器就是Dockerfile!这个看起来像普通文本文件的小东西,其实是构建Docker镜像的魔法配方!(敲黑板)
想象一下,你有个万能料理机(Docker引擎),只要把食材清单(Dockerfile)放进去,就能自动做出色香味俱全的大餐(镜像)。最棒的是,这个配方还能分享给其他小伙伴,保证他们做出的味道和你一模一样!
二、Dockerfile结构大拆解
先来看个最简单的例子,感受下它的基本结构:
# 使用官方Python运行时作为父镜像
FROM python:3.9-slim-buster
# 设置工作目录
WORKDIR /app
# 将当前目录内容复制到容器的/app目录
COPY . .
# 安装项目依赖
RUN pip install --no-cache-dir -r requirements.txt
# 声明容器运行时监听的端口
EXPOSE 80
# 定义环境变量
ENV NAME World
# 容器启动时执行的命令
CMD ["python", "app.py"]
(重要提示)每个指令都会生成新的镜像层!所以指令顺序直接影响构建速度和镜像大小!
三、常用指令深度解析(附实战技巧)
1. FROM:你的地基要打牢
FROM ubuntu:20.04
- 一定要指定具体版本号!别用latest(血泪教训)
- 推荐使用Alpine等轻量级基础镜像,比如
python:3.9-alpine
2. RUN:你的操作记录仪
# 错误示范(会产生多余缓存层):
RUN apt-get update
RUN apt-get install -y git
# 正确姿势(合并命令减少层数):
RUN apt-get update && \
apt-get install -y --no-install-recommends git && \
rm -rf /var/lib/apt/lists/*
(超级重要)记得清理安装缓存!否则镜像会像吹气球一样膨胀!
3. COPY vs ADD:文件搬运哪家强?
COPY ./src /app/src # 直接复制本地文件
ADD https://example.com/file.tar.gz /tmp # 会自动解压网络资源
- 日常开发建议用COPY(更透明可控)
- ADD的特殊能力要慎用(可能有意外惊喜)
4. CMD vs ENTRYPOINT:启动命令的哲学
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
- 组合使用时,CMD参数会传给ENTRYPOINT
- 单独使用CMD容易被docker run的参数覆盖
四、高手都在用的编写技巧
1. 多阶段构建:瘦身神器!
# 构建阶段
FROM golang:1.19 AS builder
WORKDIR /go/src/app
COPY . .
RUN go build -o myapp
# 运行阶段
FROM alpine:latest
COPY --from=builder /go/src/app/myapp .
CMD ["./myapp"]
这样最终镜像只有十几MB,比原镜像小了10倍不止!
2. .dockerignore文件:拒绝垃圾文件
创建.dockerignore文件:
.git
node_modules
*.log
.DS_Store
避免把本地垃圾文件打包进镜像(特别是node项目!)
3. 镜像标签管理
构建时加上版本标签:
docker build -t myapp:v1.0 -t myapp:latest .
方便后期回滚和版本追踪
五、真实项目实战演示
假设我们要部署一个Python Flask应用,完整Dockerfile长这样:
# 第一阶段:构建环境
FROM python:3.9-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt
# 第二阶段:运行环境
FROM python:3.9-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
EXPOSE 5000
CMD ["flask", "run", "--host=0.0.0.0"]
这样既安装了依赖,又保持了最终镜像的精简!
六、常见翻车现场汇总
1. 权限问题:
# 错误:直接以root运行
RUN chmod 777 /app
# 正确:创建专用用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser
2. 时区设置:
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
3. 环境变量泄露:
# 错误:在镜像中写死密码
ENV DB_PASSWORD=123456
# 正确:运行时注入
docker run -e DB_PASSWORD=your_pwd
七、性能优化冷知识
-
构建缓存机制:改变顺序会导致缓存失效,把变动少的指令放前面!
-
使用
--no-cache参数定期重建镜像:
docker build --no-cache -t myapp:latest .
- 镜像分析工具:
docker history myapp:latest # 查看各层大小
docker scan myapp:latest # 安全漏洞扫描
八、总结与资源推荐
记住这三个原则,你的Dockerfile就能吊打80%的开发者:
- 越小越好(多用多阶段构建)
- 越明确越好(固定版本号)
- 越安全越好(非root用户运行)
推荐进阶学习:
- 官方最佳实践文档:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
- Dive镜像分析工具:https://github.com/wagoodman/dive
- Hadolint语法检查:https://github.com/hadolint/hadolint
下次看到复杂的Dockerfile时,你会笑着对自己说:“就这?”(手动狗头)
1384

被折叠的 条评论
为什么被折叠?



