Introduction

Recently, due to certain indescribable reasons, Docker-related services have been banned, necessitating the use of proxies to pull or build images. However, there are some misconceptions when setting up proxies for Docker. Without carefully reading the official documentation, you might set up a proxy but still be unable to pull images!

Latest update:

As of 2024-09-10, Docker Registry access has gradually been restored, but Docker Hub is still inaccessible!

Architecture

Before clarifying how to set up Docker Proxy, it’s important to understand Docker’s overall architecture, which helps explain why multiple proxies need to be configured separately. Docker broadly refers to the entire toolchain and ecosystem, consisting of multiple components:

  • Docker Daemon
  • Docker Client
  • Docker Builder

Docker Daemon

When we pull images, we’re essentially sending requests from the Docker Client to the Docker Daemon, which executes the pull request. When unable to pull images, we need to configure a proxy for the Docker Daemon.

The Docker Daemon configuration file is located at:

  • Linux standard mode: /etc/docker/daemon.json
  • Linux Rootless mode: ~/.config/docker/daemon.json
  • Windows: C:\ProgramData\docker\config\daemon.json
  • macOS Docker Desktop: ~/.docker/config/daemon.json
  • macOS OrbStack: ~/.orbstack/config/docker.json
{
  "proxies": {
    "no-proxy": "*.local,localhost,127.0.0.0/8",
    "http-proxy": "http://IP_OR_DOMAIN:PORT",
    "https-proxy": "http://IP_OR_DOMAIN:PORT"
  }
}

Docker Daemon does not support the ALL_PROXY or all-proxy configuration.

Besides configuring daemon.json, we can also set up a proxy for Docker Daemon through Systemd service configuration:

sudo mkdir -p /etc/systemd/system/docker.service.d
touch /etc/systemd/system/docker.service.d/http-proxy.conf

The http-proxy.conf file content is as follows:

[Service]
Environment="HTTP_PROXY=http://proxy.example.com:PORT"
Environment="HTTPS_PROXY=http://proxy.example.com:PORT"
Environment="NO_PROXY=localhost,127.0.0.0/8"

Reload the service configuration and restart the Docker Daemon service:

sudo systemctl daemon-reload
sudo systemctl restart docker

Verify that the results meet expectations:

sudo systemctl show --property=Environment docker

Environment=HTTP_PROXY=http://proxy.example.com:3128 HTTPS_PROXY=http://proxy.example.com:3129 NO_PROXY=localhost,127.0.0.0/8

Docker Client

When we need to run containers or build images using a proxy, we need to configure the Docker Client’s proxy.

{
  "proxies": {
    "default": {
      "noProxy": "*.test,localhost,127.0.0.0/8",
      "allProxy": "socks5://host.docker.internal:PORT",
      "httpProxy": "http://host.docker.internal:PORT",
      "httpsProxy": "http://host.docker.internal:PORT"
    }
  }
}

After setting up the Docker Client proxy, you don’t need to restart Docker, but you need to understand that Docker Client injects proxies into containers through environment variables. This means that for containers that already exist, the configuration changes won’t take effect. You must stop and delete the container, then recreate it using docker run or docker compose up to add the above proxy configuration to the container’s environment variables.

Besides this method, you can also set temporary proxies in the CLI using –env and –build-arg:

docker build --build-arg HTTP_PROXY="http://proxy.example.com:PORT" .
docker run --env HTTP_PROXY="http://proxy.example.com:PORT" redis

Summary

Although Docker’s proxy configuration is relatively complex, once organized, it becomes very clear:

  • Docker Client Proxy: Responsible for proxy configuration during the docker run and docker build phases
  • Docker Daemon Proxy: Responsible for proxy configuration during the docker push and docker pull phases

I hope this is helpful, Happy hacking…