IDEA使用Docker
安装docker插件
先确定是否安装docker插件:File → Settings... 找到plugins,在中间栏搜索"docker",如果没安装则安装,如果已经安装了就不用再次安装

服务器上开启docker远程访问
编辑docker配置文件
vi /lib/systemd/system/docker.service
添加以下内容
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375

重启docker服务
systemctl daemon-reload
systemctl restart docker
开启2375端口
firewall-cmd --zone=public --add-port=2375/tcp --permanent
systemctl restart firewalld.service
新建连接
IDEA中 File → Settings...

指定docker的URL

点击"OK"完成创建,创建完毕之后会在IDEA的Services选项卡中出现docker信息

在Docker上右键 → Connect连接Docker

SpringBoot项目发布到docker
在项目的main文件夹下创建docker文件夹,并在该文件夹下创建Dockerfile文件,添加以下配置
dockerfile
FROM java:8
VOLUME /tmp
ADD dockertest-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT [ "java", "-jar", "/app.jar" ]

目录结构

在static下创建index.html
html
<body>
<a href="hello/test">hello</a>
</body>
</html>
创建controller
java
@RestController
@RequestMapping("/hello")
public class HelloController {
@GetMapping("/test")
public String test(){
return "success";
}
}
在pom.xml文件中导入docker的maven插件
xml
<plugin>
<!-- docker-maven插件-->
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<dockerHost>http://192.168.174.130:2375</dockerHost>
<imageName>${project.artifactId}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
clean项目

然后执行package重新打包项目

再然后通过docker插件打包项目为镜像文件,打包成功之后IDEA会自动将镜像文件上传到服务器

重新连接docker,可以看到在镜像列表中已经有了刚才生成的镜像

在镜像上右键 → Create Container创建新容器

在弹出的对话框中给容器指定名字

点击"Modify options"设置启动项

指定端口映射,然后点击"Run"运行容器

在linux下可以看到运行情况

开启Linux的8080端口
firewall-cmd --zone=public --add-port=8080/tcp --permanent
systemctl restart firewalld.service
在Windows的浏览器中访问项目

点击"hello"获取结果

补充:利用Java代码操作docker
外部引入docker-java所需要的jar包
将docker-java.rar添加到maven本地仓库com.github下并解压

该文件夹下包含java操作docker需要的包

在SpringBoot项目中导入依赖
xml
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java</artifactId>
<version>0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.4</version>
</dependency>
将一下pem文件拷贝到项目的resources目录下

