Docker 在 Java 开发中的实践与应用:解锁高效容器化部署新姿势

发布于:2025-02-11 ⋅ 阅读:(14) ⋅ 点赞:(0)

一、引言

在当下竞争激烈、技术迭代迅速的软件开发领域,如何实现高效、稳定的应用部署与运维,一直是开发者们重点关注的问题。容器化技术的兴起,为这一难题提供了创新的解决方案,而 Docker 无疑是其中的佼佼者。对于 Java 开发者而言,Docker 凭借其轻量级、可移植性和高效性等显著特性,重塑了 Java 应用的开发、部署和运维流程,带来了前所未有的便利与优势。本文将深入探讨 Docker 在 Java 项目中的具体实践应用,通过丰富的实际案例,全面展示 Docker 在 Java 开发场景中的强大功能与无限潜力。

二、Docker 基础概念回顾

(一)什么是 Docker

Docker 是一个开源的应用容器引擎,它允许开发者将应用程序及其依赖项打包到一个可移植的容器中,然后发布到任何支持 Docker 的操作系统上运行。简单来说,Docker 就像是一个超级 “集装箱”,把应用程序和它运行所需要的各种环境都装在一起,无论在何种环境下运输和使用,都能保证内部的应用程序稳定运行。

(二)Docker 的核心组件

  1. 镜像(Image):是一个只读的模板,包含了运行应用程序所需的所有内容,如代码、运行时环境、库、依赖项等。可以把镜像想象成一个应用程序的 “快照”,通过它可以快速创建容器。
  2. 容器(Container):是镜像的运行实例。当从镜像创建一个容器时,就相当于启动了一个独立的应用程序运行环境。容器之间相互隔离,互不干扰,并且可以在不同的主机之间轻松迁移。
  3. 仓库(Repository):是存储镜像的地方。可以将自己创建的镜像上传到仓库中,也可以从仓库中下载别人分享的镜像。常见的公共仓库有 Docker Hub,同时也可以搭建私有的仓库。

三、Docker 实践步骤

(一)安装 Docker

Docker 支持在多种操作系统上安装,以下以 CentOS 7 系统为例,详细介绍其安装步骤:

1、检查内核版本

Docker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10 。可通过以下命令检查当前系统内核版本:

uname -r

若内核版本低于 3.10,建议先进行内核升级。

2、更新 yum 包:

使用 root 权限对 yum 包进行更新,执行命令:

yum -y update

yum -y update命令会升级所有包,同时也升级软件和系统内核;而yum -y upgrade只升级所有包,不升级软件和系统内核。

3、卸载旧版本(可选):

如果之前已经安装过 Docker 旧版本,可以执行以下命令卸载:

yum remove docker docker-common docker-selinux docker-engine

 4、安装所需软件包:

安装yum-utils,它提供yum-config-manager功能,另外两个则是devicemapper驱动依赖,执行命令:

yum install -y yum-utils device-mapper-persistent-data lvm2

安装成功后,会显示相关软件包的安装信息。

5、设置 yum 源:

可以选择官方源或者国内镜像源,如阿里云镜像源,以提高下载速度。

使用官方源命令:

yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo

使用阿里云源命令:

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

 6、查看 Docker 版本:

设置好 yum 源后,可以查看有哪些可用的 Docker 版本,执行命令:

yum list docker-ce --showduplicates | sort -r

该命令会列出所有可用的 Docker 社区版版本,并按版本号从高到低排序展示。

7、 安装 Docker:

选择一个版本进行安装,例如安装docker-ce-24.0.6版本(版本号可根据实际需求选择),执行命令:

yum -y install docker-ce-24.0.6

安装过程中,系统会自动下载并安装 Docker 及其依赖项,安装完成后会显示安装成功信息。

8、启动 Docker 并设置开机自启:

安装完成后,启动 Docker 服务,并设置其开机自动启动,执行命令:

systemctl start docker # 启动Docker

systemctl enable docker # 开启开机自启模式

9、验证安装结果

通过以下命令验证 Docker 是否安装成功:

docker version

如果输出信息中包含 Client 和 Server 的相关版本信息,说明 Docker 已经成功安装并可以正常工作。也可以运行以下命令进行测试:

sudo docker run hello-world

若看到输出了一些关于 Docker 的信息和一个 “Hello from Docker!” 的提示,同样表明安装成功。

在其他操作系统上安装 Docker 的步骤会有所不同,如 Ubuntu 系统,可参考前文提到的 Ubuntu 安装步骤,或者查阅 Docker 官方文档获取更详细准确的安装指导。

