Docker环境运行Squid

Ubuntu的母公司Canonical在dockerhub官方维护了一个基于 Ubuntu LTS 的squid镜像 ubuntu/squid Docker Image ,并提供了长期安全维护。本文作为 Kubernetes部署Squid快速起步 的前奏,在本地docker环境运行 Squid代理服务 测试。

准备工作

  • 准备物理主机上的squid缓存和日志目录,这样docker容器挂载卷可以加速IO性能,也能够保证缓存数据和日志不丢失:

在物理主机创建squid容器的卷
BASE_DIR=/Users/huataihuang/docs/studio
VAR_DIR=${BASE_DIR}/var
ETC_DIR=${BASE_DIR}/etc

mkdir -p ${VAR_DIR}/log/squid
mkdir -p ${VAR_DIR}/spool/squid
mkdir -p ${VAR_DIR}/cache/squid
mkdir -p ${ETC_DIR}/squid
fedora默认初始squid配置: /etc/squid/squid.conf
acl localnet src 0.0.0.1-0.255.255.255	# RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8		# RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10		# RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16 	# RFC 3927 link-local (directly plugged) machines
acl localnet src 172.16.0.0/12		# RFC 1918 local private network (LAN)
acl localnet src 192.168.0.0/16		# RFC 1918 local private network (LAN)
acl localnet src fc00::/7       	# RFC 4193 local private network range
acl localnet src fe80::/10      	# RFC 4291 link-local (directly plugged) machines

acl SSL_ports port 443
acl Safe_ports port 80		# http
acl Safe_ports port 21		# ftp
acl Safe_ports port 443		# https
acl Safe_ports port 70		# gopher
acl Safe_ports port 210		# wais
acl Safe_ports port 1025-65535	# unregistered ports
acl Safe_ports port 280		# http-mgmt
acl Safe_ports port 488		# gss-http
acl Safe_ports port 591		# filemaker
acl Safe_ports port 777		# multiling http

http_access deny !Safe_ports

http_access deny CONNECT !SSL_ports

http_access allow localhost manager
http_access deny manager

http_access allow localnet
http_access allow localhost

http_access deny all

http_port 3128

cache_dir ufs /var/cache/squid 100 16 256

coredump_dir /var/spool/squid

refresh_pattern ^ftp:		1440	20%	10080
refresh_pattern ^gopher:	1440	0%	1440
refresh_pattern -i (/cgi-bin/|\?) 0	0%	0
refresh_pattern .		0	20%	4320

运行

  • 执行运行命令:

docker run运行squid容器,注意取消了 --network kind 参数(见上文),采用默认网络
# 请根据实际目录修订 BASE_DIR
BASE_DIR=/Users/huataihuang/docs/studio

squid_version=5.2-22.04_beta

docker run -dt --name squid --hostname squid \
    -e TZ=Asia/Shanghai -p 3128:3128 \
    -v ${BASE_DIR}/var/log/squid:/var/log/squid \
    -v ${BASE_DIR}/var/spool/squid:/var/spool/squid \
    -v ${BASE_DIR}/var/cache/squid:/var/cache/squid \
    -v ${BASE_DIR}/etc/squid/squid.conf:/etc/squid/squid.conf \
    ubuntu/squid:${squid_version}
ubuntu/squid镜像参数

参数

说明

-e TZ=Asia/Shanghai

时区

-p 3128:3128

输出代理服务

-v /Users/huataihuang/docs/studio/var/log/squid:/var/log/squid

存储squid日志目录

-v /Users/huataihuang/docs/studio/var/spool/squid:/var/spool/squid

存储squid缓存目录

-v /Users/huataihuang/docs/studio/etc/squid/squid.conf:/etc/squid/squid.conf

squid主配置文件

-v /path/to/config/snippet:/etc/squid/conf.d/snippet.conf

squid.conf配置包含的配置片段(未使用)

后期配置(关键点)

备注

我最初考虑将这个 squid 容器连接到 macOS工作室 构建的 kind(本地docker模拟k8s集群) 内置的 kind bridge网络,这样就可以同时为整个 dev kind 集群提供代理。但是我发现 docker build 不能指定具体网络( docker run 可以),而只能指定网络模式( bridge 或 host ),这导致将 squid 容器运行在 kind 代理后就不能给默认网路进行代理。

标准方法,对于 kind 网络上的 node 以及 conatiner 还是采用标准的 Kubernetes部署Squid快速起步 构建的 pod ,将Kubernetes化的 Squid代理服务 来提供 kind 网络代理加速。

我想了一下,可以在这个docker化的 squid 容器中插入多个网络接口,为 docker 所有网络提供代理服务。但是由于每个docker网络的网段不同,分配IP不同,所以配置代理的时候不使用IP地址,而是采用域名解析:

  • 发现Docker的DNS解析也比较复杂,需要研究 CoreDNS

  • 比较简单的方法是将 /etc/hosts 文件bind到容器内部,这样可以控制容器主机名解析不同网段 squid 的对应IP

当然,在 Kubernetes 集群,采用静态 /etc/hosts 维护繁琐易出错,所以采用 CoreDNS 来构建解析

参考 修复kind集群重启异常 相似方法,设置 squid 容器固定IP地址:

  • 首先获取docker容器的所有IP地址:

获取docker容器的IP地址
docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
  • 我尝试以下命令将 squid 容器的IP地址固定为当前动态分配的IP地址:

    docker stop squid
    docker network connect --ip 172.17.0.3 "bridge" "squid"
    

但是这里会报错:

Error response from daemon: user specified IP address is supported on user defined networks only

但是考虑到这个容器 squid` 绑定了 0.0.0.0:3128 ,是否可以作为通用的访问代理呢?类似在 kind集群本地Registry 通过 localhost:5001 访问本地的 registry ,是否可以在容器中通过访问 localhost:3128 访问代理服务器呢?

验证不行

检查

一切运行正常,检查 docker ps 可以看到:

CONTAINER ID   IMAGE                                COMMAND                  CREATED         STATUS         PORTS                       NAMES
cc2e1ee10eba   ubuntu/squid:5.2-22.04_beta          "entrypoint.sh -f /e…"   4 minutes ago   Up 4 minutes   0.0.0.0:3128->3128/tcp      squid
  • 检查squid日志:

    docker logs -f squid
    
  • 进入容器内部检查:

    docker exec -it squid /bin/bash
    

在容器内部可以使用 APT包管理 安装 Ubuntu Linux 相关操作系统工具,方便排查一些问题,例如 apt install iproute2 工具可以帮助检查容器IP地址和路由等

备注

我是在 macOS工作室 上运行 Docker Desktop for macOS,测试不能使用本物理主机的系统级代理设置,会导致docker出去的http/https被反向代理回去(似乎)。采用chrome结合SwitchyOmega设置chrome自身代理来进程测试(因为chrome可以不依赖系统代理设置) ,就能够验证squid是否工作正常。

下一步

参考