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