(二)拉取镜像

在使用 Docker 之前,需要先从仓库中拉取所需的镜像。例如,拉取一个官方的 Java 镜像:

sudo docker pull openjdk:11

这条命令会从 Docker Hub 上下载最新版本的 OpenJDK 11 镜像到本地。

(三)创建并运行容器

有了镜像之后,就可以创建容器并运行它。以下是使用刚才拉取的 Java 镜像创建并运行一个简单容器的命令示例,这里假设我们已经将一个 Java 的 HelloWorld.class 文件准备好,并挂载到容器内运行:

sudo docker run -it -v /host/path/to/HelloWorld.class:/app/HelloWorld.class openjdk:11 java -cp /app HelloWorld

参数解释:

  • -it:以交互模式运行容器,通常用于需要用户输入或查看实时输出的情况。
  • -v /host/path/to/HelloWorld.class:/app/HelloWorld.class:将主机上的 HelloWorld.class 文件挂载到容器内的 /app 目录下。
  • openjdk:11:指定使用的 Java 镜像。
  • java -cp /app HelloWorld:在容器内执行 Java 命令,运行 HelloWorld 类。

四、Docker 应用举例

(一)Spring Boot 应用部署

假设我们有一个简单的 Spring Boot 应用,项目结构如下:

my-spring-boot-app
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           └── myapp
│   │   │               ├── controller
│   │   │               │   └── HelloController.java
│   │   │               └── MyAppApplication.java
│   │   └── resources
│   │       ├── application.properties
│   │       └── static
│   │           └── index.html
│   └── test
│       └── java
│           └── com
│               └── example
│                   └── myapp
│                       └── MyAppApplicationTests.java
├── pom.xml

其中HelloController.java代码如下:

package com.example.myapp.controller;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

public class HelloController {

    @GetMapping("/")

    public String hello() {

    return "Hello, Docker with Spring Boot!";

    }

}

MyAppApplication.java代码如下:

package com.example.myapp;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class MyAppApplication {

    public static void main(String[] args) {

        SpringApplication.run(MyAppApplication.class, args);

    }

}

1、创建 Dockerfile:在项目根目录下创建一个名为Dockerfile的文件,内容如下:

# 使用OpenJDK 11作为基础镜像

FROM openjdk:11

# 设置工作目录

WORKDIR /app

# 复制项目的JAR包到容器内

COPY target/my-spring-boot-app-0.0.1-SNAPSHOT.jar /app/app.jar

# 暴露端口

EXPOSE 8080

# 定义容器启动时执行的命令

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

2、构建项目:在项目根目录下执行mvn clean package命令,生成可执行的 JAR 包。

3、构建镜像:在项目根目录下执行以下命令构建镜像:

sudo docker build -t my-spring-boot-app.

其中,-t参数用于指定镜像的标签(名称和版本),my-spring-boot-app是我们给镜像取的名字,最后的.表示当前目录,即 Dockerfile 所在的目录。

4、运行容器:构建镜像成功后,就可以运行容器了:

sudo docker run -d -p 8080:8080 my-spring-boot-app

通过浏览器访问http://localhost:8080,就可以看到 “Hello, Docker with Spring Boot!” 的页面,说明我们的 Spring Boot 应用已经成功部署在 Docker 容器中。

(二)多容器应用(以 Java Web 应用和 MySQL 为例)

很多 Java 应用场景需要与数据库协同工作。例如,部署一个简单的 Java Web 应用,使用 MySQL 作为数据库。

1、拉取 MySQL 镜像并运行容器

sudo docker run -d \

--name my-mysql \

-e MYSQL_ROOT_PASSWORD=rootpassword \

-e MYSQL_DATABASE=javadb \

-e MYSQL_USER=javauser \

-e MYSQL_PASSWORD=javapassword \

-p 3306:3306 \

mysql:5.7

参数解释:

  • -e参数用于设置环境变量,这里设置了 MySQL 的 root 密码、数据库名、用户名和用户密码。
  • -p 3306:3306将容器内部的 MySQL 端口 3306 映射到主机的 3306 端口。

2、假设我们有一个 Spring Boot 的 Java Web 应用,接入 MyBatis-Plus 后,项目结构如下:

