Skip to content

Docker 通过 Dockerfile 构建 JAVA 应用镜像

编写 Dockerfile

  • ARG: 构建参数
    • 功能:用于定义仅在 镜像构建阶段 有效的变量,可通过 --build-arg 动态赋值。
    • 语法:ARG 变量名[=默认值](默认值可省略,但未赋值时构建会失败)。
    • 作用域:仅在定义后的当前构建阶段有效,多阶段构建需分阶段重复声明。
    • 使用场景:动态指定基础镜像版本、应用名称、应用版本等。
  • ENV:环境变量
    • 功能:设置 构建阶段和容器运行时 均有效的环境变量,持久化到镜像中。
    • 语法:ENV 变量名=值 或 ENV 变量名1=值1 变量名2=值2...。
    • 作用域:全局生效,支持在后续指令(如 RUN、CMD)及容器内通过 printenv 查看。
    • 使用场景:配置容器运行时环境、与 ARG 结合,将构建参数转为持久化变量等。
    • 注意:
      • 变量引用:支持引用已定义的 ENV 变量(如 ENV A=1 B=$A)。
      • 覆盖规则:ENV 会覆盖同名的 ARG 变量。
      • 运行时修改:可通过 docker run --env 覆盖镜像中的 ENV 值。
  • 最佳实践
    • 敏感数据:优先使用 ENV 而非 ARG,避免通过构建历史泄露信息。
    • 多阶段构建:需在每个阶段重新声明 ARG。
    • 组合使用:可灵活使用 ENV 与 ARG 结合,将构建参数转为持久化变量。
Dockerfile
FROM openjdk:17

LABEL maintainer="Meng Wei Jin"

# 编码
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 
# 容器运行时环境
# ENV PATH=/usr/local/bin:$PATH

# 声明 JVM 参数
ENV JVM_OPTS="-Dserver.port=8080 -Dspring.profiles.active=dev -Duser.timezone=Asia/Shanghai -Xms128m -Xmx512m"

ENV JAR="app.jar"

ENV DIR=/opt/app

# 设置时区(中国区)
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone 

# 创建挂载目录 
VOLUME ${DIR}

# 设置工作目录
WORKDIR ${DIR}

EXPOSE 8080

# 推荐使用 exec 格式(数组形式)而非 shell 格式,以避免参数解析问题
ENTRYPOINT ["sh", "-c", "java ${JVM_OPTS} -jar ${JAR}"]

构建镜像

把 Dockerfile 文件放到安装了 docker 的主机上,比如:/home/docker_build/Dockerfile

shell
# docker build 命令语法格式
docker build --build-arg <变量名1>=<1> --build-arg <变量名2>=<2> -t <镜像>:<> .

构建

shell
# 进入 Dockerfile 所在的文件目录下
cd /home/docker_build

docker build -t openjdk-runner:17 .

# 查看构建好的镜像
docker images

使用镜像

格式

shell
docker run \
--name <容器名> \
-p 8080:8080 \
--restart=on-failure:3 \
-e JVM_OPTS="-Dserver.port=8080 -Dspring.profiles.active=h2 -Duser.timezone=Asia/Shanghai -Xms128m -Xmx512m" \
-e JAR="vita-admin-1.0.0-SNAPSHOT.jar" \
-v /opt/<挂载目>/:/opt/app/ \
-d openjdk-runner:17

示例:

把 vita-admin-1.0.0-SNAPSHOT.jar 放到 /opt/vita/ 目录下,授文件夹权限 755。

shell
cd /opt

mkdir vita

chmod -R 755 /opt/vita

# 已推送的镜像
docker run --name vita -p 9006:8080 --restart=on-failure:3 \
--network network_default \
-e JVM_OPTS="-Dserver.port=8080 -Dspring.profiles.active=h2 -Duser.timezone=Asia/Shanghai -Xms64m -Xmx512m" \
-e JAR="vita-admin-1.0.0-SNAPSHOT.jar" \
-v /opt/vita/:/opt/app/ \
-d registry.cn-hangzhou.aliyuncs.com/mengweijin/openjdk-runner:17

检查 docker run -e 参数在运行时是否被正确覆盖

shell
docker inspect --format='{{.Config.Env}}' <container_id>

docker inspect --format='{{.Config.Env}}' vita

验证时区

shell
# 进入容器
docker exec -it vita /bin/sh

# 检查系统时区(应显示 CST 时间)
date

Fri Feb 28 04:01:01 PM CST 2020

推送到阿里仓库

shell
# 登录
docker login --username=mengweijin@aliyun.com registry.cn-hangzhou.aliyuncs.com

docker tag 1fb854a5d2a9 registry.cn-hangzhou.aliyuncs.com/mengweijin/openjdk-runner:17

docker push registry.cn-hangzhou.aliyuncs.com/mengweijin/openjdk-runner:17

docker rmi -f 1fb854a5d2a9

docker run --rm 参数

docker run --rm 是 Docker 中用于自动清理容器的关键参数,适用于短期运行任务。以下是详细说明:

  1. 核心作用
    • 自动删除容器:容器停止运行后,自动删除容器及其匿名数据卷(anonymous volumes),避免残留无用容器。
    • 等价操作:相当于容器退出后手动执行 docker rm -v。
  2. 适用场景
    • 临时任务:适合调试、测试、单次命令执行(如编译、运行脚本)等场景,避免手动清理。
    • Foreground 模式:默认前台运行(非 -d 后台模式),容器退出时立即触发清理。
  3. 使用限制
    • 与 -d 冲突:不能与后台模式 (-d) 同时使用,否则 --rm 失效。
    • 数据卷处理:
      • 匿名卷:自动删除(如 -v /path 未命名卷)。
      • 命名卷:保留数据(如 -v my_volume:/path)。
  4. 生产环境慎用:正式环境需保留数据时,避免使用 --rm。
    • 调试辅助:结合 -it 进入交互式终端调试后自动清理。
    • 日志与状态:使用 --rm 后,docker ps -a 无法查到已退出的容器。
shell
# 进入容器(格式)
docker run -it --rm <镜像名>:<镜像版> /bin/sh