docker下载运行java项目的实现步骤
作者:、廾
核心常用参数(开发 / 生产高频)
| 参数 | 作用 | 示例 |
|---|---|---|
| -it | 分配伪终端并保持标准输入打开,实现交互模式(如进入容器终端) | docker run -it ubuntu:20.04 /bin/bash |
| -d | 后台运行容器(守护进程模式),不占用当前终端 | docker run -d nginx:1.25 |
| --name | 为容器自定义名称(默认是随机字符串),方便管理 | docker run -d --name my-nginx nginx |
| -p | 端口映射(宿主机端口:容器内端口),实现外部访问容器 | docker run -d -p 8080:80 nginx |
| -v | 数据卷挂载(宿主机路径:容器内路径),实现数据持久化 / 文件共享 | docker run -d -v /host/html:/usr/share/nginx/html nginx |
| -e | 设置容器内的环境变量 | docker run -d -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0 |
| --network | 指定容器接入的 Docker 网络,实现容器间网络互通 | docker run -d --network app-network mysql:8.0 |
| --restart | 容器重启策略(如 always 异常退出自动重启),适合生产环境 | docker run -d --restart always nginx |
| --rm | 容器停止后自动删除,适合临时测试的容器 | docker run --rm -it ubuntu /bin/bash |
一、基础场景:运行 Java JAR 包项目
在 JAR 包同级目录下创建名为 Dockerfile 的文件(无后缀),内容如下(分基础版和指定 JDK 版本版):
步骤 1:基础版(使用官方 OpenJDK 镜像,自动适配)
# 1. 选择基础镜像:使用官方 OpenJDK 的 JRE 镜像(轻量,仅运行环境) FROM openjdk:8-jre-slim # 若项目用 Java 11,改为 openjdk:11-jre-slim;Java 17 改为 openjdk:17-jre-slim # 2. 维护者信息(可选) MAINTAINER yourname <yourname@example.com> # 3. 创建容器内目录,用于存放 JAR 包 WORKDIR /app # 4. 将本地的 JAR 包复制到容器内的 /app 目录下,并重命名为 app.jar(简化名称) COPY demo-0.0.1-SNAPSHOT.jar /app/app.jar # 5. 暴露项目的端口(如 Spring Boot 项目的 8080 端口,仅声明,不实际映射) EXPOSE 8080 # 6. 容器启动时执行的命令:运行 JAR 包 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
步骤 2:指定具体 JDK 版本(如国产龙蜥 / 华为镜像,适配国产化)
若需要指定更精细的 JDK 版本,或使用国产镜像:
# 使用阿里云的 OpenJDK 镜像(国内速度快) FROM registry.cn-hangzhou.aliyuncs.com/acs/openjdk:8-jre WORKDIR /app COPY demo-0.0.1-SNAPSHOT.jar /app/app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
步骤 3:构建 Docker 镜像
在 Dockerfile 所在目录执行构建命令,<image-name> 为镜像名称(如 java-demo),<tag> 为版本(如 v1.0):
docker build -t <image-name>:<tag> . # 示例:docker build -t java-demo:v1.0 .
- 命令末尾的
.表示当前目录是构建上下文(Docker 会读取该目录下的文件)。 - 构建完成后,执行
docker images可看到新创建的镜像。
步骤 4:启动 Docker 容器
通过镜像启动容器,映射端口(容器内 8080 → 宿主机 8080),并命名容器(可选):
docker run -d -p 8080:8080 --name <container-name> <image-name>:<tag> # 示例:docker run -d -p 8080:8080 --name my-java-app java-demo:v1.0
- 参数说明:
-d:后台运行容器(守护进程模式)。-p 宿主机端口:容器端口:端口映射(关键,外部通过宿主机端口访问)。--name:给容器命名,方便管理。
步骤 5:验证运行结果
- 查看容器状态:
docker ps(若显示容器为Up状态,说明启动成功)。 - 访问项目:浏览器 / Postman 访问
http://宿主机IP:8080(如本地则http://localhost:8080)。 - 查看容器日志:
docker logs <container-name>(排查启动失败问题)。
二、进阶场景:运行 Java WAR 包项目
适用于传统 Java Web 项目(如 SSH/SSM),打包为 WAR 包,需部署到 Tomcat 容器。
步骤 1:准备 WAR 包
将项目打包为 demo.war,放在本地目录(如 ~/java-war-docker/)。
步骤 2:编写 Dockerfile
使用官方 Tomcat 镜像作为基础镜像,将 WAR 包复制到 Tomcat 的 webapps 目录:
# 1. 选择官方 Tomcat 镜像(内置 JRE,可指定版本) FROM tomcat:8.5-jre8-slim # 若用 Tomcat 9,改为 tomcat:9-jre11-slim # 2. 维护者信息(可选) MAINTAINER yourname <yourname@example.com> # 3. 删除 Tomcat 自带的默认项目(可选,清理无用文件) RUN rm -rf /usr/local/tomcat/webapps/* # 4. 将本地 WAR 包复制到 Tomcat 的 webapps 目录 COPY demo.war /usr/local/tomcat/webapps/ROOT.war # 重命名为 ROOT.war,访问时无需加项目名 # 5. 暴露 Tomcat 端口(默认 8080) EXPOSE 8080 # 6. 启动 Tomcat(Tomcat 镜像默认入口命令就是启动脚本,可省略) CMD ["catalina.sh", "run"]
步骤 3:构建并启动容器
# 构建镜像 docker build -t java-war-demo:v1.0 . # 启动容器 docker run -d -p 8080:8080 --name my-war-app java-war-demo:v1.0
步骤 4:验证
访问 http://宿主机IP:8080,即可访问 WAR 包项目(因 WAR 包重命名为 ROOT.war,无需加项目上下文路径)。
三、优化 Docker 镜像(减小体积 + 提升安全性)
上述基础镜像(如 openjdk:8-jre-slim)虽已轻量化,但可进一步优化:
1. 使用更小的基础镜像(Alpine 版本)
Alpine 是轻量级 Linux 发行版,镜像体积仅几 MB:
# Java 8 Alpine 镜像(体积约 80MB,而 slim 版本约 200MB) FROM openjdk:8-jre-alpine # Alpine 缺少时区依赖,需手动安装(解决项目时区问题) RUN apk add --no-cache tzdata ENV TZ=Asia/Shanghai # 设置时区为上海 WORKDIR /app COPY demo-0.0.1-SNAPSHOT.jar /app/app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
2. 非 root 用户运行容器(提升安全性)
默认容器以 root 用户运行,存在安全风险,可创建普通用户:
FROM openjdk:8-jre-alpine # 创建普通用户 appuser RUN addgroup -S appgroup && adduser -S appuser -G appgroup # 切换到普通用户 USER appuser WORKDIR /app COPY demo-0.0.1-SNAPSHOT.jar /app/app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
3. 分层构建(分离编译和运行环境)
适用于需要在容器内编译项目的场景(如源码打包),使用多阶段构建减小镜像体积:
# 第一阶段:编译阶段(使用带 JDK 的镜像,打包源码) FROM maven:3.8.5-openjdk-8 AS builder WORKDIR /src COPY pom.xml . COPY src ./src # 执行 maven 打包(跳过测试) RUN mvn clean package -DskipTests # 第二阶段:运行阶段(仅使用 JRE 镜像,复制编译后的 JAR 包) FROM openjdk:8-jre-alpine WORKDIR /app # 从编译阶段复制 JAR 包到运行阶段 COPY --from=builder /src/target/demo-0.0.1-SNAPSHOT.jar /app/app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
四、常见问题排查
- 容器启动后立即退出:查看日志
docker logs <容器名>,大概率是 JAR 包路径错误、端口被占用或项目代码异常。 - 外部无法访问项目:检查宿主机防火墙是否开放端口,或 Docker 端口映射是否正确(
-p参数)。 - 时区问题:项目中时间显示错误,需在 Dockerfile 中设置时区(如 Alpine 镜像安装
tzdata并指定TZ环境变量)。 - 镜像构建缓慢:使用国内镜像源(如阿里云 Docker 镜像加速器),或更换基础镜像为国内仓库(如阿里云的 OpenJDK/Tomcat 镜像)。
通过以上步骤,即可完成 Java 项目的 Docker 容器化部署,适配绝大多数 Java 项目场景。
五、jdk下载失败问题
方式一:手动下载官方 OpenJDK 17 压缩包(通用所有 Linux 发行版)
这是最通用的安装方式,不受发行版限制,可精准控制安装路径和版本。
一、选择下载源并获取 JDK 17 压缩包
推荐从 OpenJDK 官方镜像 或 Adoptium(Eclipse Temurin) 下载(Adoptium 提供稳定的 OpenJDK 发行版,更推荐)。
- 打开终端,进入下载目录(如
/usr/local/src):cd /usr/local/src
- 下载 OpenJDK 17 压缩包(以 Adoptium 的 Temurin 17 为例,适配 x86_64 架构):
# 下载 x86_64 架构的 Temurin 17 最新版(Linux tar.gz 包) wget https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.11%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.11_9.tar.gz
- 若需其他架构(如 aarch64/ARM)或版本,可访问 Adoptium 官网 复制对应下载链接。
- 若没有
wget,可先安装:apt install wget(Debian/Ubuntu)或yum install wget(CentOS/RHEL)。 - 实在下载不了就外部下载了再传到linux
二、编写 Dockerfile
创建 Dockerfile 文件,内容分为基础镜像选择、JDK 解压配置、项目运行三个部分,核心是将本地 JDK 包复制到容器并配置环境变量。
# 1. 选择基础 Linux 镜像(以轻量的 CentOS 7 为例,也可用 alpine) FROM centos:7 # 2. 维护者信息(可选) MAINTAINER yourname <yourname@example.com> # 3. 创建JDK安装目录,将本地JDK包复制到容器内并解压 RUN mkdir -p /usr/local/jdk COPY jdk-8u361-linux-x64.tar.gz /usr/local/jdk/ RUN cd /usr/local/jdk && tar -zxvf jdk-8u361-linux-x64.tar.gz && rm -rf jdk-8u361-linux-x64.tar.gz # 4. 配置JDK环境变量(容器内生效) ENV JAVA_HOME=/usr/local/jdk/jdk1.8.0_361 # 解压后的JDK实际目录 ENV JRE_HOME=$JAVA_HOME/jre ENV CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib ENV PATH=$JAVA_HOME/bin:$PATH # 5. 创建项目目录,复制Java项目JAR包到容器内 RUN mkdir -p /app COPY demo-0.0.1-SNAPSHOT.jar /app/app.jar # 6. 暴露项目端口(如Spring Boot的8080端口) EXPOSE 8080 # 7. 容器启动时运行JAR包 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
关键说明:
- 若使用 Alpine 基础镜像(更轻量),需替换
FROM centos:7为FROM alpine:3.18,并添加RUN apk add --no-cache tar(Alpine 默认无tar解压工具)。 - 若使用国产 JDK(如华为毕昇 JDK、阿里 Dragonwell),只需替换本地 JDK 包,解压路径和环境变量配置逻辑不变。
三、构建 Docker 镜像
在项目目录(java-docker/)下执行构建命令,指定镜像名称和标签:
docker build -t custom-jdk-java:v1.0 .
-t custom-jdk-java:v1.0:给镜像命名为custom-jdk-java,版本为v1.0。- 末尾的
.:表示 Docker 构建上下文为当前目录(会读取目录下的 JDK 包、JAR 包和 Dockerfile)。
构建过程中,Docker 会依次执行 Dockerfile 中的指令:复制 JDK 包 → 解压 → 配置环境 → 复制项目 JAR 包。构建完成后,执行 docker images 可看到新创建的镜像。
四、启动 Docker 容器
通过构建好的镜像启动容器,映射宿主机端口到容器端口(如 8080):
# 后台启动容器,端口映射 宿主机8080 → 容器8080,命名为my-java-app docker run -d -p 8080:8080 --name my-java-app custom-jdk-java:v1.0
常用参数补充:
-v /host/logs:/app/logs:若项目有日志输出到容器内/app/logs,可通过数据卷挂载到宿主机/host/logs,实现日志持久化。--restart always:配置容器异常退出时自动重启(生产环境推荐)docker run -d -p 8080:8080 -v /host/logs:/app/logs --restart always --name my-java-app custom-jdk-java:v1.0
五、验证运行结果
- 查看容器状态:执行
docker ps,若容器状态为Up,说明启动成功。 - 访问项目:浏览器 / Postman 访问
http://宿主机IP:8080,即可访问 Java 项目。 - 查看容器日志:若启动失败,通过日志排查问题:
docker logs my-java-app # 查看日志 docker logs -f my-java-app # 实时跟踪日志
六、优化方案(可选)
制作自定义 JDK 基础镜像:若多个 Java 项目需要相同的自定义 JDK 环境,可先构建仅包含 JDK 的基础镜像,后续项目直接基于该镜像构建,避免重复解压配置 JDK:
# 构建自定义JDK基础镜像的Dockerfile FROM centos:7 RUN mkdir -p /usr/local/jdk COPY jdk-8u361-linux-x64.tar.gz /usr/local/jdk/ RUN cd /usr/local/jdk && tar -zxvf jdk-8u361-linux-x64.tar.gz && rm -rf *.tar.gz ENV JAVA_HOME=/usr/local/jdk/jdk1.8.0_361 ENV PATH=$JAVA_HOME/bin:$PATH # 构建命令:docker build -t custom-jdk8:v1.0 .
后续项目的 Dockerfile 可直接引用该基础镜像:
dockerfile
FROM custom-jdk8:v1.0 # 引用自定义JDK基础镜像 RUN mkdir -p /app COPY demo-0.0.1-SNAPSHOT.jar /app/app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
精简镜像体积:使用
alpine基础镜像替代centos,并通过jlink工具制作精简版 JRE(仅保留项目所需的 Java 模块),可将镜像体积从几百 MB 压缩到几十 MB。
七、常见问题排查
- JDK 解压路径错误:检查 Dockerfile 中
JAVA_HOME的路径是否与容器内解压后的 JDK 目录一致(可通过docker exec -it 容器ID /bin/bash进入容器查看)。 - 容器启动后立即退出:查看日志
docker logs 容器名,大概率是 JAR 包路径错误、端口被占用或项目代码异常。 - 外部无法访问项目:检查宿主机防火墙是否开放端口,或 Docker 端口映射是否正确(
-p参数)。 - JDK 包复制失败:确保 JDK 包在 Docker 构建上下文目录内,且文件名与 Dockerfile 中一致。
八、进入运行中的容器(状态为 Up)
使用docker exec进入交互终端(推荐)
exec 是 Docker 官方推荐的进入容器的方式,会在容器内启动一个新的 shell 进程,不影响容器原有进程,退出后容器仍正常运行。
# 通用Linux镜像(CentOS/Ubuntu)用 /bin/bash docker exec -it cad120a3ea47 /bin/bash # 若容器是Alpine系统(轻量Linux),需替换为 /bin/sh docker exec -it cad120a3ea47 /bin/sh # 先停止容器 docker stop <容器名或ID> # 删除容器 docker rm <容器名或ID> # 重新运行 docker run [参数] <镜像> # 重命名镜像 # 用原长名称作为标识 docker tag registry.cn-hangzhou.aliyuncs.com/my-namespace/very-long-app-name:v1 myapp:v1 # 也可以用镜像ID作为标识(更快捷) docker tag 8f9b89f23768 myapp:v1 # 删除之前长镜像(不能通过id删除,因为重命名的镜像id都是同一个) docker rmi registry.cn-hangzhou.aliyuncs.com/my-namespace/very-long-app-name:v1
参数说明:
-i:保持标准输入打开,实现交互。-t:为容器分配一个伪终端。cad120a3ea47:容器 ID(也可使用容器名,如my-java-app)。
执行后,终端提示符会变成容器内的格式(如 root@cad120a3ea47:/#),表示已成功进入容器,可执行任意 Linux 命令(如查看环境变量、修改文件等)。
九、jar包替换
当容器启动后,Java 项目的 JAR 包需要频繁修改替换时,无需重新构建镜像或重启容器(可选轻量重启),核心思路是通过Docker 数据卷挂载将宿主机的 JAR 包目录映射到容器内,替换宿主机的 JAR 包后,重启容器内的 Java 进程即可生效。以下是两种主流方案,按「便捷性」和「规范性」划分,适配不同场景:
方案一:数据卷挂载(推荐,最便捷)
这是生产 / 测试环境最常用的方式,提前将宿主机的 JAR 包目录挂载到容器内的 JAR 包路径,后续只需替换宿主机的 JAR 包,重启容器 / 进程即可生效,无需重新构建镜像。
步骤 1:启动容器时挂载数据卷
在docker run命令中通过-v参数将宿主机 JAR 包目录映射到容器内 JAR 包所在目录。假设:
- 宿主机 JAR 包存放路径:
/opt/java-projects/demo.jar - 容器内 JAR 包运行路径:
/app/app.jar
启动容器的命令:
# 后台启动容器,挂载宿主机JAR包到容器内,同时映射端口 docker run -d -p 8080:8080 \ --name my-java-app \ -v /opt/java-projects/demo.jar:/app/app.jar \ # 挂载单个JAR包 custom-jdk-java:v1.0 # 你的镜像名
进阶:挂载整个目录(更适合频繁替换)若需替换多个文件(如配置文件 + JAR 包),可挂载整个目录:
docker run -d -p 8080:8080 \ --name my-java-app \ -v /opt/java-projects/:/app/ # 宿主机目录 → 容器目录 custom-jdk-java:v1.0
此时容器内/app/目录会同步宿主机/opt/java-projects/的所有文件(包括 JAR 包、配置文件)。
步骤 2:替换宿主机的 JAR 包
直接将新的 JAR 包覆盖宿主机的/opt/java-projects/demo.jar(或目录内的 JAR 包):
# 示例:用本地新JAR包替换宿主机的旧包(可通过rz/scp/FTP上传新包) cp /root/new-demo.jar /opt/java-projects/demo.jar
步骤 3:重启容器 / 进程使新 JAR 包生效
JAR 包替换后,需重启 Java 进程才能加载新包,有两种方式:
方式 1:轻量重启容器内的 Java 进程(推荐,不中断容器)
进入容器,找到 Java 进程并杀死,容器会自动重启 Java 进程(需保证容器的启动命令是「前台运行」,如java -jar /app/app.jar)
# 1. 进入容器 docker exec -it my-java-app /bin/bash # 2. 查找Java进程ID ps -ef | grep java # 3. 杀死旧进程(替换为实际PID) kill -9 1 # 容器内的主进程通常是PID 1,杀死后容器会重启主进程 # 4. 退出容器 exit
原理:Docker 容器的主进程退出后会自动重启(若未配置
--restart,需手动启动),而容器的启动命令是运行 JAR 包,因此重启后会加载新的 JAR 包。
方式 2:直接重启容器(更简单,适合测试环境
# 重启容器 docker restart my-java-app
该方式会短暂中断服务,适合测试环境或对服务可用性要求不高的场景。
方案二:通过 Docker Compose 挂载(规范,适合多容器)
若使用docker-compose管理容器,只需在docker-compose.yml中配置volumes挂载,后续替换宿主机 JAR 包后重启服务即可。
步骤 1:编写docker-compose.ym
version: '3.8'
services:
java-app:
image: custom-jdk-java:v1.0
ports:
- "8080:8080"
volumes:
- /opt/java-projects/demo.jar:/app/app.jar # 挂载单个JAR包
# 或挂载整个目录:- /opt/java-projects/:/app/
restart: always # 进程退出后自动重启
container_name: my-java-app
步骤 2:启动服务
docker-compose up -d
步骤 3:替换 JAR 包并重启服务
# 1. 替换宿主机JAR包 cp /root/new-demo.jar /opt/java-projects/demo.jar # 2. 重启服务 docker-compose restart java-app
方案三:不挂载卷(临时替换,适合应急)
若未提前挂载数据卷,可通过docker cp命令直接将新 JAR 包复制到容器内,再重启进程,但该方式替换的 JAR 包会在容器重启后丢失(适合应急场景)。
步骤 1:将新 JAR 包复制到容器内
# 格式:docker cp 宿主机文件 容器名:容器内路径 docker cp /root/new-demo.jar my-java-app:/app/app.jar
步骤 2:重启容器内的 Java 进程或容器
同方案一的步骤 3,重启后新 JAR 包生效。
关键注意事项
容器启动命令必须是前台运行确保 Dockerfile 的
ENTRYPOINT/CMD是前台运行 JAR 包(如ENTRYPOINT ["java", "-jar", "/app/app.jar"]),而非后台运行(如java -jar /app/app.jar &),否则杀死进程后容器不会重启。数据卷挂载的权限问题若容器内的用户不是
root,需给宿主机的 JAR 包 / 目录添加权限:chmod 777 /opt/java-projects/demo.jar # 临时授权 # 或修改目录所属用户(适合生产) chown -R 1000:1000 /opt/java-projects/
避免容器重启后数据丢失仅通过
docker cp替换的 JAR 包会在容器重启后丢失,生产环境必须使用数据卷挂载。配置文件同步若 JAR 包依赖外部配置文件(如
application.yml),可将配置文件也放入挂载目录,实现 JAR 包 + 配置文件的同步替换。
总结
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 数据卷挂载 | 无需重构镜像,永久生效 | 需提前配置挂载 | 生产 / 测试环境(推荐) |
| Docker Compose 挂载 | 规范,适合多容器管理 | 需学习 Compose 配置 | 多容器微服务环境 |
| docker cp 临时替换 | 应急,无需提前配置 | 容器重启后丢失 | 临时应急、测试 |
生产环境优先使用数据卷挂载,既能实现 JAR 包的快速替换,又能保证数据持久化,避免容器重启后配置丢失。
十、容器网络互通,创建自定义网络 app-network 后再连接容器
这是推荐的方式,自定义网络的容器间互通性更好,支持通过容器名直接访问(默认桥接网络也支持,但自定义网络更隔离、更规范)。
步骤 1:创建app-network网络
执行以下命令创建一个桥接模式的自定义网络(Docker 网络默认模式为 bridge):
docker network create app-network
执行后会输出网络的 ID,说明创建成功。可通过以下命令查看所有网络,确认 app-network 已存在:
docker network ls
输出中会包含类似这样的条目:
NETWORK ID NAME DRIVER SCOPE xxxxxxxxx app-network bridge local
步骤 2:将容器连接到app-network网络
现在重新执行连接命令,即可成功将 my-java-app 容器接入该网络:
docker network connect app-network my-java-app
若你还有 MySQL 容器(如 mysql-db),也需将其接入同一网络,实现容器间互通:
docker network connect app-network mysql-db
步骤 3:验证容器是否接入网络
执行以下命令查看 app-network 网络的详细信息,确认容器已接入:
docker network inspect app-network
在输出的 Containers 节点下,能看到 my-java-app 和 mysql-db 容器的信息,说明接入成功。
到此这篇关于docker下载运行java项目的实现步骤的文章就介绍到这了,更多相关docker下载运行java内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
