Skip to content

Commit 6b06d5e

Browse files
author
xianyanYang
committed
添加远程镜像下载功能
1 parent 5ca4754 commit 6b06d5e

12 files changed

Lines changed: 411 additions & 160 deletions

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
<groupId>com.learn.docker</groupId>
1414
<artifactId>docker-java-api</artifactId>
15-
<version>2.0.0-SNAPSHOT</version>
15+
<version>2.1.0-SNAPSHOT</version>
1616

1717
<description>Docker Java API</description>
1818

src/main/java/com/docker/infrastructure/service/InternalDockerClientConnection.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,6 @@ public class InternalDockerClientConnection implements DockerClientConnection {
5656
@Value("${dockerClient.pullImagesAwaitCompletionSeconds:30}")
5757
private int pullImagesAwaitSeconds;
5858

59-
/**
60-
* 镜像仓库地址,用于镜像的推送存储,
61-
* 如 : docker login xxx.xxx.xxx.xxx:xxxx或者放置域名
62-
*/
63-
@Value("${registryRepository:localhost:9005}")
64-
private String registryRepository;
65-
6659
/**
6760
* 容器启动间隔时间
6861
*/
@@ -91,8 +84,7 @@ public void init() {
9184
DockerClient dockerClient = DockerClientBuilder.getInstance(config).build();
9285
dockerImageOperations = new InternalDockerImageOperations(dockerClient).
9386
setPullImagesAwaitSeconds(pullImagesAwaitSeconds).
94-
setPushImagesAwaitSeconds(pushImagesAwaitSeconds).
95-
setRegistryRepository(registryRepository);
87+
setPushImagesAwaitSeconds(pushImagesAwaitSeconds);
9688
dockerNetworkOperations = new InternalDockerNetworkOperations(dockerClient);
9789
dockerContainerOperations = new InternalDockerContainerOperations(dockerClient, dockerNetworkOperations, dockerImageOperations).
9890
setIntervalSecond(intervalSecond);

src/main/java/com/docker/infrastructure/service/InternalDockerContainerOperations.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import org.apache.commons.lang.StringUtils;
1818
import org.slf4j.Logger;
1919
import org.slf4j.LoggerFactory;
20-
import org.springframework.beans.factory.annotation.Value;
2120
import org.springframework.util.CollectionUtils;
2221

2322
import java.util.ArrayList;
Lines changed: 59 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.docker.infrastructure.service;
22

33
import com.docker.exception.DockerImageException;
4+
import com.docker.model.ImageRepository;
5+
import com.docker.model.RegistryAuthConfig;
46
import com.docker.service.DockerImageOperations;
57
import com.github.dockerjava.api.DockerClient;
68
import com.github.dockerjava.api.command.BuildImageCmd;
@@ -32,20 +34,10 @@
3234
public class InternalDockerImageOperations implements DockerImageOperations {
3335

3436
private static final Logger logger = LoggerFactory.getLogger(InternalDockerImageOperations.class);
35-
3637
private DockerClient dockerClient;
37-
private String registryRepository = "localhost:8081";
3838
private long pullImagesAwaitSeconds = 30;
3939
private long pushImagesAwaitSeconds = 30;
4040

41-
public InternalDockerImageOperations setRegistryRepository(String registryRepository) {
42-
if (StringUtils.isBlank(registryRepository)) {
43-
throw new DockerImageException("pullImage-init", String.format("镜像仓库地址不能为NULL或者空字符串。", pullImagesAwaitSeconds));
44-
}
45-
this.registryRepository = registryRepository;
46-
return this;
47-
}
48-
4941
public InternalDockerImageOperations setPullImagesAwaitSeconds(long pullImagesAwaitSeconds) {
5042
if (pullImagesAwaitSeconds <= 0) {
5143
throw new DockerImageException("pullImage-init", String.format("镜像拉取延迟时间(%秒)不合法。", pullImagesAwaitSeconds));
@@ -70,91 +62,113 @@ public InternalDockerImageOperations(DockerClient dockerClient) {
7062
}
7163

7264
@Override
73-
public void pullImageFrom(String imageRepository, AuthConfig authConfig) throws DockerImageException {
74-
if (StringUtils.isBlank(imageRepository)) {
75-
throw new DockerImageException("pullImage-001", "镜像地址不能为NULL或者空字符串。");
65+
public void pullImageFrom(ImageRepository imageNameWithRepository, RegistryAuthConfig registryAuthConfig) throws DockerImageException {
66+
if (imageNameWithRepository == null) {
67+
throw new DockerImageException("pullImageFrom-001", "镜像地址不能为NULL。");
68+
}
69+
70+
if (registryAuthConfig == null) {
71+
throw new DockerImageException("pullImageFrom-002", "镜像仓库认证信息不能为NULL。");
7672
}
73+
74+
AuthConfig authConfig = new AuthConfig()
75+
.withUsername(registryAuthConfig.getUsername())
76+
.withPassword(registryAuthConfig.getPassword())
77+
.withRegistryAddress(registryAuthConfig.getRegistryAddress());
78+
79+
String imageName = imageNameWithRepository.toString();
7780
try {
78-
dockerClient.pullImageCmd(imageRepository).
81+
dockerClient.pullImageCmd(imageName).
7982
withAuthConfig(authConfig).
8083
exec(new PullImageResultCallback()).
8184
awaitCompletion(pullImagesAwaitSeconds, TimeUnit.SECONDS);
8285
} catch (InterruptedException e) {
83-
throw new DockerImageException("pullImage-004", String.format("下载镜像 %s 失败。", imageRepository));
86+
throw new DockerImageException("pullImageFrom-003", String.format("下载镜像 %s 失败。", imageName));
8487
}
8588
}
8689

8790
@Override
88-
public void pullImage(String imageRepository) throws DockerImageException {
89-
if (StringUtils.isBlank(imageRepository)) {
90-
throw new DockerImageException("pullImage-001", "镜像地址不能为NULL或者空字符串。");
91+
public void pullImage(ImageRepository imageNameWithRepository) throws DockerImageException {
92+
if (imageNameWithRepository == null) {
93+
throw new DockerImageException("pullImage-001", "镜像地址不能为NULL。");
9194
}
95+
this.pullImage(imageNameWithRepository.toString());
96+
}
97+
98+
@Override
99+
public void pullImage(String imageNameWithRepository) throws DockerImageException {
92100
try {
93101
dockerClient
94-
.pullImageCmd(imageRepository)
102+
.pullImageCmd(imageNameWithRepository)
95103
.exec(new PullImageResultCallback())
96104
.awaitCompletion(pullImagesAwaitSeconds, TimeUnit.SECONDS);
97105
} catch (InterruptedException e) {
98-
throw new DockerImageException("pullImage-004", String.format("下载镜像 %s 失败。", imageRepository));
106+
throw new DockerImageException("pullImage-002", String.format("下载镜像 %s 失败。", imageNameWithRepository));
99107
}
100108
}
101109

102-
/**
103-
* @param dockerFilePath
104-
* @param imageRepository 仓库名为两段式路径,比如 jwilder/nginx-proxy
105-
* @param tag
106-
* @return
107-
*/
108110
@Override
109-
public String buildImage(String dockerFilePath, String imageRepository, String tag) throws DockerImageException {
110-
if (StringUtils.isBlank(imageRepository)) {
111+
public String buildImage(String dockerFilePath, ImageRepository imageNameWithRepository) throws DockerImageException {
112+
if (imageNameWithRepository == null) {
111113
throw new DockerImageException("buildImage-002", "镜像仓库名不能为NULL或者空字符串。");
112114
}
113-
if (StringUtils.isBlank(tag)) {
114-
throw new DockerImageException("buildImage-003", "镜像标签名不能为NULL或者空字符串。");
115-
}
116115

116+
String imageName = imageNameWithRepository.toString();
117117
InputStream tarFile = fetchImageBuildFilesToTarFile(dockerFilePath);
118-
String imageName = String.format("%s/%s:%s", registryRepository, imageRepository, tag);
119118
return dockerfileBuild(tarFile, imageName);
120119
}
121120

122-
123121
@Override
124-
public void pushImage(String imageRepository, String tag) throws DockerImageException {
125-
String imageName = String.format("%s/%s:%s", registryRepository, imageRepository, tag);
122+
public void pushImageToLocal(ImageRepository imageNameWithRepository) throws DockerImageException {
123+
if (imageNameWithRepository == null) {
124+
throw new DockerImageException("pushImageToLocal-001", "镜像地址不能为NULL。");
125+
}
126+
127+
String imageName = imageNameWithRepository.toString();
126128
try {
127-
dockerClient.pushImageCmd(imageName)
128-
.withAuthConfig(dockerClient.authConfig())
129-
.exec(new PushImageResultCallback())
130-
.awaitCompletion(pushImagesAwaitSeconds, TimeUnit.SECONDS);
129+
dockerClient.pushImageCmd(imageName).
130+
withAuthConfig(dockerClient.authConfig()).
131+
exec(new PushImageResultCallback()).
132+
awaitCompletion(pushImagesAwaitSeconds, TimeUnit.SECONDS);
131133
} catch (InterruptedException e) {
132134
logger.error("推送镜像失败。", e);
133-
throw new DockerImageException("pushImage-001", "镜像制作文件读取失败。");
135+
throw new DockerImageException("pushImageToLocal-002", "镜像制作文件读取失败。");
134136
} catch (Exception e) {
135137
logger.error("推送镜像失败。", e);
136-
throw new DockerImageException("pushImage-002", "推送镜像失败。");
138+
throw new DockerImageException("pushImageToLocal-003", String.format("推送镜像 %s 失败。", imageName));
137139
}
138140
}
139141

142+
@Override
143+
public void tagImage(ImageRepository imageNameWithRepository, ImageRepository newImageNameWithRepository) throws DockerImageException {
144+
if (imageNameWithRepository == null) {
145+
throw new DockerImageException("tagImage-001", "原镜像地址不能为NULL。");
146+
}
147+
if (newImageNameWithRepository == null) {
148+
throw new DockerImageException("tagImage-002", "新镜像地址不能为NULL。");
149+
}
150+
151+
dockerClient.tagImageCmd(imageNameWithRepository.toString(), newImageNameWithRepository.toStringWithoutTag(), newImageNameWithRepository.getTag()).exec();
152+
}
153+
140154
private InputStream fetchImageBuildFilesToTarFile(String dockerFilePath) {
141155
if (StringUtils.isBlank(dockerFilePath)) {
142-
throw new DockerImageException("buildImage-001", "镜像制作文件目录不能为NULL或者空字符串。");
156+
throw new DockerImageException("fetchImageBuildFilesToTarFile-001", "镜像制作文件目录不能为NULL或者空字符串。");
143157
}
144158
File dockerFile = FileUtils.getFile(dockerFilePath);
145159
if (dockerFile.exists() == false) {
146-
throw new DockerImageException("buildImage-004", "镜像制作文件目录不存在。");
160+
throw new DockerImageException("fetchImageBuildFilesToTarFile-002", "镜像制作文件目录不存在。");
147161
}
148162
Collection<File> files = FileUtils.listFiles(dockerFile, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
149163
if (CollectionUtils.isEmpty(files)) {
150-
throw new DockerImageException("buildImage-005", "镜像制作文件不存在。");
164+
throw new DockerImageException("fetchImageBuildFilesToTarFile-003", "镜像制作文件不存在。");
151165
}
152166
try {
153167
File file = CompressArchiveUtil.archiveTARFiles(dockerFile, files, UUID.randomUUID().toString());
154168
return new FileInputStream(file);
155169
} catch (IOException e) {
156170
logger.error("镜像制作文件读取失败。", e);
157-
throw new DockerImageException("buildImage-006", "镜像制作失败。");
171+
throw new DockerImageException("fetchImageBuildFilesToTarFile-004", "镜像制作失败。");
158172
}
159173
}
160174

@@ -166,5 +180,4 @@ private String dockerfileBuild(InputStream inputStream, String imageName) {
166180
return buildImageCmd.withNoCache(true).exec(new BuildImageResultCallback()).awaitImageId();
167181
}
168182

169-
170183
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.docker.model;
2+
3+
import com.docker.exception.DockerImageException;
4+
import org.apache.commons.lang.StringUtils;
5+
6+
/**
7+
* @author sofia
8+
* 镜像地址
9+
*/
10+
public class ImageRepository {
11+
/**
12+
* 镜像名称,如:skynj/app1,不能为空
13+
*/
14+
private String name;
15+
/**
16+
* 仓库地址,如:localhost:9000,可以为空
17+
*/
18+
private String repository;
19+
/**
20+
* 版本号,如:1.0.0,默认为:latest
21+
*/
22+
private String tag = "latest";
23+
24+
public ImageRepository(String name) {
25+
if (StringUtils.isBlank(name)) {
26+
throw new DockerImageException("ImageRepository-001", "镜像名称不能为NULL或空字符串。");
27+
}
28+
this.name = name;
29+
}
30+
31+
public void setName(String name) {
32+
if (StringUtils.isBlank(name)) {
33+
throw new DockerImageException("ImageRepository-001", "镜像名称不能为NULL或空字符串。");
34+
}
35+
this.name = name;
36+
}
37+
38+
public void setRepository(String repository) {
39+
this.repository = repository;
40+
}
41+
42+
public void setTag(String tag) {
43+
this.tag = tag;
44+
}
45+
46+
public String getName() {
47+
return name;
48+
}
49+
50+
public String getRepository() {
51+
return repository;
52+
}
53+
54+
public String getTag() {
55+
return tag;
56+
}
57+
58+
/**
59+
* 完整地址,不能为空,格式为:[repository]/[name]:[tag],如:localhost:9005/skynj/app1:1.0.0
60+
*
61+
* @return
62+
*/
63+
@Override
64+
public String toString() {
65+
StringBuilder result = new StringBuilder();
66+
if (StringUtils.isBlank(this.repository) == false) {
67+
result.append(this.repository);
68+
result.append("/");
69+
}
70+
result.append(name);
71+
if (StringUtils.isBlank(tag) == false) {
72+
result.append(":");
73+
result.append(tag);
74+
}
75+
return result.toString();
76+
}
77+
78+
/**
79+
* 无版本地址,不能为空,格式为:[repository]/[name],如:localhost:9005/skynj/app1
80+
*
81+
* @return
82+
*/
83+
public String toStringWithoutTag() {
84+
StringBuilder result = new StringBuilder();
85+
if (StringUtils.isBlank(this.repository) == false) {
86+
result.append(this.repository);
87+
result.append("/");
88+
}
89+
result.append(name);
90+
return result.toString();
91+
}
92+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.docker.model;
2+
3+
public class RegistryAuthConfig {
4+
5+
private static final String DEFAULT_SERVER_ADDRESS = "http://%s/v2/";
6+
7+
private String username;
8+
9+
private String password;
10+
11+
private String registryAddress;
12+
13+
public RegistryAuthConfig(String username, String password, String registryAddress) {
14+
this.username = username;
15+
this.password = password;
16+
this.registryAddress = String.format(DEFAULT_SERVER_ADDRESS, registryAddress);
17+
}
18+
19+
public String getUsername() {
20+
return username;
21+
}
22+
23+
public String getPassword() {
24+
return password;
25+
}
26+
27+
28+
public String getRegistryAddress() {
29+
return registryAddress;
30+
}
31+
}
Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
package com.docker.service;
22

33
import com.docker.exception.DockerImageException;
4-
import com.github.dockerjava.api.model.AuthConfig;
4+
import com.docker.model.ImageRepository;
5+
import com.docker.model.RegistryAuthConfig;
56

67
public interface DockerImageOperations {
78

8-
void pullImageFrom(String imageRepository, AuthConfig authConfig) throws DockerImageException;
9+
void pullImageFrom(ImageRepository imageNameWithRepository, RegistryAuthConfig authConfig) throws DockerImageException;
910

10-
void pullImage(String imageRepository) throws DockerImageException;
11+
void pullImage(ImageRepository imageNameWithRepository) throws DockerImageException;
1112

12-
/**
13-
* @param dockerFilePath
14-
* @param imageRepository
15-
* @param tag
16-
* @return
17-
*/
18-
String buildImage(String dockerFilePath, String imageRepository, String tag) throws DockerImageException;
13+
void pullImage(String imageNameWithRepository) throws DockerImageException;
1914

20-
void pushImage(String imageRepository, String tag) throws DockerImageException;
15+
String buildImage(String dockerFilePath, ImageRepository imageNameWithRepository) throws DockerImageException;
16+
17+
void pushImageToLocal(ImageRepository imageNameWithRepository) throws DockerImageException;
18+
19+
void tagImage(ImageRepository imageNameWithRepository, ImageRepository newImageNameWithRepository) throws DockerImageException;
2120
}

0 commit comments

Comments
 (0)