源本科技 | 码上会

Dockerfile 实战

2026/04/25
3
0

引言

Dockerfile 是一个文本文件,包含了一组用于构建 Docker 镜像的指令。通过定义基础镜像、添加文件、运行命令等步骤,Dockerfile 允许开发者描述应用的环境和依赖关系。这个文件被 Docker 引擎解释,自动构建出可执行的容器镜像。Dockerfile 的使用简化了应用的打包和分发过程,为容器化应用的部署提供了标准和可重复的方法。

核心概念

  • Dockerfile 是自定义镜像的一套标准化规则

  • Dockerfile 由多条指令构成,文件中的每一条指令都会对应 Docker 镜像中的每一层

镜像分层机制

  • Dockerfile 中的每个指令都会创建一个新的镜像层(执行时会生成临时容器,执行完成后自动销毁)

  • 镜像层会被缓存和复用,后续层基于前序层构建,可大幅提升构建效率

  • 当 Dockerfile 指令被修改、复制的文件发生变化,或构建时指定的变量不同,对应层的缓存会自动失效

  • 某一层镜像缓存失效后,其后续所有层的缓存都会同步失效

  • 容器的修改不会影响原始镜像;若在某一层添加文件,下一层删除该文件,镜像中仍会保留该文件

下面以 Nginx 镜像为例,加深对镜像分层的理解:

编写规范

  • 文件名必须为 Dockerfile(严格区分大小写,推荐大写)

  • Dockerfile 中引用的所有文件,必须与 Dockerfile 位于同一级父目录下

  • Dockerfile 中的相对路径,默认以文件所在目录为根目录

  • 能合并为一行的指令尽量合并,减少镜像层数,提升构建和运行效率

  • 指令大小写不敏感,约定俗成使用大写,提升可读性

  • 非注释行的第一行必须是 FROM 指令

  • 工作目录支持 .dockerignore 隐藏文件,作用与 Git 的 .gitignore 一致,过滤无需上传的文件

常用指令

指令

含义

FROM

指定基础镜像,是构建镜像的起点,必须为第一条非注释指令

LABEL

为镜像添加元数据(替代废弃的 MAINTAINER,推荐使用)

COPY

将本地文件 / 目录复制到镜像内,仅支持本地文件,性能更优

ADD

复制本地文件 / 目录到镜像,支持 URL 远程文件,压缩包会自动解压

RUN

在镜像构建时执行命令,生成新的镜像层

CMD

指定容器启动时的默认命令,仅最后一条生效

EXPOSE

声明容器暴露的端口,仅做说明,不实际映射端口

ENV

设置环境变量,可被后续所有指令调用,容器运行时也生效

WORKDIR

为后续指令指定工作目录,相当于 cd 命令,支持多级目录

ONBUILD

定义作为基础镜像时,被继承后触发执行的命令

USER

指定执行命令的用户或 UID

VOLUME

创建匿名数据卷,实现容器数据持久化

ENTRYPOINT

容器启动执行的入口命令,不可被覆盖,推荐搭配 CMD 使用

ARG

定义构建参数,仅在构建镜像时生效

HEALTHCHECK

配置容器健康检查,监控容器运行状态


构建自定义镜像

本章节以 JDK 17 Java 应用为例,完成从 Dockerfile 编写、镜像构建、上传私有仓库到跨服务器部署的全流程。

前置准备

  • 创建工作目录

mkdir -p /usr/local/docker/myprofile
  • 使用 Maven 打包基于 JDK 17 开发的项目,将生成的 Jar 包上传至上述目录

mvn clean package -Pprod

编写 Dockerfile

采用 OpenJDK 17 官方轻量镜像,适配现代 Java 版本,优化镜像体积与启动性能:

# Version 1.0.0
# 基础镜像:JDK 17 LTS 轻量运行时(当前主流生产版本)
# 第一次构建时会拉取该镜像
# eclipse-temurin:17-jre-alpine
# eclipse-temurin:21-jre-alpine
# eclipse-temurin:25-jre-alpine
FROM eclipse-temurin:17-jre-alpine

# 镜像元数据(替代废弃的 MAINTAINER 指令)
LABEL author="my@gmail.com"
LABEL version="1.0.0"
LABEL description="JDK 17 Java 应用镜像"

