Docker proxy setup involves configuring individual containers, docker-compose services, or the Docker daemon itself to route outbound network traffic through an intermediary proxy server for tasks like pulling images, building, or accessing external resources from within applications.
Why Use a Proxy with Docker?
Integrating a proxy with Docker environments addresses several common requirements:
- Internet Access Control: In corporate or restricted network environments, direct internet access from build servers or containers may be prohibited. A proxy acts as a controlled gateway.
- Security Scanning & Filtering: Proxies can intercept and scan outbound traffic from containers for malicious content or enforce content policies.
- Caching: Proxies can cache frequently accessed external resources (e.g., package manager repositories, base images), reducing bandwidth usage and accelerating builds/downloads.
- Anonymity/Geo-unblocking: While less common in enterprise setups, proxies can mask the origin IP or bypass geo-restrictions.
Types of Proxy Configurations
There are two primary contexts for proxying in Docker:
- Docker Daemon Proxy: Configures the Docker daemon itself to use a proxy for operations like pulling base images, accessing remote registries, or during the build process (for commands like
RUN apt-get update). - Container/Service Proxy: Configures individual containers or services within
docker-composeto use a proxy for their own outbound application traffic at runtime.
These configurations are independent and often both are required for a complete setup.
Docker Daemon Proxy Configuration
This method ensures that the Docker daemon's operations, including image pulls and some build steps, pass through the specified proxy.
For systemd-based Linux Hosts
Most modern Linux distributions use systemd. Create a drop-in directory for the Docker service:
sudo mkdir -p /etc/systemd/system/docker.service.d
Create a configuration file (e.g., http-proxy.conf) within this directory:
sudo nano /etc/systemd/system/docker.service.d/http-proxy.conf
Add the following content, replacing YOUR_PROXY_HOST and YOUR_PROXY_PORT with your proxy details:
[Service]
Environment="HTTP_PROXY=http://YOUR_PROXY_HOST:YOUR_PROXY_PORT"
Environment="HTTPS_PROXY=http://YOUR_PROXY_HOST:YOUR_PROXY_PORT"
Environment="NO_PROXY=localhost,127.0.0.1,::1,YOUR_DOCKER_NETWORK_CIDR,YOUR_INTERNAL_DOMAINS"
Note:
* HTTP_PROXY and HTTPS_PROXY should typically use http:// scheme, even for HTTPS traffic, as the proxy server handles the TLS negotiation.
* NO_PROXY is crucial. It prevents traffic to specified hosts or networks from going through the proxy. Include localhost, 127.0.0.1, ::1, and any Docker internal networks (e.g., 172.17.0.0/16 for the default bridge network, or custom network CIDRs) to ensure containers can communicate with each other and the host without issues. Also, add any internal domain names that should bypass the proxy.
Reload systemd and restart the Docker daemon for changes to take effect:
sudo systemctl daemon-reload
sudo systemctl restart docker
Verify by pulling an image:
docker pull alpine
If the proxy is configured correctly, this pull operation will go via the proxy.
For Docker CLI (Client-side Configuration)
This configuration affects the Docker client when interacting with registries. It's less common for daemon-wide proxying but useful for specific CLI operations.
Create or edit ~/.docker/config.json:
{
"proxies": {
"default": {
"httpProxy": "http://YOUR_PROXY_HOST:YOUR_PROXY_PORT",
"httpsProxy": "http://YOUR_PROXY_HOST:YOUR_PROXY_PORT",
"noProxy": "localhost,127.0.0.1,::1,YOUR_DOCKER_NETWORK_CIDR,YOUR_INTERNAL_DOMAINS"
}
}
}
This configuration applies to the user running the Docker CLI.
Container/Service Proxy Configuration
This method configures specific containers or docker-compose services to use a proxy for their runtime outbound traffic. This is distinct from the daemon proxy and is often necessary for applications running inside containers to access external resources through a proxy.
Using Dockerfile
You can set proxy environment variables directly in your Dockerfile. This bakes the proxy settings into the image.
FROM ubuntu:latest
# Set proxy for build time operations (e.g., apt-get update)
ENV HTTP_PROXY="http://YOUR_PROXY_HOST:YOUR_PROXY_PORT" \
HTTPS_PROXY="http://YOUR_PROXY_HOST:YOUR_PROXY_PORT" \
NO_PROXY="localhost,127.0.0.1,::1,YOUR_DOCKER_NETWORK_CIDR,YOUR_INTERNAL_DOMAINS"
RUN apt-get update && apt-get install -y curl
# These ENV variables will also be present at runtime unless overridden
CMD ["curl", "http://example.com"]
Considerations:
* Proxy credentials in Dockerfiles are a security risk. Consider using build arguments (ARG) or runtime environment variables (-e or environment in docker-compose.yml) instead.
* If the proxy is only needed during build, unset the variables at the end of the build stage in a multi-stage build or use RUN --mount=type=secret,id=proxy,target=/run/secrets/proxy-creds for more secure handling.
Using docker run
For individual containers, pass proxy settings using the -e flag:
docker run -e HTTP_PROXY="http://YOUR_PROXY_HOST:YOUR_PROXY_PORT" \
-e HTTPS_PROXY="http://YOUR_PROXY_HOST:YOUR_PROXY_PORT" \
-e NO_PROXY="localhost,127.0.0.1,::1,172.17.0.0/16,my-app-service" \
my-image:latest curl http://example.com
Using docker-compose.yml
For multi-service applications, docker-compose is the standard. Define proxy environment variables within the environment section of each service that requires proxy access:
version: '3.8'
services:
webapp:
image: my-webapp:latest
environment:
- HTTP_PROXY=http://YOUR_PROXY_HOST:YOUR_PROXY_PORT
- HTTPS_PROXY=http://YOUR_PROXY_HOST:YOUR_PROXY_PORT
- NO_PROXY=localhost,127.0.0.1,::1,your-db-service,your-cache-service,172.18.0.0/16 # Add internal service names and network CIDRs
# ... other service configurations
database:
image: postgres:13
# This service typically does not need proxy settings if it only communicates internally or is not outbound
# ... other service configurations
Note on NO_PROXY in docker-compose:
* Include localhost, 127.0.0.1, ::1.
* Include the names of other services within the same docker-compose network (e.g., your-db-service).
* Include the CIDR range of the Docker network created by docker-compose (e.g., 172.18.0.0/16 if your docker-compose network is in that range). You can inspect the network with docker network inspect <network_name> to find its CIDR.
External proxy.env File
For better management of sensitive or frequently changed proxy settings, you can define them in an external .env file and reference it in docker-compose.yml:
proxy.env:
HTTP_PROXY=http://YOUR_PROXY_HOST:YOUR_PROXY_PORT
HTTPS_PROXY=http://YOUR_PROXY_HOST:YOUR_PROXY_PORT
NO_PROXY=localhost,127.0.0.1,::1,your-db-service,your-cache-service,172.18.0.0/16
docker-compose.yml:
version: '3.8'
services:
webapp:
image: my-webapp:latest
env_file:
- ./proxy.env
# ... other service configurations
This approach is cleaner and allows for easy updates without modifying the docker-compose.yml directly.
SOCKS Proxy Configuration
While HTTP/HTTPS proxies are most common, some environments use SOCKS proxies. Docker does not natively support SOCKS proxy environment variables (SOCKS_PROXY, ALL_PROXY) in the same ubiquitous way as HTTP/HTTPS.
- Application-level: Most applications need explicit SOCKS support. If your application within the container supports SOCKS, you can pass
ALL_PROXYor similar variables. - Proxychains-NG: For applications that do not natively support SOCKS, tools like
proxychains-ngcan be installed inside the container to force traffic through a SOCKS proxy. This adds complexity and overhead.
For typical Docker deployments, HTTP/HTTPS proxying is preferred due to broader support.
Comparison of Proxy Configuration Methods
| Method | Scope | When to Use | Pros | Cons |
|---|---|---|---|---|
Docker Daemon (systemd) |
Host-wide Docker daemon operations | For all image pulls, build steps, and registry interactions on the host. | Centralized for daemon. Ensures all builds/pulls use proxy. | Requires systemd knowledge. Requires daemon restart. Does not affect runtime container applications. |
Docker CLI (config.json) |
User-specific Docker CLI operations | For a specific user's CLI commands that interact with registries. | User-specific, doesn't affect other users or daemon. | Only affects CLI, not daemon or container runtime. |
Dockerfile (ENV) |
Image build time & container runtime | When proxy settings are consistent for all instances of an image. | Self-contained within the image. Simple for development. | Bakes settings into image (less flexible). Security risk if credentials are included. |
docker run (-e) |
Single container runtime | For ad-hoc testing, specific container runs, or overriding Dockerfile settings. | Highly flexible, runtime-specific. | Cumbersome for multiple containers or docker-compose setups. |
docker-compose.yml (environment/env_file) |
Service-specific container runtime | For multi-service applications where each service has distinct proxy needs. | Cleanly defines settings per service. Supports external .env files for secrets/flexibility. |
Requires defining for each service. Does not affect daemon-level operations (e.g., docker-compose build). |
Troubleshooting Common Proxy Issues
- Verify Environment Variables: Inside a running container, use
docker exec -it <container_id> envto check ifHTTP_PROXY,HTTPS_PROXY, andNO_PROXYare correctly set. - Test Connectivity from Container:
bash docker exec -it <container_id> curl -v --proxy <YOUR_PROXY_HOST:YOUR_PROXY_PORT> http://example.com
This explicitly forcescurlto use the proxy, bypassing container environment variables, for direct testing. - Check Proxy Server Logs: Inspect your proxy server's access logs to see if traffic from the Docker host or containers is reaching it and being processed.
- Network Connectivity: Ensure the Docker host can reach the proxy server on the specified port. Use
curlortelnetfrom the Docker host. - Firewall Rules: Verify that no firewall (host, network, or proxy server) is blocking traffic between the Docker host/containers and the proxy server.
- DNS Resolution: Ensure DNS resolution works correctly inside the containers, especially for the proxy host itself and the target domains.
NO_PROXYConfiguration: Incorrect or incompleteNO_PROXYsettings often lead to internal communication failures. Ensure all internal networks, Docker bridge networks, and service names are listed.