如何配置docker通過代理服務器拉取鏡像

如果 docker 所在的環境是通過代理服務器和互聯網連通的,那麼需要一番配置才能讓 docker 正常從外網正常拉取鏡像。然而僅僅通過配置環境變量的方法是不夠的。本文結合已有文檔,介紹如何配置代理服務器能使docker正常拉取鏡像。

本文使用的docker 版本是

docker --version
Docker version 24.0.2, build cb74dfc

問題現象

如果不配置代理服務器就直接拉鏡像,docker 會直接嘗試連接鏡像倉庫,並且連接超時報錯。如下所示:

$ docker pull busybox
Using default tag: latest
Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled 
while waiting for connection (Client.Timeout exceeded while awaiting headers)

容易誤導的官方文檔

有這麼一篇關於 docker 配置代理服務器的 官方文檔 ,如果病急亂投醫,直接按照這篇文章配置,是不能成功拉取鏡像的。

我們來理解一下這篇文檔,文檔關鍵的原文摘錄如下:

If your container needs to use an HTTP, HTTPS, or FTP proxy server, you can configure it in different ways: Configure the Docker client On the Docker client, create or edit the file ~/.docker/config.json in the home directory of the user that starts containers.

...

When you create or start new containers, the environment variables are set automatically within the container.

這篇文檔說:如果你的 容器 需要使用代理服務器,那麼可以以如下方式配置: 在運行容器的用戶 home 目錄下,配置 ~/.docker/config.json 文件。重新啓動容器後,這些環境變量將自動設置進容器,從而容器內的進程可以使用代理服務。

所以這篇文章是講如何配置運行 容器 的環境,與如何拉取鏡像無關。如果按照這篇文檔的指導,如同南轅北轍。

要解決問題,我們首先來看一般情況下命令行如何使用代理。

環境變量

常規的命令行程序如果要使用代理,需要設置兩個環境變量:HTTP_PROXYHTTPS_PROXY 。但是僅僅這樣設置環境變量,也不能讓 docker 成功拉取鏡像。

我們仔細觀察 上面的報錯信息,有一句說明了報錯的來源:

Error response from daemon:

因爲鏡像的拉取和管理都是 docker daemon 的職責,所以我們要讓 docker daemon 知道代理服務器的存在。而 docker daemon 是由 systemd 管理的,所以我們要從 systemd 配置入手。

正確的官方文檔

關於 systemd 配置代理服務器的 官方文檔在這裏,原文說:

The Docker daemon uses the HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environmental variables in its start-up environment to configure HTTP or HTTPS proxy behavior. You cannot configure these environment variables using the daemon.json file.

This example overrides the default docker.service file.

If you are behind an HTTP or HTTPS proxy server, for example in corporate settings, you need to add this configuration in the Docker systemd service file.

這段話的意思是,docker daemon 使用 HTTP_PROXY, HTTPS_PROXY, 和 NO_PROXY 三個環境變量配置代理服務器,但是你需要在 systemd 的文件裏配置環境變量,而不能配置在 daemon.json 裏。

具體操作

下面是來自 官方文檔 的操作步驟和詳細解釋:

1、創建 dockerd 相關的 systemd 目錄,這個目錄下的配置將覆蓋 dockerd 的默認配置

$ sudo mkdir -p /etc/systemd/system/docker.service.d

新建配置文件 /etc/systemd/system/docker.service.d/http-proxy.conf,這個文件中將包含環境變量

[Service]
Environment="HTTP_PROXY=http://proxy.example.com:80"
Environment="HTTPS_PROXY=https://proxy.example.com:443"

如果你自己建了私有的鏡像倉庫,需要 dockerd 繞過代理服務器直連,那麼配置 NO_PROXY 變量:

[Service]
Environment="HTTP_PROXY=http://proxy.example.com:80"
Environment="HTTPS_PROXY=https://proxy.example.com:443"
Environment="NO_PROXY=your-registry.com,10.10.10.10,*.example.com"

多個 NO_PROXY 變量的值用逗號分隔,而且可以使用通配符(*),極端情況下,如果 NO_PROXY=*,那麼所有請求都將不通過代理服務器。

重新加載配置文件,重啓 dockerd

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

檢查確認環境變量已經正確配置:

$ sudo systemctl show --property=Environment docker

從 docker info 的結果中查看配置項。

這樣配置後,應該可以正常拉取 docker 鏡像。

結論

docker 鏡像由 docker daemon 管理,所以不能用修改 shell 環境變量的方法使用代理服務,而是從 systemd 角度設置環境變量。

參考資料
https://www.lfhacks.com/tech/pull-docker-images-behind-proxy/#correct
https://stackoverflow.com/questions/69047394/cant-pull-docker-image-behind-a-proxy
https://mikemylonakis.com/unix/docker-proxy/
https://docs.docker.com/config/daemon/systemd/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章