Skip to content

Commit 7f26859

Browse files
committed
Added back autoupdate
1 parent a6823bc commit 7f26859

3 files changed

Lines changed: 128 additions & 12 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package io.github.intisy.docker;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.JsonObject;
5+
6+
import java.io.IOException;
7+
import java.io.InputStreamReader;
8+
import java.net.HttpURLConnection;
9+
import java.net.URL;
10+
11+
public class DockerVersionFetcher {
12+
private static final String GITHUB_API_URL = "https://api.github.com/repos/moby/moby/releases/latest";
13+
private static final String FALLBACK_VERSION = "26.1.4";
14+
private static String latestVersion;
15+
16+
public static String getLatestVersion() {
17+
if (latestVersion == null) {
18+
try {
19+
URL url = new URL(GITHUB_API_URL);
20+
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
21+
conn.setRequestMethod("GET");
22+
conn.setRequestProperty("Accept", "application/vnd.github.v3+json");
23+
24+
if (conn.getResponseCode() != 200) {
25+
throw new IOException("Failed to fetch latest version from GitHub: " + conn.getResponseCode());
26+
}
27+
28+
try (InputStreamReader reader = new InputStreamReader(conn.getInputStream())) {
29+
JsonObject jsonObject = new Gson().fromJson(reader, JsonObject.class);
30+
latestVersion = jsonObject.get("tag_name").getAsString().replace("v", "");
31+
}
32+
} catch (IOException e) {
33+
System.err.println("Could not fetch latest Docker version, falling back to " + FALLBACK_VERSION + ". Error: " + e.getMessage());
34+
latestVersion = FALLBACK_VERSION;
35+
}
36+
}
37+
return latestVersion;
38+
}
39+
}

src/main/java/io/github/intisy/docker/LinuxDockerProvider.java

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@
2626
* @author Finn Birich
2727
*/
2828
public class LinuxDockerProvider implements DockerProvider {
29-
private static final String DOCKER_URL = "https://download.docker.com/linux/static/stable/x86_64/docker-26.1.4.tgz";
3029
private static final String ROOTLESSKIT_VERSION = "v2.1.1";
31-
private static final String ROOTLESSKIT_DOWNLOAD_URL = "https://github.com/rootless-containers/rootlesskit/releases/download/%s/rootlesskit-x86_64.tar.gz";
30+
private static final String ROOTLESSKIT_DOWNLOAD_URL = "https://github.com/rootless-containers/rootlesskit/releases/download/%s/rootlesskit-%s.tar.gz";
3231
private static final String DOCKER_ROOTLESS_SCRIPT_URL = "https://raw.githubusercontent.com/moby/moby/master/contrib/dockerd-rootless.sh";
3332
private static final Path DOCKER_DIR = Path.of(System.getProperty("user.home"), ".docker-java");
3433
private static final Path DOCKER_PATH = DOCKER_DIR.resolve("docker/dockerd");
3534
private static final Path ROOTLESSKIT_PATH = DOCKER_DIR.resolve("rootlesskit");
3635
private static final Path DOCKER_SOCKET_PATH = DOCKER_DIR.resolve("run/docker.sock");
36+
private static final Path DOCKER_VERSION_FILE = DOCKER_DIR.resolve(".docker-version");
3737

3838
private static final String SLIRP4NETNS_VERSION = "v1.2.1";
39-
private static final String SLIRP4NETNS_DOWNLOAD_URL = "https://github.com/rootless-containers/slirp4netns/releases/download/%s/slirp4netns-x86_64";
39+
private static final String SLIRP4NETNS_DOWNLOAD_URL = "https://github.com/rootless-containers/slirp4netns/releases/download/%s/slirp4netns-%s";
4040
private static final Path SLIRP4NETNS_DIR = DOCKER_DIR.resolve("slirp4netns");
4141
private static final Path SLIRP4NETNS_PATH = SLIRP4NETNS_DIR.resolve("slirp4netns");
4242

@@ -52,7 +52,25 @@ public void ensureInstalled() throws IOException, InterruptedException {
5252
}
5353

5454
private void ensureDockerInstalled() throws IOException, InterruptedException {
55-
if (!Files.exists(DOCKER_PATH)) {
55+
boolean autoUpdate = Boolean.parseBoolean(System.getProperty("docker.auto.update", "true"));
56+
String latestVersion = DockerVersionFetcher.getLatestVersion();
57+
boolean needsUpdate = true;
58+
59+
if (Files.exists(DOCKER_PATH)) {
60+
if (autoUpdate && Files.exists(DOCKER_VERSION_FILE)) {
61+
String installedVersion = Files.readString(DOCKER_VERSION_FILE).trim();
62+
if (!installedVersion.equals(latestVersion)) {
63+
System.out.println("Newer Docker version available. Updating from " + installedVersion + " to " + latestVersion);
64+
} else {
65+
System.out.println("Docker is up to date. (" + latestVersion + ")");
66+
needsUpdate = false;
67+
}
68+
} else if (!autoUpdate) {
69+
needsUpdate = false;
70+
}
71+
}
72+
73+
if (needsUpdate) {
5674
System.out.println("Docker installation is incomplete or outdated. Re-installing...");
5775

5876
Path dockerInstallDir = DOCKER_DIR.resolve("docker");
@@ -64,7 +82,22 @@ private void ensureDockerInstalled() throws IOException, InterruptedException {
6482
}
6583
}
6684

67-
downloadAndExtract(DOCKER_URL, DOCKER_DIR);
85+
String arch = getArch();
86+
String dockerUrl = String.format("https://download.docker.com/linux/static/stable/%s/docker-%s.tgz", arch, latestVersion);
87+
downloadAndExtract(dockerUrl, DOCKER_DIR);
88+
Files.writeString(DOCKER_VERSION_FILE, latestVersion);
89+
}
90+
}
91+
92+
private String getArch() {
93+
String osArch = System.getProperty("os.arch");
94+
switch (osArch) {
95+
case "amd64":
96+
return "x86_64";
97+
case "aarch64":
98+
return "aarch64";
99+
default:
100+
throw new UnsupportedOperationException("Unsupported architecture: " + osArch);
68101
}
69102
}
70103

@@ -82,7 +115,7 @@ private void ensureRootlessKitInstalled() throws IOException, InterruptedExcepti
82115
return;
83116
}
84117
System.out.println("RootlessKit not found. Downloading...");
85-
String url = String.format(ROOTLESSKIT_DOWNLOAD_URL, ROOTLESSKIT_VERSION);
118+
String url = String.format(ROOTLESSKIT_DOWNLOAD_URL, ROOTLESSKIT_VERSION, getArch());
86119
downloadAndExtract(url, ROOTLESSKIT_PATH);
87120
System.out.println("RootlessKit installed successfully.");
88121
}
@@ -93,8 +126,8 @@ private void ensureSlirp4netnsInstalled() throws IOException, InterruptedExcepti
93126
}
94127
System.out.println("slirp4netns not found. Downloading...");
95128
SLIRP4NETNS_DIR.toFile().mkdirs();
96-
String url = String.format(SLIRP4NETNS_DOWNLOAD_URL, SLIRP4NETNS_VERSION);
97-
Path downloadedFilePath = SLIRP4NETNS_DIR.resolve("slirp4netns-x86_64");
129+
String url = String.format(SLIRP4NETNS_DOWNLOAD_URL, SLIRP4NETNS_VERSION, getArch());
130+
Path downloadedFilePath = SLIRP4NETNS_DIR.resolve("slirp4netns-" + getArch());
98131
downloadFile(url, downloadedFilePath);
99132
Files.move(downloadedFilePath, SLIRP4NETNS_PATH);
100133
SLIRP4NETNS_PATH.toFile().setExecutable(true);