my-java-web-app
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           └── mywebapp
│   │   │               ├── config
│   │   │               │   └── MyBatisPlusConfig.java
│   │   │               ├── controller
│   │   │               │   └── UserController.java
│   │   │               ├── entity
│   │   │               │   └── User.java
│   │   │               ├── mapper
│   │   │               │   └── UserMapper.java
│   │   │               ├── service
│   │   │               │   ├── impl
│   │   │               │   │   └── UserServiceImpl.java
│   │   │               │   └── UserService.java
│   │   │               └── MyWebAppApplication.java
│   │   └── resources
│   │       ├── application.properties
│   │       ├── mapper
│   │       │   └── UserMapper.xml
│   │       └── static
│   │           └── index.html
│   └── test
│       └── java
│           └── com
│               └── example
│                   └── mywebapp
│                       └── MyWebAppTests.java
├── pom.xml

3、添加依赖:

在pom.xml文件中添加 MyBatis-Plus 和相关依赖:

<dependencies>

<!-- Spring Boot Starter -->

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>


<!-- MyBatis-Plus Starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>最新版本号</version>
</dependency>


<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>


<!-- 其他依赖... -->

</dependencies>

​​​​​​​​​​​​​​4、配置文件:

在application.properties中添加数据库连接和 MyBatis-Plus 相关配置:

# 数据库连接配置
spring.datasource.url=jdbc:mysql://mysql:3306/javadb?useSSL=false&characterEncoding=utf8
spring.datasource.username=javauser
spring.datasource.password=javapassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# MyBatis-Plus配置
mybatis-plus.mapper-locations=classpath:/mapper/*.xml
mybatis-plus.type-aliases-package=com.example.mywebapp.entity

​​​​​​​5、代码实现:

  • User.java实体类:
package com.example.mywebapp.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("users")
public class User {

private Integer id;

private String name;

}
  • UserMapper.java接口:
package com.example.mywebapp.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mywebapp.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {

}
  • IUserService.java接口:
package com.example.mywebapp.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.mywebapp.entity.User;

public interface IUserService extends IService<User> {

}
  • UserServiceImpl.java实现类:
package com.example.mywebapp.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mywebapp.entity.User;
import com.example.mywebapp.mapper.UserMapper;
import com.example.mywebapp.service.IUserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

}
  • UserController.java控制器:
package com.example.mywebapp.controller;

import com.example.mywebapp.entity.User;
import com.example.mywebapp.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

@Autowired
private UserService userService;

    @GetMapping("/user")
    public User getUser(@RequestParam Integer id) {
        return userService.getById(id);
    }

}
  • MyBatisPlusConfig.java配置类(可选,用于自定义 MyBatis-Plus 配置):
package com.example.mywebapp.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.example.mywebapp.mapper")
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }

}

6、创建 Dockerfile:在项目根目录下创建一个名为Dockerfile的文件,内容如下:

# 使用Tomcat 9作为基础镜像
FROM tomcat:9.0

# 设置工作目录
WORKDIR /usr/local/tomcat/webapps

# 复制项目的WAR包到容器内
COPY target/my-java-web-app.war ROOT.war

# 暴露端口
EXPOSE 8080

# 定义容器启动时执行的命令
CMD ["catalina.sh", "run"]

 7、构建项目:在项目根目录下执行mvn clean package命令,生成可执行的 WAR 包。

8、构建镜像:在项目根目录下执行以下命令构建镜像:

sudo docker build -t my-java-web-app.

 9、运行容器:构建镜像成功后,就可以运行容器了:

sudo docker run -d -p 8081:8080 --link my-mysql:mysql my-java-web-app

参数解释:

  • --link my-mysql:mysql:将 Java Web 应用容器与 MySQL 容器建立链接,my-mysql是 MySQL 容器的名称,mysql是链接别名,方便在 Java Web 应用中通过mysql来访问 MySQL 容器。
  • -p 8081:8080:将容器内部的 Tomcat 端口 8080 映射到主机的 8081 端口。

通过浏览器访问http://localhost:8081/user?id=1,就可以看到根据数据库查询结果展示的用户信息页面,这两个容器之间通过网络进行通信,协同工作。

五、总结

通过以上基于 Java 的 Docker 实践和应用举例,我们可以看到 Docker 在简化 Java 应用部署、提高开发效率和实现多容器协作等方面的巨大优势。无论是小型 Java 项目还是大型企业级 Java 应用,Docker 都能为开发者提供便捷、高效的解决方案。随着技术的不断发展,Docker 在 Java 开发领域的应用场景也将越来越广泛,希望本文能为你开启 Docker 在 Java 项目中的探索之旅,让你在容器化的世界中尽情发挥。