application.yml配置
yaml
spring:
application:
name: dockertest
server:
port: 8080
docker:
url: tcp://192.168.232.129:2375
创建Docker配置类
java
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.DockerCmdExecFactory;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author: Mr·Xiang
* @create 2023-03-15 20:31
*/
@Configuration
public class DockerConfig {
@Value("${docker.url}")
private String url;
@Bean
public DockerClient dockerClient(){
// 进行安全认证
DockerClientConfig config =
DefaultDockerClientConfig.createDefaultConfigBuilder()
// 服务器ip
.withDockerHost(url)
.withDockerTlsVerify(true)
// 压缩包解压的路径
.withDockerCertPath(
DockerClient.class.getClassLoader().getResource("").getPath())
// API版本 可通过在服务器 docker version 命令查看
.withApiVersion("1.38")
.build();
// docker命令执行工厂
DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory()
.withReadTimeout(60000)
.withConnectTimeout(60000)
.withMaxTotalConnections(100)
.withMaxPerRouteConnections(10);
DockerClient dockerClient = DockerClientBuilder.getInstance(config)
.withDockerCmdExecFactory(dockerCmdExecFactory).build();
//
return dockerClient;
}
}
添加Docker工具类
java
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.PullImageCmd;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.Ports;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import static com.github.dockerjava.api.model.HostConfig.newHostConfig;
/**
* @author: Mr·Xiang
* @create 2023-03-15 20:41
*/
@Component
public class DockerUtil {
@Resource
private DockerClient dockerClient;
/**
*
* @param containerName 容器名
* @param imageName 镜像名
* @param containerPort 容器端口
* @param linuxPort Linux操作系统端口
* @return 容器信息
*/
public CreateContainerResponse createContainers(String containerName, String imageName, int containerPort, int linuxPort){
//映射端口8088--->80
ExposedPort exposedPort = ExposedPort.tcp(containerPort);
Ports portBindings = new Ports();
portBindings.bind(exposedPort, Ports.Binding.bindPort(linuxPort));
CreateContainerResponse container =
dockerClient.createContainerCmd(imageName)
.withName(containerName)
.withHostConfig(newHostConfig().withPortBindings(portBindings))
.withExposedPorts(exposedPort).exec();
// 启动容器
startContainer(container.getId());
return container;
}
/**
* 开启容器
* @param containerId 容器id
*/
public boolean startContainer(String containerId){
try {
dockerClient.startContainerCmd(containerId).exec();
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
/**
* 停止容器
* @param containerId 容器id
*/
public boolean stopContainer(String containerId){
try {
dockerClient.stopContainerCmd(containerId).exec();
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
/**
* 删除容器
* @param containerId 容器id
*/
public boolean removeContainer(String containerId){
try {
dockerClient.removeContainerCmd(containerId).exec();
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
/**
* 拉取镜像
* @param repository 仓库
* @return
*/
public PullImageCmd pullImage(String repository){
PullImageCmd pullImageCmd = dockerClient.pullImageCmd(repository);
return pullImageCmd;
}
/**
* 删除镜像
* @param imageId
*/
public boolean removeImage(String imageId){
try {
dockerClient.removeImageCmd(imageId).exec();
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
}
创建Controller
java
import com.example.dockertest2.DockerUtil;
import com.github.dockerjava.api.command.CreateContainerResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author: Mr·Xiang
* @create 2023-03-15 20:40
*/
@RestController
@RequestMapping("/docker")
public class DockerController {
@Resource
private DockerUtil dockerUtil;
@GetMapping("/create")
public CreateContainerResponse create(){
CreateContainerResponse containerResponse =
dockerUtil.createContainers("nginx-java", "nginx", 80, 81);
System.out.println(containerResponse);
return containerResponse;
}
@GetMapping("/stop")
public void stop(String id){
dockerUtil.stopContainer(id);
}
@GetMapping("/del")
public void del(String id){
dockerUtil.removeContainer(id);
}
}
启动项目请求接口进行测试,浏览器得到以下信息表示创建成功

通过docker ps指令验证容器是否启动成功,看到以下信息表示容器启动成功

开启Linux的81端口可以访问nginx
firewall-cmd --zone=public --add-port=81/tcp --permanent
systemctl restart firewalld.service

自主生成docker-java所需要的jar包(可选)
拉取docker-java源代码到本地文件夹
git clone https://github.com/docker-java/docker-java.git

编译包,生成本地jar
cd docker-java
mvn install -Dmaven.test.skip=true

成功入下图所示

生成Java项目需要的pem文件
在Linux的任意目录下创建auto_gen_docker.sh文件,并添加以下内容
sh
#!/bin/bash
#
# -------------------------------------------------------------
# 自动创建 Docker TLS 证书
# -------------------------------------------------------------
# 以下是配置信息
# --[BEGIN]------------------------------
CODE="docker"
IP="192.168.1.1"
PASSWORD="123456"
COUNTRY="CN"
STATE="HUNAN"
CITY="CHANGSHA"
ORGANIZATION="thyc"
ORGANIZATIONAL_UNIT="Dev"
COMMON_NAME="$IP"
EMAIL="an23gn@163.com"
# --[END]--
# Generate CA key
openssl genrsa -aes256 -passout "pass:$PASSWORD" -out "ca-key-$CODE.pem" 4096
# Generate CA
openssl req -new -x509 -days 365 -key "ca-key-$CODE.pem" -sha256 -out "ca-$CODE.pem" -passin "pass:$PASSWORD" -subj "/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORGANIZATION/OU=$ORGANIZATIONAL_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"
# Generate Server key
openssl genrsa -out "server-key-$CODE.pem" 4096
# Generate Server Certs.
openssl req -subj "/CN=$COMMON_NAME" -sha256 -new -key "server-key-$CODE.pem" -out server.csr
echo "subjectAltName = IP:$IP,IP:127.0.0.1" >> extfile.cnf
echo "extendedKeyUsage = serverAuth" >> extfile.cnf
openssl x509 -req -days 365 -sha256 -in server.csr -passin "pass:$PASSWORD" -CA "ca-$CODE.pem" -CAkey "ca-key-$CODE.pem" -CAcreateserial -out "server-cert-$CODE.pem" -extfile extfile.cnf
# Generate Client Certs.
rm -f extfile.cnf
openssl genrsa -out "key-$CODE.pem" 4096
openssl req -subj '/CN=client' -new -key "key-$CODE.pem" -out client.csr
echo extendedKeyUsage = clientAuth >> extfile.cnf
openssl x509 -req -days 365 -sha256 -in client.csr -passin "pass:$PASSWORD" -CA "ca-$CODE.pem" -CAkey "ca-key-$CODE.pem" -CAcreateserial -out "cert-$CODE.pem" -extfile extfile.cnf
rm -vf client.csr server.csr
chmod -v 0400 "ca-key-$CODE.pem" "key-$CODE.pem" "server-key-$CODE.pem"
chmod -v 0444 "ca-$CODE.pem" "server-cert-$CODE.pem" "cert-$CODE.pem"
# 打包客户端证书
mkdir -p "tls-client-certs-$CODE"
cp -f "ca-$CODE.pem" "cert-$CODE.pem" "key-$CODE.pem" "tls-client-certs-$CODE/"
cd "tls-client-certs-$CODE"
tar zcf "tls-client-certs-$CODE.tar.gz" *
mv "tls-client-certs-$CODE.tar.gz" ../
cd ..
rm -rf "tls-client-certs-$CODE"
# 拷贝服务端证书
mkdir -p /etc/docker/certs.d
cp "ca-$CODE.pem" "server-cert-$CODE.pem" "server-key-$CODE.pem" /etc/docker/certs.d/
给auto_gen_docker.sh添加执行权限
chmod a+x auto_gen_docker.sh
执行脚本
./auto_gen_docker.sh
执行完毕之后会在当前文件夹下生成一个压缩包:tls-client-certs-docker.tar.gz,该压缩包中的文件就是Java项目需要的pem文件,解压压缩包将其中的文件拷贝到springboot项目的resources目录下即可