# 设置环境变量
ENV WORKPATH /usr/local/java
ENV TZ Asia/Shanghai

# 合并执行命令:设置时区 + 创建工作目录(减少镜像层,提升构建速度)
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
    && mkdir -p $WORKPATH

# 声明数据卷挂载点
VOLUME $WORKPATH

# 复制项目 Jar 包到镜像工作目录
COPY myprofile-0.0.1-SNAPSHOT.jar $WORKPATH/app.jar

# 声明服务暴露端口
EXPOSE 8080

# 设置工作目录
WORKDIR $WORKPATH

# JDK 17 适配启动命令(兼容随机数参数,无废弃配置)
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]

镜像构建与私有仓库上传

构建镜像时直接打上 Harbor 私有仓库标签,方便后续上传:

# 构建 JDK 17 版本镜像
docker build -t 192.168.203.128/library/myprofile:latest .

# 查看构建完成的镜像
docker images

输出示例:

192.168.203.128/library/myprofile   latest    c5b1cfb14d75   3 seconds ago   321MB

登录 Harbor 并上传镜像:

# 非交互方式登录私有仓库
cat /usr/local/docker/pwd/harbor | docker login http://192.168.203.128 --username admin --password-stdin

# 上传镜像到 Harbor
docker push 192.168.203.128/library/myprofile:latest

跨服务器部署镜像

在目标服务器拉取镜像并运行,首次使用需配置 Docker 信任 HTTP 私有仓库

  • 配置 Docker 守护进程

vi /etc/docker/daemon.json
{
  "insecure-registries": ["192.168.203.128"]
}
  • 重载配置并重启 Docker

systemctl daemon-reload 
systemctl restart docker
  • 编写 docker-compose.yml 部署文件

services:
  myprofile:
    image: 192.168.203.128/library/myprofile:latest
    restart: always
    container_name: myprofile
    ports:
      - 8080:8080
    environment:
      DEVOPS_MYSQL_HOST: 192.168.203.128
      DEVOPS_MYSQL_PORT: 3306
      DEVOPS_MYSQL_DATABASE_NAME: crmeb
      DEVOPS_MYSQL_USERNAME: root
      DEVOPS_MYSQL_PASSWORD: 123456
  1. 启动容器并查看日志

# 启动服务
docker-compose up -d

# 实时查看服务日志
docker logs -f myprofile

docker build 命令详解

命令说明

  • docker build 命令基于 Dockerfile 和构建上下文构建镜像

  • 构建上下文:指定路径或 Git 地址中的所有文件集合

  • 构建过程可通过 COPY 指令引用上下文中的任意文件

构建上下文特性

构建上下文支持递归处理,会包含指定目录的所有子目录、Git 仓库的所有子模块。

使用当前目录作为上下文(最常用):

docker build .

执行命令时,Docker 会将本地目录的所有文件发送到 Docker 守护进程,控制台会提示 Sending build context

核心使用建议

  • 不要使用根目录 / 作为构建上下文,会将整个硬盘内容发送到守护进程

  • 推荐使用空目录作为上下文,仅存放 Dockerfile 和必要的构建文件

  • 构建由 Docker 守护进程执行,而非本地 CLI 工具

指令执行规则

  • 守护进程会逐行执行 Dockerfile 指令,每条指令生成一个新镜像层

  • Docker 会自动使用构建缓存加速构建,控制台出现 CACHED 即代表命中缓存

  • 每条指令独立运行,RUN cd /tmp 不会对下一条指令产生影响

常用命令行参数

--file / -f

指定 Dockerfile 路径,不指定则默认读取上下文目录下的 Dockerfile

docker build -f /path/to/Dockerfile .

--tag / -t

指定镜像名称和版本标签,支持同时打多个标签

# 单标签
docker build -t myapp:v1.0.0 .

# 多标签
docker build -t myapp:1.0.2 -t myapp:latest .

--add-host

自定义容器 hosts 映射,支持配置多个

docker build --add-host=docker:10.180.0.1 .

--no-cache

构建时禁用缓存,强制重新构建所有层

docker build --no-cache -t myapp:latest .

--network

指定构建过程中 RUN 指令使用的网络模式

docker build --network host -t myapp:latest .