易君召
易君召
发布于 2026-07-26 / 1 阅读
0
0

Dockerfile 完整构建镜像教程(从语法到实战、推送私服)

一、基础概念

  1. Dockerfile:纯文本脚本,定义镜像的构建步骤、环境、依赖、启动命令

  2. 镜像 (image):Dockerfile 构建出的只读模板

  3. 容器 (container):镜像运行后的实例

  4. 构建命令docker build 读取 Dockerfile 生成镜像

二、Dockerfile 核心常用指令

指令

作用

示例

FROM

必须第一行,指定基础镜像

FROM openjdk:17-jdk-slim

WORKDIR

容器内工作目录(自动创建)

WORKDIR /app

COPY

本地文件复制到容器

COPY target/demo.jar app.jar

ADD

类似 COPY,额外支持自动解压 tar、远程 URL

ADD app.tar.gz /app/

RUN

构建阶段执行命令(安装依赖)

RUN apt update && apt install -y curl

ENV

设置环境变量

ENV SPRING_PROFILES_ACTIVE=prod

EXPOSE

声明容器暴露端口(仅文档,不会自动映射)

EXPOSE 8080

ENTRYPOINT

容器启动入口程序(不可被命令覆盖)

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

CMD

容器默认启动参数,可被 docker run 覆盖

CMD ["--server.port=8080"]

VOLUME

声明持久化数据卷目录

VOLUME /app/logs

USER

指定运行容器的用户(避免 root 权限风险)

USER appuser

关键区分: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"]

五、构建镜像常用优化技巧

  1. 分层缓存优化

    频繁变动的文件放后面,不变依赖文件先 COPY,构建时复用缓存。

    例:先复制 pom 下载依赖,再复制源码。

  2. 使用轻量基础镜像

    优先 alpine 极简版(nginx:alpine、openjdk-slim),比完整版小数倍。

  3. 多阶段构建剔除编译工具

    不把 maven、git、编译器打进最终运行镜像。

  4. 容器使用非 root 用户运行

    避免容器提权风险:

    dockerfile

    RUN addgroup --system app && adduser --system app --ingroup app
    USER app
    
  5. 合并 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(完整流程)

  1. 给镜像打私服标签(仓库地址 / 项目 / 镜像名:版本)

bash

docker tag demo:1.0 harbor.local/library/demo:1.0
  1. 登录 Harbor 私服

bash

docker login harbor.local
  1. 推送镜像

bash

docker push harbor.local/library/demo:1.0

七、常见报错排查

  1. COPY failed: no such file or directory

    本地文件路径错误,构建上下文目录不对,jar 包未编译生成。

  2. 端口无法访问

    EXPOSE 仅声明,docker run 必须 -p 宿主机端口:容器端口 端口映射。

  3. 镜像体积过大

    改用多阶段构建、alpine 轻量基础镜像、清理安装缓存。

  4. 构建一直使用旧缓存

    增加参数 --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


评论