Slow GitHub clones, Docker image pulls, and npm installs can look like the same network problem, but they use different clients, protocols, caches, and configuration layers. A browser opening a website successfully does not prove that Git, the Docker daemon, or Node.js is using the same route. The useful approach is to test each tool separately, identify where the transfer stalls, and change one setting at a time.
This guide focuses on developer workstations and CI builds. It covers proxy routing, DNS, transfer checks, command-line configuration, and credential safety. The goal is not to make every connection use a proxy: it is to route the traffic that needs one without breaking local services, leaking tokens, or hiding a DNS or certificate problem behind repeated retries.
Map the connection path before changing settings
A Git operation may use HTTPS or SSH, depending on the repository URL. npm typically retrieves package metadata and tarballs from its configured registry. Docker image pulls are handled by the Docker daemon, which can have proxy settings separate from the shell and Docker CLI. In a container build, the build process may also need its own network configuration. These distinctions explain why setting a proxy in one terminal window may fix npm but leave image pulls unchanged.
Start by writing down the exact failing operation and its destination. Record whether it is a clone, fetch, package install, image pull, or build step; whether it fails on the host or inside a container; and whether it fails on every network or only one. Note the error text and the time at which the request stalls. A timeout during name resolution points in a different direction from a TLS certificate error or a transfer that begins and then stops.
Check the URL and tool configuration before changing the network. For Git, inspect the remote with git remote -v and review relevant settings with git config --show-origin --get-regexp 'http\\..*|https\\..*|url\\..*'. For npm, inspect the effective registry with npm config get registry. For Docker, confirm the image name and tag, then check whether the daemon is running locally or on a separate host. The client’s environment and the daemon’s environment may not be the same.
Compare behavior with and without the suspected proxy or VPN route, where your network and organization policies permit that test. If only one tool fails, concentrate on that tool’s configuration rather than replacing system DNS or disabling security checks globally. If all three fail toward the same destination, investigate shared routing, DNS, firewall, or network restrictions first.
3
Tool paths to check: Git, Docker, npm
4
Signals: route, DNS, TLS, transfer
Test routing, DNS, and transfer separately
First check whether the affected hostname resolves. On systems with nslookup, run nslookup github.com or substitute the package registry or image registry that is failing. If available, dig can show the DNS response and the resolver that answered. A lookup failure is evidence about name resolution, not proof that the remote service is down. If your organization supplies DNS settings, use its documented resolver rather than copying addresses from an unrelated tutorial.
Next, test an HTTPS response from the same machine and shell that runs the failing command. For example, curl -I https://github.com checks whether an HTTP response can be obtained, while curl -I https://registry.npmjs.org/ checks a common npm registry endpoint. A response can confirm that a connection reached an HTTP server, but it does not prove that a large repository, package tarball, or container layer will transfer quickly. Some endpoints also treat a request for headers differently from a full download.
To distinguish connection setup from a slow body transfer, use curl’s timing output on a URL that is appropriate to test and that you are authorized to access. For instance, curl -L -o /dev/null -w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} first_byte=%{time_starttransfer} total=%{time_total}\\n' https://github.com/ reports stages of an HTTP request. These figures are measurements from your current machine and route, not a universal benchmark. Repeat the same test under comparable conditions before drawing a conclusion.
If DNS succeeds but the TLS handshake fails, inspect the system clock, proxy configuration, and any organization-managed certificate inspection. Do not “fix” certificate errors by disabling verification. A proxy that intercepts TLS may require a certificate installed through an approved IT process; an unknown certificate should be treated as a security warning. If the handshake completes but data transfer is slow, compare another permitted route and check whether the issue affects one destination or several.
- ✅ Keep a baseline test with the proxy or VPN route disabled only when policy allows it.
- ✅ Compare the same hostname and command across routes, recording the error and timing.
- ✅ Check whether the client, daemon, and container use the same DNS and proxy path.
- ❌ Do not replace certificate validation with an insecure setting to make a test pass.
- ❌ Do not assume a successful browser request proves command-line tools are routed correctly.
When a managed network, VPN client, or local proxy is involved, make sure the application is actually included in its routing rules. Some clients support system-wide routing; others offer rule-based or per-application modes. A command-line tool launched from a terminal may inherit environment variables, while a background service may not. If you use a compatible client with a subscription configuration, confirm that the selected profile and traffic mode cover the relevant destination rather than assuming that importing a subscription automatically routes every process.
Configure Git, npm, and Docker at the right layer
Git: proxy settings and clone choices
For an HTTPS remote, Git can use proxy values from environment variables such as HTTPS_PROXY, or from Git configuration. Prefer a temporary, per-command test before changing a global setting. For example, in a compatible shell, HTTPS_PROXY=http://proxy.example:8080 git ls-remote https://github.com/OWNER/REPO.git tests whether Git can list remote references through that proxy. Replace the example address with a proxy provided by your network administrator. Do not put a real password or token directly in a command that may be saved in shell history or process listings.
If a test confirms that a proxy is needed, configure it at the narrowest scope that fits your use: the current command, a single repository, or the user account. Git supports URL-specific configuration, which can avoid sending unrelated traffic through the same proxy. To remove a temporary setting, unset the environment variable or delete the exact configuration entry you added. Avoid accumulating multiple global proxy values, because it becomes difficult to tell which one is active.
For a large repository where you only need the latest files, consider git clone --depth 1 to reduce history transfer, or git clone --filter=blob:none for a partial clone that can retrieve file contents when needed. These options change what is initially downloaded and how later commands behave; they do not repair a broken route or guarantee that every project workflow supports a shallow or partial checkout. If you need full history, tags, submodules, or offline access to past versions, use the clone mode required by the project.
npm: check the registry and preserve the cache
Start with npm config get registry and confirm that the configured registry is intentional and trusted. A registry can be set in a project’s .npmrc, a user configuration file, environment variables, or a command-line option. Inspect the effective value and its source before editing files. Changing to an unfamiliar mirror may expose package names and metadata, serve stale content, or create an unexpected dependency source. Follow your organization’s registry policy when working on company projects.
npm can use proxy configuration, but it should match the proxy type and address provided for your environment. Test with a command-scoped setting or an approved environment variable first, then use a project or user configuration only if the behavior is consistent and intended. If authentication is required, use the credential mechanism recommended by the registry and keep tokens out of source control, command history, logs, and screenshots.
For repeat installs, preserve npm’s local cache instead of clearing it as a routine speed fix. In CI, use the platform’s supported cache mechanism for the npm cache directory and choose a cache key that changes when dependency lockfiles or relevant runtime settings change. Run npm ci when the project expects a clean, lockfile-based install. A warm cache can reduce repeated downloads, but it cannot supply uncached packages when the registry is unreachable, so keep a reliable registry route as well.
Docker: distinguish image pulls from build traffic
An image pull is usually performed by the Docker daemon, not by the shell process that invoked docker pull. If shell-level proxy variables have no effect, check the daemon’s documented proxy configuration for your operating system and installation method. Desktop installations, Linux services, and remote Docker contexts can have different settings. Restarting or reconfiguring a managed daemon may require administrator approval, so follow the relevant system instructions rather than editing a guessed configuration path.
Keep image pulling separate from network access during a Docker build. A daemon proxy may allow the base image to download while a package manager running in a build step still cannot reach its registry. Docker supports predefined proxy build arguments such as HTTP_PROXY and HTTPS_PROXY; pass them only through the approved mechanism for your builder, and avoid baking proxy credentials into image layers or build logs. Review the build output and final image configuration for accidental secrets.
Check whether the project already uses a trusted registry mirror or an internal cache. A mirror can improve repeat pulls when it is maintained for your environment, but a randomly selected public mirror is not a safe substitute for a verified source. Use a pinned image tag or digest according to the project’s release practice, and do not switch image sources solely because one endpoint responds faster.
Hands-on: isolate one slow transfer step by step
Choose one failing operation and avoid changing Git, npm, Docker, DNS, and the VPN profile all at once. If the problem is a repository clone, copy its remote URL and run git ls-remote first. This checks access to repository references without downloading the working tree. If that succeeds, retry the clone with the project’s expected options. A smaller clone can help identify whether the amount of transferred history matters, but keep the original command available so you can compare like with like.
- Capture the starting state. Note the remote or registry hostname, the exact command, the active network route, and whether proxy variables are set. Redact usernames, tokens, and private repository names before sharing logs.
- Test name resolution and HTTPS. Run a DNS lookup and a simple curl request from the same host. If the failing tool runs in a container or on a remote daemon, repeat the checks in that actual environment; host results do not establish container or daemon connectivity.
- Compare one route change. If policy allows, test with the intended proxy or VPN route and then with the permitted baseline route. Keep the destination and command constant. If the route changes DNS behavior, record that separately from the transfer result.
- Apply a narrow configuration. Change only the failing tool’s proxy or registry setting. Re-run the original operation, then verify that unrelated destinations and local services still work. Remove the test setting if it was temporary.
- Check for a cache opportunity. For Git, decide whether full history is actually needed. For npm and Docker, check the project’s existing cache or internal registry arrangement. Use cache configuration that is reproducible and approved, not a cache from an unknown source.
- Retest from a clean context. Confirm that the result is not dependent on an interactive shell variable that CI or a background daemon will not receive. Document the working configuration without recording credentials.
For a CI runner, examine the network boundary between the job container, runner host, and any remote build service. A variable defined in the job may reach a build step but not the Docker service that pulls the base image. Conversely, configuring the runner daemon may not pass a proxy into a package install inside the build. Use the CI platform’s secret store for credentials, limit secret exposure to the job that needs them, and avoid printing the environment for debugging.
Teams that need a managed route for developer tools can review the service details on VPNNR and then test the relevant client and application behavior in their own environment. That should be treated as a routing option to evaluate, not as a guarantee that every registry, repository, or CI provider will behave identically.
Keep builds repeatable and credentials safe
Once the slow step is understood, make the fix repeatable. Put non-secret project settings in version control only when they are intended to apply to every contributor. Keep personal proxy addresses, access tokens, and machine-specific certificates out of shared configuration. For CI, use protected variables or the platform’s secret manager and scope access to the jobs that need it. Avoid embedding credentials in Git remote URLs, Docker build arguments that are persisted, or npm configuration files that are committed.
Use lockfiles and the project’s supported install command so that speed improvements do not turn into dependency drift. Cache downloaded artifacts where the CI platform supports it, but define invalidation around lockfile or runtime changes rather than assuming a cache is always valid. For container builds, arrange layers so that stable dependency manifests can be reused before frequently changing application files, while respecting the project’s build requirements. Cache hits are an optimization, not a substitute for trustworthy package sources.
When a fix stops working, first check whether the route, proxy, registry, daemon, or CI runner changed. Retest DNS, TLS, and transfer as separate stages. If only one service is affected, capture a minimal, redacted diagnostic and consult the network or platform administrator. If a credential may have appeared in logs or a URL, rotate it through the service that issued it rather than merely deleting the visible copy.
Diagnose Git, Docker, and npm as separate network clients; verify DNS, TLS, and transfer independently; and apply the smallest supported proxy or cache change. Keep registry sources trusted and credentials out of commands, images, and logs.