一、基础概念
Dockerfile:纯文本脚本,定义镜像的构建步骤、环境、依赖、启动命令
镜像 (image):Dockerfile 构建出的只读模板
容器 (container):镜像运行后的实例
构建命令:
docker build读取 Dockerfile 生成镜像
二、Dockerfile 核心常用指令
关键区分:ENTRYPOINT + CMD
ENTRYPOINT:固定执行程序
CMD:给程序传默认参数
运行时传参覆盖 CMD:
bash
docker run demo-image --server.port=8081
三、标准构建流程(分 3 步)
步骤 1:编写 Dockerfile
新建文件名为 Dockerfile(无后缀,首字母大写)
示例 1:SpringBoot Java 项目(生产常用)
dockerfile
# 1. 基础JDK镜像
FROM openjdk:17-jdk-slim
# 2. 设置工作目录
WORKDIR /app
# 3. 复制本地jar包到容器
COPY target/demo-0.0.1.jar app.jar
# 4. 声明对外端口
EXPOSE 8080
# 5. 容器启动命令
ENTRYPOINT ["java", "-jar", "app.jar"]
# 启动默认参数
CMD ["--spring.profiles.active=prod"]
示例 2:Nginx 静态页面
dockerfile
FROM nginx:alpine
# 复制本地html到nginx网页目录
COPY ./html /usr/share/nginx/html
# 复制自定义nginx配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
步骤 2:构建镜像 docker build
基础语法
bash
docker build [参数] 构建上下文目录
构建上下文:
Dockerfile所在文件夹(.代表当前目录)-t:给镜像打标签(名称:版本,规范写法)
常用构建命令
bash
# 1. 最简构建,当前目录Dockerfile,命名demo:1.0
docker build -t demo:1.0 .
# 2. 指定非标准文件名(文件名为Dockerfile-prod)
docker build -f Dockerfile-prod -t demo:prod .
# 3. 构建时传入环境变量(Dockerfile中用ARG接收)
docker build --build-arg VERSION=1.0 -t demo:1.0 .
# 4. 不使用缓存构建(每次完整重新构建,解决缓存污染)
docker build --no-cache -t demo:1.0 .
ARG 构建参数示例(Dockerfile)
dockerfile
FROM openjdk:17-jdk-slim
# 接收构建传入参数
ARG JAR_VERSION
COPY target/demo-${JAR_VERSION}.jar app.jar
步骤 3:运行镜像验证容器
bash
# 后台启动容器,映射8080端口
docker run -d -p 8080:8080 --name demo-container demo:1.0
# 查看运行容器
docker ps
# 查看容器日志
docker logs demo-container
四、多阶段构建(Multi-stage,生产必备,减小镜像体积)
问题:直接用 JDK 镜像打包会包含 Maven/Gradle 源码、编译工具,镜像几百 MB;多阶段构建编译和运行分离,最终镜像仅保留运行环境,体积大幅缩小。
SpringBoot 多阶段 Dockerfile 完整示例
dockerfile
# ========== 第一阶段:编译打包(构建阶段,临时镜像) ==========
FROM maven:3.9-openjdk-17 AS builder
WORKDIR /build
# 先复制pom,缓存maven依赖(优化构建速度)
COPY pom.xml .
RUN mvn dependency:go-offline
# 复制源码打包
COPY src ./src
RUN mvn clean package -DskipTests
# ========== 第二阶段:运行镜像(最终产出镜像,无编译工具) ==========
FROM openjdk:17-jdk-slim
WORKDIR /app
# 从编译阶段复制打好的jar包
COPY --from=builder /build/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
五、构建镜像常用优化技巧
分层缓存优化
频繁变动的文件放后面,不变依赖文件先 COPY,构建时复用缓存。
例:先复制 pom 下载依赖,再复制源码。
使用轻量基础镜像
优先
alpine极简版(nginx:alpine、openjdk-slim),比完整版小数倍。多阶段构建剔除编译工具
不把 maven、git、编译器打进最终运行镜像。
容器使用非 root 用户运行
避免容器提权风险:
dockerfile
RUN addgroup --system app && adduser --system app --ingroup app USER app合并 RUN 指令减少镜像层数
每一条 RUN 会生成一层镜像,多条命令用
&&合并:dockerfile
# 推荐 RUN apt update && apt install -y curl vim && rm -rf /var/lib/apt/lists/* # 不推荐(两层镜像,体积更大) RUN apt update RUN apt install curl
六、镜像推送至私有仓库 Harbor(完整流程)
给镜像打私服标签(仓库地址 / 项目 / 镜像名:版本)
bash
docker tag demo:1.0 harbor.local/library/demo:1.0
登录 Harbor 私服
bash
docker login harbor.local
推送镜像
bash
docker push harbor.local/library/demo:1.0
七、常见报错排查
COPY failed: no such file or directory本地文件路径错误,构建上下文目录不对,jar 包未编译生成。
端口无法访问
EXPOSE 仅声明,
docker run必须-p 宿主机端口:容器端口端口映射。镜像体积过大
改用多阶段构建、alpine 轻量基础镜像、清理安装缓存。
构建一直使用旧缓存
增加参数
--no-cache重新构建。
八、完整实操总结命令
# 1. 编写Dockerfile
# 2. 构建镜像
docker build -t demo:1.0 .
# 3. 本地测试运行
docker run -d -p 8080:8080 demo:1.0
# 4. 打私服标签并推送
docker tag demo:1.0 harbor.local/library/demo:1.0
docker push harbor.local/library/demo:1.0