Docker守护进程配置代理

Docker守护进程配置代理 基础理论部分引言在日常的工作中我们使用docker拉取镜像的时候总是会出现一些问题。国内镜像站能解决大部分拉取需求但在编译依赖GitHub源码、拉取新版镜像、或构建过程中涉及外部插件下载时仍需稳定的外部访问。这一篇博客是笔者最近在工作中找到的一些简单的处理办法在这里做一个梳理和总结。Docker架构首先有必要强调一下Docker的架构设计这个是我们深入的重要的前提概念。Docker 架构是基于客户端-服务器模式的其中包括多个关键组件确保容器化应用的高效构建、管理和运行。Docker 的架构设计使得开发者能够轻松地将应用程序与其所有依赖封装在一个可移植的容器中并在不同的环境中一致地运行。Docker 使用客户端-服务器 (C/S) 架构模式使用远程 API 来管理和创建 Docker 容器。Docker 容器通过 Docker 镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类。—— Docker架构 | 菜鸟教程https://www.runoob.com/docker/docker-architecture.htmlhttps://www.runoob.com/docker/docker-architecture.html也就是说我们平时敲击的命令docker run, docker build, docker pull 都是在Docker 客户端Client上随后客户端会通过 REST API 或 Unix 套接字与 Docker 守护进程进行通信。这是我们最常使用也最熟悉的组件部分是操作用的命令行工具。Docker守护进程dockerd是Docker架构的核心以后台进程的方式运行监听来自Docker 客户端的API请求。可以看到它主要负责了对容器、镜像等Docker对象的管理。这里来到了重点也就是说我们在敲击命令行的时候docker pull image实际上 docker CLI调用了API与守护进程dockerd进行通讯随后dockerd再根据配置去与Registry镜像存储仓库进行交互上传或下载。进程的网络访问一个进程是如何访问网络的这样讲可能过于抽象或者说从更底层来讲网络是什么为什么我们需要网络网络是用于传输、交换数据和信息的一种抽象模型。我们先从最基础的本机网络下不同进程访问交互的策略。这也有一个专用的名词进程间通信IPC Interprocess communication我们主要讨论套接字通信Socket。套接字是一种进程间通信机制与其他通信机制不同的是它可用于不同机器间的进程通信。它是计算机网络中实现进程间通信的端点和API接口位于应用层和传输层之间负责将应用程序的数据通过网络协议进行传输。实质上它是操作系统提供的一套网络编程接口把复杂的网络协议如TCP/IP封装成了简单的函数供开发者调用。在使用过程中Socket通过结合IP地址和端口号唯一标识了在网络上一个通信的进程是一个通信的端点。一个完整的Socket通信通信意味着双向由“源地址IP、源端口、目的IP地址、目的端口”四元组来确定。接下来的情况也就是进程要访问某个url资源比如说https://www.baidu.com/s?wd进程间通信首先会解析URL提取主机名www.baidu.com、端口https默认是443、和资源路径s?wd进程间通信接着是DNS解析向域名服务器发送解析请求获得目标主机的实际IP地址随后建立Socket通信信道TCP类型的可靠流式通信获得一个文件描述符接着通过五元组建立连接源IP源端口目标IP目标端口协议类型整个互联网上便唯一标识这条连接接着是TCP三次握手建立TCP连接随后是TLS/SSL握手交换密钥保证安全性HTTPS加密随后进程开始通过Socket发送HTTP请求进程在Socket上写入HTTP协议准许的各种方法GET /s?wd进程间通信接着进程从Socket上读取响应数据最后便是关闭Socket连接断开这条独特的管道close(fd)。代理做了什么没有代理的情况下进程与远程服务器建立Socket通信直接通信。有了代理之后进程先与代理服务器建立第一条Socket随后代理服务器与远程服务器建立第二条Socket代理在两条Socket之间转发数据。192.168.1.100:1080 - 192.168.1.102:8388 //第一条socket192.168.1.102:12345 - 123.106.216.34:433 //第二条socketDocker Deamon的情况用户键入 proxychains docker pulldocker客户端创建Socket调用 docker daemon 请求和命令docker daemon收到i请求并执行命令。systemd 是现代 Linux 发行版最核心的初始化系统Init System和服务管理器作为 PID 1 经常运行。它用于启动、管理和监控系统服务。systemd 以并行方式加载单元Units通过依赖关系Requires/Wants和顺序关系After/Before确保服务依序启动并利用cgroups监控进程。核心流程包括读取配置文件、解析依赖、执行与启动ExecStartPre、启动服务ExecStart及最终注册服务状态。加载配置解析/etc/systemd/system/ 或 /usr/lib/systemd/system/ 下的 .service单元文件。dockerd 是由 systemd 管理的系统服务。其配置文件也由 systemd 同一解析和管理。当我们需要网络方面配置代理时必须通过 systemd 内部的进行处理。systemd 会根据配置文件为该进程设置环境变量设置权限、资源限制等等随后启动该进程。也就是说容器运行时所有的环境变量全部继承于 systemd 设置的环境变量。读取主配置文件 /etc/systemd/system/docker.service读取 Drop-in 目录用来覆盖和拓展上面的配置 /etc/systemd/system/docker.service.d/*.conf合并配置 Drop-in 覆盖主配置准备环境变量 env { ... }执行 /usr/bin/dockerd -H fd:// envdockerd 进程启动继承环境变量。dockerd 运行时读取$HTTP_PROXY等变量用于网络请求具体实践ss2的源代码编译作者选择的是最新版本的 ss2-go 随后使用 go 进行编译打包成二进制可执行文件。ss2 分为客户端和服务端。我们有自己购买的境外服务器的话就可以将 ss2 配置在境外服务器上作为代理服务器开放对应的端口这样也会更加安全。在代理服务器上使用 ss2 配置加密方式、密钥和主机端口。在 docker 运行的我们的生产环境服务器上使用 ss2 客户端命令使用对应的加密方式、密钥和代理服务器的 IP 与端口进行远程连接。成功的话就可以看见双向的 socks5 连接建立。dockerd 守护进程配置在 /etc/systemd/system/docker.service.d/ 位置处新建 proxy.conf 文件。写入环境变量配置。参照具体的代理中的实际配置。如代理中是 本机IP:本机端口 -- 代理服务器IP:代理端口则在中配置stmaster:~/workplace/module/k8s/kube-prometheus$ cat /etc/systemd/system/docker.service.d/proxy.conf.bak [Service] EnvironmentHTTP_PROXYhttp://127.0.0.1:8118 EnvironmentHTTPS_PROXYhttp://127.0.0.1:8118 stmaster:~/workplace/module/k8s/kube-prometheus$接着重新载入新的配置systemctl daemon-reload systemctl restart docker.service现在docker 就会从配置文件中加载环境变量也就是示例中的 127.0.0.1:8118 流量也会随之使用代理了注意在拉取完更新完之后如果之后不需要这个代理了最好及时移除。就像这里我把proxy.conf 文件修改了后缀 proxy.conf.bak 随后重载重启这样 systemd 就不会自动再读取这个配置文件并注入了