提前踩坑
剛入專案組,就開始用dokcer-java去干活了,由于之前沒接觸過,所以就開始全網找資料,于是乎,找了一堆博客,好像都差不多,雖然都能跑起來,但是我的需求并沒有得以實作:
?
- 無法連接遠程docker
- 無法實作路徑掛載
- 無法實作安全連接(按照操作后,出現了Client sent an HTTP request to an HTTPS server的錯誤,很蛋疼)
- 如何實作docker 執行腳本檔案,并攜帶引數
我們現在開始避坑
踩了這么多坑之后,我決定做下總結,于是就有了現在這篇 “號稱全網最全的docker-java 快速入門案例” 的文章,
?
前提是docker環境已經安裝,如果沒有安裝過可以參考我的文章:https://blog.csdn.net/weixin_34311210/article/details/106181740
集成docker-java
下載docker-java原始碼
git clone https://github.com/docker-java/docker-java.git
如果嫌網速太慢,搞不下來的話,可以關注公眾號”AI碼師“,回復docker-java 獲取最新原始碼
編譯包,生成本地jar
cd docker-java
mvn install -Dmaven.test.skip=true
創建maven專案
程序省略…
引入依賴
<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資訊,實作遠程訪問
進入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了,接下來我會寫很多示例給大家去使用,避免大家全網找檔案,
?
最強示例
1.首先來一個高逼格的:丟棄普通連接,實作安全連接
- 撰寫生成證書的腳本,這是在網上找的,可以自動生成腳本并且完成拷貝
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
- 拷貝當前目錄下的tls-client-certs-docker.tar 檔案到專案的resource下,并解壓,如圖所示:

- 撰寫建立安全連接的方法
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的,所以會出現上面那個錯誤,
?
如何解決呢?原始碼是修改不了的,我們只需要把我們生成的認證檔案修改成他需要的名稱格式就可以了,相信有不少網友也遇到過這樣的坑吧!
?
按要求修改后

重新運行 程式正常.
2.創建容器
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;
}
3.加載鏡像
public LoadImageCmd loadImage(DockerClient client, String filePath){
LoadImageCmd loadImageCmd = null;
try {
loadImageCmd = client.loadImageCmd(new FileInputStream(filePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return loadImageCmd;
}
4.拉取鏡像
/**
* repository 鏡像名稱:tag名稱
**/
public PullImageCmd pullImage(DockerClient client,String repository){
PullImageCmd pullImageCmd = client.pullImageCmd(repository);
return pullImageCmd;
}
5.洗掉鏡像
public void removeImage(DockerClient client,String imageId){
client.removeImageCmd(imageId).exec();
}
6.移除容器
public void removeContainer(DockerClient client,String containerId){
client.removeContainerCmd(containerId).exec();
}
7.啟動容器
public void startContainer(DockerClient client,String containerId){
client.startContainerCmd(containerId).exec();
}
8.停止容器
public void stopContainer(DockerClient client,String containerId){
client.stopContainerCmd(containerId).exec();
}
9.路徑掛載
使用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;
}
10 執行命令
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;
}
11 利用docker 執行腳本命令 傳遞引數
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示例全部撰寫完成,后續會增加更多的實戰用例,敬請期待吧,如果運行程序中出現任何問題,直接在底部留言即可,我看到后會回復你的,
福利大放送
關注微信公眾號“AI碼師”,領取2021面試資料和2021最新全套微服務教程

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/333565.html
標籤:其他
上一篇:Linux作業系統學習02
