Reliable NO_PROXY Rules for RAGFlow MCP Clients in Docker
Proxy environment variables can prevent RAGFlow from reaching a local or internal Model Context Protocol (MCP) endpoint. A common response is to add localhost or a CIDR block such as 127.0.0.0/8 to NO_PROXY. That may work in one environment and fail in another.
The reliable approach is to inject proxy variables into the correct container explicitly, use the exact host names or IP addresses that the application requests, and avoid relying on CIDR support unless the active HTTP client documents it.
Two Common Misunderstandings
A Compose environment file does not automatically populate a container
Docker Compose commonly reads a project .env file for variable substitution. Reading that file does not mean every variable becomes part of a service’s runtime environment.
For example, this project-level file can provide a value for ${NO_PROXY}, but it does not by itself make NO_PROXY visible to the application in a container:
NO_PROXY=localhost,127.0.0.1,::1
Inject the variable explicitly through environment or env_file instead:
services:
ragflow:
environment:
NO_PROXY: ${NO_PROXY}
no_proxy: ${NO_PROXY}
HTTP_PROXY: ${HTTP_PROXY}
HTTPS_PROXY: ${HTTPS_PROXY}
Alternatively, use a service environment file:
services:
ragflow:
env_file:
- ./ragflow.env
The ragflow.env file is then part of the service configuration and its values are available to the process in the container.
After changing the service environment, recreate the affected container. A restarted application process cannot see environment values that Docker never injected.
CIDR notation is not a portable NO_PROXY rule
Entries such as 10.0.0.0/8 and 127.0.0.0/8 are not defined consistently across HTTP clients. Treating CIDR as a universal NO_PROXY feature makes deployments fragile.
The most broadly reliable forms are:
- an exact host name, such as
localhost; - an exact IP address, such as
127.0.0.1; - a domain suffix, such as
.yourdomain.com; - a host with an optional port, such as
localhost:9382.
For loopback traffic, include both address families explicitly:
NO_PROXY=localhost,127.0.0.1,::1
no_proxy=localhost,127.0.0.1,::1
Keep both uppercase and lowercase forms when multiple tools or subprocesses are involved. Different clients and runtimes do not always use the same spelling.
localhost Means the Current Container
Inside a container, localhost and 127.0.0.1 point back to that same container. They do not refer to the Windows host.
When a container must connect to a service running on Docker Desktop’s Windows host, use host.docker.internal as the target and include that exact name in the bypass list:
NO_PROXY=localhost,127.0.0.1,::1,host.docker.internal
no_proxy=localhost,127.0.0.1,::1,host.docker.internal
If host.docker.internal is omitted, it does not match a localhost rule and can be sent through the proxy. Likewise, adding localhost does not bypass a request made to a container DNS name, an internal load balancer name, or a different IP address.
The effective destination must match the actual URL used by the MCP client, not the address that was intended during configuration.
Python Client Behavior Is Different by Library
Python does not provide one uniform implementation of proxy bypass rules. The library making the MCP request determines what syntax is honored.
| Client | Practical guidance for CIDR entries |
|---|---|
urllib.request |
Does not support CIDR in proxy_bypass_environment(). Use exact hosts, suffixes, IPs, and optional ports. |
requests |
Supports IPv4 CIDR entries such as 127.0.0.0/8 and 10.0.0.0/8. |
httpx |
Do not depend on CIDR behavior. Prefer explicit host names and IP addresses. |
aiohttp, SDKs, and curl-based clients |
Validate the implementation and version in use; behavior varies. |
For an MCP Python client using httpx, the conservative configuration is:
NO_PROXY=localhost,127.0.0.1,::1,host.docker.internal
no_proxy=localhost,127.0.0.1,::1,host.docker.internal
If the service deliberately uses another loopback address, for example 127.0.0.2, add that exact address. Do not assume that 127.0.0.0/8 will work for every client.
Docker Has Two Independent Proxy Layers
It is useful to separate two configurations that are often confused:
- Application proxy configuration controls requests made by a process inside the running container.
HTTP_PROXY,HTTPS_PROXY,ALL_PROXY, andNO_PROXYaffect this layer. - Docker daemon or BuildKit proxy configuration controls image pulls and image builds. Its configuration source is separate from the container environment.
Setting NO_PROXY for a Compose service can affect the RAGFlow MCP client, but it does not automatically change the proxy used to pull an image or build a Dockerfile. Configure those layers independently when necessary.
A Safer Compose Example
The following pattern keeps proxy configuration focused on the application process:
services:
ragflow:
environment:
HTTP_PROXY: ${HTTP_PROXY:-}
HTTPS_PROXY: ${HTTPS_PROXY:-}
ALL_PROXY: ${ALL_PROXY:-}
NO_PROXY: localhost,127.0.0.1,::1,host.docker.internal
http_proxy: ${HTTP_PROXY:-}
https_proxy: ${HTTPS_PROXY:-}
all_proxy: ${ALL_PROXY:-}
no_proxy: localhost,127.0.0.1,::1,host.docker.internal
Extend the two bypass entries with the exact internal MCP names that RAGFlow uses, for example ragflow-mcp, mcp-gateway.internal, or a specific private IP address. Do not add a broad CIDR block unless it has been tested with the exact client library and version.
Troubleshooting a Request That Still Uses the Proxy
If an MCP request still goes through the proxy, check these points in order:
- Inspect the proxy-related variables inside the running RAGFlow container. Do not rely on the host shell or the project
.envfile. - Confirm the final MCP endpoint URL. It may use
host.docker.internal,::1, a container DNS name, or an IP address instead of the literallocalhost. - Add that exact target to both
NO_PROXYandno_proxy. - Identify the HTTP library used by the MCP path and test the syntax against that library.
- Check whether
ALL_PROXYorall_proxyremains set. - Recreate the container after changing its service environment.
Avoid logging complete environment dumps in shared logs. Proxy URLs can contain usernames, passwords, or other sensitive information. Log only the relevant variable names and redact credentials.
Summary
Reliable proxy bypasses for RAGFlow MCP services require exact matching and explicit environment injection. A Compose project .env file alone does not place NO_PROXY in a container, and CIDR entries are not portable across Python HTTP clients.
For an httpx-based MCP client, explicitly include localhost, 127.0.0.1, ::1, and host.docker.internal when applicable. Then add the precise host names or IP addresses used by the service, recreate the container, and verify the variables from within the process boundary that makes the request.