点击上方蓝字关注我们 文末有惊喜
刚入项目组,就开始用dokcer-java去干活了,由于之前没接触过,所以就开始全网找资料,于是乎,找了一堆博客,好像都差不多,虽然都能跑起来,但是我的需求并没有得以实现:
踩了这么多坑之后,我决定做下总结,于是就有了现在这篇 “号称全网最全的docker-java 快速入门案例” 的文章。
前提是docker环境已经安装,如果没有安装过可以参考我的文章:https://blog.csdn.net/weixin_34311210/article/details/106181740
git clone https://github.com/docker-java/docker-java.git
如果嫌网速太慢,搞不下来的话,可以关注公众号”AI码师“,回复docker-java 获取最新源码
cd docker-java
mvn install -Dmaven.test.skip=true
过程省略...
<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>
注意:idea 设置的maven配置的仓库路径要和刚才打包的maven 的仓库路径要保持一致,否则是找不到你本地打包的jar
进入docker服务器,修改配置文件
vi /lib/systemd/system/docker.service
找到ExecStart 开头的配置,注释原配置 进行备份
插入以下内容
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
保存退出
systemctl daemon-reload
service docker restart
注意:如果是云服务或者防火墙打开的话,记得开放端口 浏览器输入:http://IP:2375/version 如果响应正常,则配置生效
public DockerClient connectDocker(){
DockerClient dockerClient = DockerClientBuilder.getInstance("tcp://ip:2375").build();
Info info = dockerClient.infoCmd().exec();
String infoStr = JSONObject.toJSONString(info);
System.out.println("docker的环境信息如下:=================");
System.out.println(info);
return dockerClient;
}
如果控制台打印了信息,则代表你已经通过java 连接上了docker,如果出现可以私信我哦
到目前为止,我们已经连上docker了,接下来我会写很多示例给大家去使用,避免大家全网找文档。
vim auto_gen_docker.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/
chmod a+x auto_gen_docker.sh
sh auto_gen.sh
public static DockerClient getDockerClient() {
// 进行安全认证
DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
// 服务器ip
.withDockerHost("tcp://IP:PORT")
.withDockerTlsVerify(true)
// 压缩包解压的路径
.withDockerCertPath("D:\\code\\my_code\\test-skill\\src\\main\\resources\\tls-client-certs-docker")
// API版本 可通过在服务器 docker version 命令查看
.withApiVersion("1.37")
// 默认
.withRegistryUrl("https://index.docker.io/v1/")
// 默认
.withRegistryUsername("docker")
// 默认
.withRegistryPassword("123456")
// 默认
.withRegistryEmail("an23gn@163.com")
.build();
// docker命令执行工厂
DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory()
.withReadTimeout(60000)
.withConnectTimeout(60000)
.withMaxTotalConnections(100)
.withMaxPerRouteConnections(10);
dockerClient = DockerClientBuilder.getInstance(config).withDockerCmdExecFactory(dockerCmdExecFactory).build();
return dockerClient;
}
使用这个docker-client代替上面普通连接生成的docker-client
public DockerClient connectDocker(){
DockerClient dockerClient = getDockerClient();
Info info = dockerClient.infoCmd().exec();
String infoStr = JSONObject.toJSONString(info);
System.out.println("docker的环境信息如下:=================");
System.out.println(info);
return dockerClient;
}
执行后,应该会报如下这个错误 Client sent an HTTP request to an HTTPS server 这是我踩的其中一个坑,后面我通过跟踪源码,找到问题所在:源码中需要验证认证文件是否存在:
但是我们压缩包里面的认证文件是这样的:
所导致没有识别到认证文件,从而导致docker以为我们没有采用https协议,默认就是用http;但是我们服务端是开启了https的,所以会出现上面那个错误。
如何解决呢?源码是修改不了的,我们只需要把我们生成的认证文件修改成他需要的名称格式就可以了,相信有不少网友也遇到过这样的坑吧!
按要求修改后
重新运行 程序正常.
public CreateContainerResponse createContainers(DockerClient client,String containerName,String imageName){
//映射端口8088—>80
ExposedPort tcp80 = ExposedPort.tcp(80);
Ports portBindings = new Ports();
portBindings.bind(tcp80, Ports.Binding.bindPort(8088));
CreateContainerResponse container = client.createContainerCmd(imageName)
.withName(containerName)
.withHostConfig(newHostConfig().withPortBindings(portBindings))
.withExposedPorts(tcp80).exec();
return container;
}
public LoadImageCmd loadImage(DockerClient client, String filePath){
LoadImageCmd loadImageCmd = null;
try {
loadImageCmd = client.loadImageCmd(new FileInputStream(filePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return loadImageCmd;
}
/**
* repository 镜像名称:tag名称
**/
public PullImageCmd pullImage(DockerClient client,String repository){
PullImageCmd pullImageCmd = client.pullImageCmd(repository);
return pullImageCmd;
}
public void removeImage(DockerClient client,String imageId){
client.removeImageCmd(imageId).exec();
}
public void removeContainer(DockerClient client,String containerId){
client.removeContainerCmd(containerId).exec();
}
public void startContainer(DockerClient client,String containerId){
client.startContainerCmd(containerId).exec();
}
public void stopContainer(DockerClient client,String containerId){
client.stopContainerCmd(containerId).exec();
}
使用hostConfig方式,直接使用Volumes是行不通的,这个也是请教我领导的,自己确实琢磨了半天。
public CreateContainerResponse createContainers(DockerClient client,String containerName,String imageName){
HostConfig hostConfig = newHostConfig();
Bind bind = new Bind("服务器路径",new Volume("容器路径"));
hostConfig.setBinds(bind);
CreateContainerResponse container = client.createContainerCmd(imageName)
.withName(containerName)
.withHostConfig(hostConfig)
.exec();
return container;
}
public CreateContainerResponse createContainers(DockerClient client,String containerName,String imageName){
HostConfig hostConfig = newHostConfig();
CreateContainerResponse container = client.createContainerCmd(imageName)
.withName(containerName)
.withHostConfig(hostConfig)
.withCmd("python","/root/scripts/test.py")
.exec();
return container;
}
public CreateContainerResponse createContainers(DockerClient client,String containerName,String imageName){
HostConfig hostConfig = newHostConfig();
CreateContainerResponse container = client.createContainerCmd(imageName)
.withName(containerName)
.withHostConfig(hostConfig)
// 注意命令和参数不能进行组合,必须都用逗号隔开,也就是空格全部换成这里的,分割
.withCmd("python","/root/scripts/test.py","-t","999")
.exec();
return container;
}
到这里,所有的docker-java示例全部编写完成,后续会增加更多的实战用例,敬请期待吧。