diff --git a/samples/docker_wrapper/Makefile b/samples/docker_wrapper/Makefile
index f735ec6880fc73cbd02fbba35bc408661b99fa17..28a0a2631d956a20d51b533472f24ebe668874b2 100644
--- a/samples/docker_wrapper/Makefile
+++ b/samples/docker_wrapper/Makefile
@@ -31,6 +31,11 @@ ifdef BUILD_APPS_WITH_VCPKG
     -L$(VCPKG_DIR)/lib
 endif
 
+ifdef BUILD_WITH_MINGW
+  MAKEFILE_LDFLAGS += \
+    -lws2_32
+endif
+
 all: docker_wrapper
 
 libstdc++.a:
diff --git a/samples/docker_wrapper/docker_wrapper.cpp b/samples/docker_wrapper/docker_wrapper.cpp
index fe0a78834284d2508a5ebc97b333bff73ad1d1e4..ef6118adf5657cbb0a8ef9aeabf6eb746c75bf05 100644
--- a/samples/docker_wrapper/docker_wrapper.cpp
+++ b/samples/docker_wrapper/docker_wrapper.cpp
@@ -17,6 +17,7 @@
 
 // docker_wrapper: run a BOINC job in a Docker container,
 //      and interface between the BOINC client and the container
+// See https://github.com/BOINC/boinc/wiki/Docker-apps#the-docker-wrapper
 //
 // docker_wrapper [options] arg1 arg2 ...
 // options:
@@ -92,6 +93,7 @@
 
 #include "util.h"
 #include "boinc_api.h"
+#include "network.h"
 
 #ifdef _WIN32
 #include "win_util.h"
@@ -128,6 +130,10 @@ struct CONFIG {
         // use this as the image name, and don't delete it when done.
         // For testing.
     bool use_gpu;
+        // tell Docker to enable GPU access
+    int web_graphics_guest_port;
+        // map this to a host port,
+        // and inform the client using boinc_web_graphics_url()
     vector<string> mounts;
         // -v args in create container
     vector<string> portmaps;
@@ -141,6 +147,11 @@ struct CONFIG {
             fprintf(stderr, "   project dir mounted at: %s\n", project_dir_mount.c_str());
         }
         fprintf(stderr, "   use GPU: %s\n", use_gpu?"yes":"no");
+        if (web_graphics_guest_port) {
+            fprintf(stderr, "   Web graphics guest port: %d\n",
+                web_graphics_guest_port
+            );
+        }
         for (string& s: mounts) {
             fprintf(stderr, "   mount: %s\n", s.c_str());
         }
@@ -202,6 +213,11 @@ int parse_config_file() {
         config.use_gpu = x->as<bool>();
     }
 
+    x = v.find("web_graphics_guest_port");
+    if (x) {
+        config.web_graphics_guest_port = x->as<int>();
+    }
+
     x = v.find("mount");
     if (x) {
         const toml::Array& ar = x->as<toml::Array>();
@@ -373,6 +389,26 @@ int create_container() {
         strcat(cmd, " --gpus all");
     }
 
+    // web graphics
+    //
+    if (config.web_graphics_guest_port) {
+        int host_port;
+        retval = boinc_get_port(false, host_port);
+        if (retval) {
+            fprintf(stderr, "can't allocated host port for web graphics\n");
+        } else {
+            fprintf(stderr, "web graphics: host port %d, guest port %d\n",
+                host_port, config.web_graphics_guest_port
+            );
+            snprintf(buf, sizeof(buf), " -p %d:%d",
+                host_port, config.web_graphics_guest_port
+            );
+            strcat(cmd, buf);
+            snprintf(buf, sizeof(buf), "http://localhost:%d", host_port);
+            boinc_web_graphics_url(buf);
+        }
+    }
+
     strcat(cmd, " ");
     strcat(cmd, image_name);
     retval = docker_conn.command(cmd, out);
diff --git a/win_build/docker_wrapper.vcxproj b/win_build/docker_wrapper.vcxproj
index e445e797bea6ceed6fefbe4a023564aa2a6fed15..d5e93d4aaeb21276c619350a3b3afeae2e1fb47c 100644
--- a/win_build/docker_wrapper.vcxproj
+++ b/win_build/docker_wrapper.vcxproj
@@ -15,6 +15,7 @@
       <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
+      <AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalDependencies Condition="'$(Configuration)'=='Debug'">libcmtd.lib;libcpmtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalDependencies Condition="'$(Configuration)'=='Release'">libcmt.lib;libcpmt.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Console</SubSystem>