src/main/java/io/github/intisy/docker/WindowsDockerProvider.java

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,66 @@
33
import com.github.dockerjava.api.DockerClient;
44
import com.github.dockerjava.api.command.PingCmd;
55
import com.github.dockerjava.core.DockerClientBuilder;
6+
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.net.URI;
10+
import java.net.http.HttpClient;
11+
import java.net.http.HttpRequest;
12+
import java.net.http.HttpResponse;
613
import java.nio.file.Files;
714
import java.nio.file.Path;
815
import java.nio.file.Paths;
16+
import java.nio.file.StandardCopyOption;
917

1018
/**
1119
* @author Finn Birich
1220
*/
1321
public class WindowsDockerProvider implements DockerProvider {
1422
private static final Path DOCKER_DESKTOP_PATH = Paths.get("C:", "Program Files", "Docker", "Docker", "Docker Desktop.exe");
23+
private static final String DOCKER_DESKTOP_INSTALLER_URL = "https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe";
24+
private static final Path DOCKER_INSTALLER_PATH = Paths.get(System.getProperty("java.io.tmpdir"), "DockerDesktopInstaller.exe");
1525

1626
@Override
17-
public void ensureInstalled() {
27+
public void ensureInstalled() throws IOException, InterruptedException {
1828
if (Files.exists(DOCKER_DESKTOP_PATH)) {
1929
return;
2030
}
21-
System.out.println("Docker Desktop not found. Please download and install Docker Desktop for Windows from: https://www.docker.com/products/docker-desktop");
22-
throw new UnsupportedOperationException("Automatic installation on Windows is not supported. Please install Docker Desktop manually.");
31+
32+
System.out.println("Docker Desktop not found. Downloading installer...");
33+
downloadFile(DOCKER_DESKTOP_INSTALLER_URL, DOCKER_INSTALLER_PATH);
34+
35+
System.out.println("Starting Docker Desktop installer. This may take a while...");
36+
ProcessBuilder pb = new ProcessBuilder(DOCKER_INSTALLER_PATH.toString(), "install", "--quiet");
37+
Process process = pb.start();
38+
int exitCode = process.waitFor();
39+
40+
Files.deleteIfExists(DOCKER_INSTALLER_PATH);
41+
42+
if (exitCode != 0) {
43+
throw new IOException("Docker Desktop installation failed with exit code: " + exitCode);
44+
}
45+
46+
System.out.println("Installation finished. Please start Docker Desktop manually to complete the setup.");
47+
}
48+
49+
private void downloadFile(String urlString, Path destinationPath) throws IOException, InterruptedException {
50+
System.out.println("Downloading " + urlString + " to " + destinationPath);
51+
HttpClient client = HttpClient.newBuilder()
52+
.followRedirects(HttpClient.Redirect.ALWAYS)
53+
.build();
54+
HttpRequest request = HttpRequest.newBuilder()
55+
.uri(URI.create(urlString))
56+
.build();
57+
HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
58+
59+
if (response.statusCode() >= 400) {
60+
throw new IOException("Failed to download file: " + response.statusCode());
61+
}
62+
63+
try (InputStream in = response.body()) {
64+
Files.copy(in, destinationPath, StandardCopyOption.REPLACE_EXISTING);
65+
}
2366
}
2467

2568
@Override
@@ -38,5 +81,6 @@ public DockerClient getClient() {
3881
}
3982

4083
@Override
41-
public void stop() {}
84+
public void stop() {
85+
}
4286
}

0 commit comments

Comments
 (0)