1717import java .net .URL ;
1818import java .nio .file .Files ;
1919import java .nio .file .Path ;
20- import java .nio .file .Paths ;
2120import java .nio .file .StandardCopyOption ;
2221import java .util .concurrent .TimeUnit ;
2322
2423/**
2524 * @author Finn Birich
2625 */
2726@ SuppressWarnings ("ResultOfMethodCallIgnored" )
28- public class LinuxDockerProvider implements DockerProvider {
27+ public class LinuxDockerProvider extends DockerProvider {
2928 private static final String ROOTLESSKIT_VERSION = "v2.1.1" ;
3029 private static final String ROOTLESSKIT_DOWNLOAD_URL = "https://github.com/rootless-containers/rootlesskit/releases/download/%s/rootlesskit-%s.tar.gz" ;
3130 private static final String DOCKER_ROOTLESS_SCRIPT_URL = "https://raw.githubusercontent.com/moby/moby/master/contrib/dockerd-rootless.sh" ;
3231 private static final String DOCKER_DOWNLOAD_URL = "https://download.docker.com/linux/static/stable/%s/docker-%s.tgz" ;
33- private static final Path DOCKER_DIR = Paths .get (System .getProperty ("user.home" ), ".docker-java" );
34- private static final Path DOCKER_PATH = DOCKER_DIR .resolve ("docker/dockerd" );
35- private static final Path ROOTLESSKIT_PATH = DOCKER_DIR .resolve ("rootlesskit" );
36- private static final Path DOCKER_SOCKET_PATH = DOCKER_DIR .resolve ("run/docker.sock" );
37- private static final Path DOCKER_VERSION_FILE = DOCKER_DIR .resolve (".docker-version" );
3832
3933 private static final String SLIRP4NETNS_VERSION = "v1.2.1" ;
4034 private static final String SLIRP4NETNS_DOWNLOAD_URL = "https://github.com/rootless-containers/slirp4netns/releases/download/%s/slirp4netns-%s" ;
4135 private static final Path SLIRP4NETNS_DIR = DOCKER_DIR .resolve ("slirp4netns" );
4236 private static final Path SLIRP4NETNS_PATH = SLIRP4NETNS_DIR .resolve ("slirp4netns" );
4337
38+ private Path dockerPath ;
39+ private Path rootlessKitPath ;
40+ private Path dockerSocketPath ;
41+ private Path dockerVersionFile ;
42+
4443 private DockerClient dockerClient ;
4544 private Process dockerProcess ;
46-
47- @ Override
48- public void ensureInstalled () throws IOException {
49- ensureDockerInstalled ();
50- ensureRootlessScriptInstalled ();
51- ensureRootlessKitInstalled ();
52- ensureSlirp4netnsInstalled ();
45+
46+ public LinuxDockerProvider () {
47+ setPath (DOCKER_DIR );
48+ }
49+
50+ public void setPath (Path path ) {
51+ dockerPath = path .resolve ("docker/dockerd" );
52+ rootlessKitPath = path .resolve ("rootlesskit" );
53+ dockerSocketPath = path .resolve ("run/docker.sock" );
54+ dockerVersionFile = path .resolve (".docker-version" );
5355 }
5456
5557 @ SuppressWarnings ("ResultOfMethodCallIgnored" )
56- private void ensureDockerInstalled () throws IOException {
58+ public void ensureInstalled () throws IOException {
5759 boolean autoUpdate = Boolean .parseBoolean (System .getProperty ("docker.auto.update" , "true" ));
5860 String latestVersion = DockerVersionFetcher .getLatestVersion ();
5961 boolean needsUpdate = true ;
6062
61- if (Files .exists (DOCKER_PATH )) {
62- if (autoUpdate && Files .exists (DOCKER_VERSION_FILE )) {
63- String installedVersion = new String (Files .readAllBytes (DOCKER_VERSION_FILE )).trim ();
63+ if (Files .exists (dockerPath )) {
64+ if (autoUpdate && Files .exists (dockerVersionFile )) {
65+ String installedVersion = new String (Files .readAllBytes (dockerVersionFile )).trim ();
6466 if (!installedVersion .equals (latestVersion )) {
6567 System .out .println ("Newer Docker version available. Updating from " + installedVersion + " to " + latestVersion );
6668 } else {
@@ -87,7 +89,7 @@ private void ensureDockerInstalled() throws IOException {
8789 String arch = getArch ();
8890 String dockerUrl = String .format (DOCKER_DOWNLOAD_URL , arch , latestVersion );
8991 downloadAndExtract (dockerUrl , DOCKER_DIR );
90- Files .write (DOCKER_VERSION_FILE , latestVersion .getBytes ());
92+ Files .write (dockerVersionFile , latestVersion .getBytes ());
9193 }
9294 }
9395
@@ -104,7 +106,7 @@ private String getArch() {
104106 }
105107
106108 private void ensureRootlessScriptInstalled () throws IOException {
107- Path rootlessScriptPath = DOCKER_PATH .getParent ().resolve ("dockerd-rootless.sh" );
109+ Path rootlessScriptPath = dockerPath .getParent ().resolve ("dockerd-rootless.sh" );
108110 if (!Files .exists (rootlessScriptPath )) {
109111 System .out .println ("Downloading dockerd-rootless.sh script..." );
110112 downloadFile (DOCKER_ROOTLESS_SCRIPT_URL , rootlessScriptPath );
@@ -113,12 +115,12 @@ private void ensureRootlessScriptInstalled() throws IOException {
113115 }
114116
115117 private void ensureRootlessKitInstalled () throws IOException {
116- if (Files .exists (ROOTLESSKIT_PATH .resolve ("rootlesskit" ))) {
118+ if (Files .exists (rootlessKitPath .resolve ("rootlesskit" ))) {
117119 return ;
118120 }
119121 System .out .println ("RootlessKit not found. Downloading..." );
120122 String url = String .format (ROOTLESSKIT_DOWNLOAD_URL , ROOTLESSKIT_VERSION , getArch ());
121- downloadAndExtract (url , ROOTLESSKIT_PATH );
123+ downloadAndExtract (url , rootlessKitPath );
122124 System .out .println ("RootlessKit installed successfully." );
123125 }
124126
@@ -146,24 +148,29 @@ public void start() throws IOException, InterruptedException {
146148
147149 boolean forceRootless = Boolean .parseBoolean (System .getProperty ("docker.force.rootless" , "true" ));
148150
151+ ensureInstalled ();
149152 ProcessBuilder pb ;
150153 if (isRoot () && !forceRootless ) {
151154 System .out .println ("Running as root, starting dockerd with sudo." );
152- pb = new ProcessBuilder ("sudo" , DOCKER_PATH .toString (), "-H" , "unix://" + DOCKER_SOCKET_PATH );
155+ pb = new ProcessBuilder ("sudo" , dockerPath .toString (), "-H" , "unix://" + dockerSocketPath . toString () );
153156 } else {
154157 System .out .println ("Attempting to start in rootless mode using dockerd-rootless.sh." );
155158
159+ ensureRootlessScriptInstalled ();
160+ ensureRootlessKitInstalled ();
161+ ensureSlirp4netnsInstalled ();
162+
156163 Path runDir = DOCKER_DIR .resolve ("run" );
157164 Path dataDir = DOCKER_DIR .resolve ("data" );
158165 Path configDir = DOCKER_DIR .resolve ("config" );
159166 runDir .toFile ().mkdirs ();
160167 dataDir .toFile ().mkdirs ();
161168 configDir .toFile ().mkdirs ();
162169
163- pb = new ProcessBuilder (DOCKER_PATH .getParent ().resolve ("dockerd-rootless.sh" ).toString ());
170+ pb = new ProcessBuilder (dockerPath .getParent ().resolve ("dockerd-rootless.sh" ).toString ());
164171
165172 String path = pb .environment ().getOrDefault ("PATH" , "" );
166- pb .environment ().put ("PATH" , SLIRP4NETNS_DIR + File .pathSeparator + ROOTLESSKIT_PATH + File .pathSeparator + DOCKER_PATH .getParent ().toString () + File .pathSeparator + path );
173+ pb .environment ().put ("PATH" , SLIRP4NETNS_DIR + File .pathSeparator + rootlessKitPath + File .pathSeparator + dockerPath .getParent ().toString () + File .pathSeparator + path );
167174 pb .environment ().put ("XDG_RUNTIME_DIR" , runDir .toString ());
168175 pb .environment ().put ("XDG_DATA_HOME" , dataDir .toString ());
169176 pb .environment ().put ("XDG_CONFIG_HOME" , configDir .toString ());
@@ -181,7 +188,7 @@ public void start() throws IOException, InterruptedException {
181188 @ Override
182189 public DockerClient getClient () {
183190 if (this .dockerClient == null ) {
184- String socketPath = DOCKER_SOCKET_PATH .toString ();
191+ String socketPath = dockerSocketPath .toString ();
185192 DefaultDockerClientConfig config = DefaultDockerClientConfig .createDefaultConfigBuilder ()
186193 .withDockerHost ("unix://" + socketPath ).build ();
187194
@@ -290,11 +297,11 @@ private void downloadAndExtract(String urlString, Path destinationDir) throws IO
290297
291298 @ SuppressWarnings ("BusyWait" )
292299 private boolean waitForSocket () throws InterruptedException {
293- System .out .println ("Waiting for Docker socket to be available at " + DOCKER_SOCKET_PATH + "..." );
300+ System .out .println ("Waiting for Docker socket to be available at " + dockerSocketPath + "..." );
294301 long timeoutMillis = TimeUnit .SECONDS .toMillis (30 );
295302 long startTime = System .currentTimeMillis ();
296303 while (System .currentTimeMillis () - startTime < timeoutMillis ) {
297- if (Files .exists (DOCKER_SOCKET_PATH )) {
304+ if (Files .exists (dockerSocketPath )) {
298305 System .out .println ("Docker socket found." );
299306 return true ;
300307 }
0 commit comments