66import com .github .dockerjava .httpclient5 .ApacheDockerHttpClient ;
77import com .github .dockerjava .transport .DockerHttpClient ;
88
9- import java .io .File ;
10- import java .io .IOException ;
11- import java .io .InputStream ;
9+ import java .io .*;
1210import java .net .HttpURLConnection ;
1311import java .net .URL ;
1412import java .nio .file .Files ;
@@ -105,6 +103,13 @@ private void downloadAndExtract(String urlString) throws IOException {
105103
106104 @ Override
107105 public void start () throws IOException , InterruptedException {
106+ if (!isAdministrator ()) {
107+ System .err .println ("\n ERROR: Docker daemon on Windows requires Administrator privileges.\n Please run your application or test as Administrator.\n " );
108+ throw new RuntimeException ("Administrator privileges required to start Docker daemon on Windows." );
109+ }
110+
111+ ensureContainersFeatureEnabled ();
112+
108113 this .dockerClient = tryConnectToExistingDocker ();
109114 if (this .dockerClient != null ) {
110115 return ;
@@ -123,15 +128,50 @@ public void start() throws IOException, InterruptedException {
123128 }
124129 }
125130
126- private DockerClient tryConnectToExistingDocker () {
127- String systemPipePath = "//./pipe/docker_engine" ;
128- File systemPipe = new File (systemPipePath );
131+ private void ensureContainersFeatureEnabled () throws IOException , InterruptedException {
132+ ProcessBuilder pb = new ProcessBuilder ("powershell.exe" , "-Command" , "Get-WindowsOptionalFeature -Online -FeatureName Containers" );
133+ pb .redirectErrorStream (true );
134+ Process process = pb .start ();
135+
136+ StringBuilder output = new StringBuilder ();
137+ try (BufferedReader reader = new BufferedReader (new InputStreamReader (process .getInputStream ()))) {
138+ String line ;
139+ while ((line = reader .readLine ()) != null ) {
140+ output .append (line ).append ("\n " );
141+ }
142+ }
143+
144+ process .waitFor ();
145+ String outputStr = output .toString ();
146+
147+ if (!outputStr .contains ("State : Enabled" )) {
148+ System .out .println ("Enabling Windows Containers feature (requires reboot)..." );
149+ ProcessBuilder enablePb = new ProcessBuilder ("powershell.exe" , "-Command" , "Enable-WindowsOptionalFeature -Online -FeatureName Containers -All" );
150+ enablePb .inheritIO ();
151+ Process enableProcess = enablePb .start ();
152+ enableProcess .waitFor ();
153+ System .err .println ("\n The Windows Containers feature was just enabled. Please reboot your computer and run again.\n " );
154+ throw new RuntimeException ("Windows Containers feature enabled. Reboot required." );
155+ }
156+ }
157+
158+ private boolean isAdministrator () {
159+ try {
160+ ProcessBuilder pb = new ProcessBuilder ("net" , "session" );
161+ pb .redirectErrorStream (true );
162+ Process process = pb .start ();
163+ return process .waitFor () == 0 ;
164+ } catch (IOException | InterruptedException e ) {
165+ return false ;
166+ }
167+ }
129168
130- if (systemPipe .exists ()) {
131- System .out .println ("Found existing Docker pipe at " + systemPipePath + ". Attempting to connect." );
169+ private DockerClient tryConnectToExistingDocker () {
170+ if (Files .exists (DOCKER_PIPE_PATH )) {
171+ System .out .println ("Found existing Docker pipe at " + DOCKER_PIPE_PATH + ". Attempting to connect." );
132172 try {
133173 DefaultDockerClientConfig config = DefaultDockerClientConfig .createDefaultConfigBuilder ()
134- .withDockerHost ("npipe://" + systemPipePath ).build ();
174+ .withDockerHost ("npipe://" + DOCKER_PIPE_PATH . toString (). replace ( " \\ " , "/" ) ).build ();
135175
136176 DockerHttpClient httpClient = new ApacheDockerHttpClient .Builder ()
137177 .dockerHost (config .getDockerHost ())
@@ -143,7 +183,7 @@ private DockerClient tryConnectToExistingDocker() {
143183 System .out .println ("Successfully connected to existing Docker daemon." );
144184 return client ;
145185 } catch (Exception e ) {
146- System .err .println ("Failed to connect to existing Docker daemon at " + systemPipePath + ": " + e .getMessage ());
186+ System .err .println ("Failed to connect to existing Docker daemon at " + DOCKER_PIPE_PATH + ": " + e .getMessage ());
147187 }
148188 }
149189 return null ;
0 commit comments