Rootop 服务器运维与web架构

2025-08-21
发表者 Venus
docker pull配置代理服务拉取镜像已关闭评论

docker pull配置代理服务拉取镜像

配置http代理拉取官方仓库镜像
参考文档:https://docs.docker.com/engine/daemon/proxy/

# 将http代理配置到shell环境变量
export http_proxy=http://192.168.6.88:10810
export HTTP_PROXY=http://192.168.6.88:10810
export HTTPS_PROXY=http://192.168.6.88:10810
export https_proxy=http://192.168.6.88:10810

# 通过拉取镜像发现docker并不会使用这个代理,重启docker服务也并不会加载代理的环境变量
[root@localhost ~]# docker pull nginx
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官方是3种配置方法
1、配置systemd插件(drop-in)
[root@localhost ~]# mkdir -p /etc/systemd/system/docker.service.d
[root@localhost ~]# vi /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://192.168.6.88:10810"
Environment="HTTPS_PROXY=http://192.168.6.88:10810"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"

[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart docker

# 查看是否加载
[root@localhost ~]# systemctl show docker --property=Environment
Environment=HTTP_PROXY=http://192.168.6.88:10810 HTTPS_PROXY=http://192.168.6.88:10810 NO_PROXY=localhost,127.0.0.1,.example.com

2、配置 daemon.json
[root@localhost ~]# vi /etc/docker/daemon.json

{
  "proxies": {
    "default": {
      "httpProxy": "http://192.168.6.88:10810",
      "httpsProxy": "http://192.168.6.88:10810",
      "noProxy": "localhost,127.0.0.1,.example.com"
    }
  }
}

[root@localhost ~]# systemctl restart docker

3、配置环境变量
Docker 守护进程在启动时,会检查以下环境变量实现代理
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
NO_PROXY
no_proxy
在上面的实际测试时并没有效果,推测是因为systemd管理的docker服务因为不是在同一个shell环境启动,不会继承这些变量。
[root@localhost ~]# /usr/bin/dockerd -h | grep proxy
      --http-proxy string                     HTTP proxy URL to use for outgoing traffic
      --https-proxy string                    HTTPS proxy URL to use for outgoing traffic
      --no-proxy string                       Comma-separated list of hosts or IP addresses for which the proxy is skipped
通过帮助文档来看是可以通过传递参数实现。但需要手动启动服务,就不能用systemd管理了。

export http_proxy=http://192.168.6.88:10810
export HTTP_PROXY=http://192.168.6.88:10810
export HTTPS_PROXY=http://192.168.6.88:10810
export https_proxy=http://192.168.6.88:10810

/usr/bin/dockerd

这样手动启动的docker服务才会继承代理变量并生效。

# 带账号密码的代理写法
http://user:pass@192.168.6.88:10810

至此,可以通过镜像站、自建registry加速、配置代理 3种方式实现拉取官方镜像

2025-08-19
发表者 Venus
nginx add_header 指令在http{}段不生效的问题已关闭评论

nginx add_header 指令在http{}段不生效的问题

目的:实现一个全局配置,让所有网站都响应一个指定头。

官方文档:https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header
其中一句
There could be several directives. These directives are inherited from the previous configuration level if and only if there are no directives defined on the current level.

可能会有多个指令。如果在当前配置级别没有定义这些指令,那么它们才会从上一级配置继承。

例子:

http {
	# 在http{}段里定义
    add_header X-From-Http "hello_http";

    server {
        # server{}段没有定义 add_header
        location / {
            root /usr/share/nginx/html;
        }
    }
}

在这种情况下:
server{} 没有定义 add_header,所以它会继承 http{} 里的配置。

响应头会包含 X-From-Http: hello_http。


另一个情况:
http {
    add_header X-From-Http "hello_http";

    server {
        add_header X-From-Server "hello_server";

        location / {
            root /usr/share/nginx/html;
        }
    }
}

在这种情况下:
server{} 已经定义了自己的 add_header。
根据文档所说,只要当前级别定义了 add_header 指令(不管后面添加的什么响应头),就不会继承上一级的。

所以最终响应头里只有:
X-From-Server: hello_server响应,而不会有 X-From-Http。

# 补充
只有响应下面这些状态码时add_header才会生效:
200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13), or 308 (1.13.0). 

但是可以通过添加 always 参数实现无论什么状态码都添加。

最后通过 sed -i '/server_name/a # added by script' *.conf 这种批量方式实现在指定字符串的下一行添加。

2025-08-18
发表者 Venus
子网掩码计算已关闭评论

子网掩码计算

CIDR /30 指的是二进制子网掩码的前30位是网络位,后2位是主机位。
11111111.11111111.11111111.11111100

在ip地址二进制表示中,最后2位的组合就是 00、01、10、11,(转十进制为 0、1、2、3)也就是2的2次方个组合。

# 子网ip地址个数计算方式
/24 即2的8次方个ip地址(32-24=8)
/28 即2的4次方个ip地址(32-28=4)

在二进制表示中后面有几个0,子网ip数量(子网大小)就是2的几次方。

/30 转十进制为 255.255.255.252
ip子网划分始终是从"网络边界"开始,即,一个子网的起点必须是 "以子网大小为单位" 的倍数。
子网是 "连续的区间",不是从任意地址开始。
以cidr/30为例,它的子网大小就是2的2次方,即4:

所有的子网都是从 4 的倍数开始:

倍数  网络地址          ip范围                          可用ip
0倍: 192.168.0.0/30  → IP: 192.168.0.0 ~ 192.168.0.3   去掉网络地址0和广播地址3,可用ip就是 1、2
1倍: 192.168.0.4/30  → IP: 192.168.0.4 ~ 192.168.0.7   去掉网络地址4和广播地址7,可用ip就是 5、6
2倍: 192.168.0.8/30  → IP: 192.168.0.8 ~ 192.168.0.11  去掉网络地址8和广播地址11,可用ip就是 9、10
3倍: 192.168.0.12/30 → IP: 192.168.0.12 ~ 192.168.0.15 去掉网络地址12和广播地址15,可用ip就是 13、14
...

# 得到子网后再算网络、广播地址
网络地址:主机位全为 0 (子网第一个ip)
广播地址:主机位全为 1 (子网最后一个ip)

每个子网的起点必须是与其子网掩码对齐的地址,即主机位全为 0 的地址。

广播地址是某个子网中所有主机都能接收到的特殊地址。

网络、广播地址的计算方式如下:
确定网络地址: 将ip地址与子网掩码逐位相与(AND)运算,得到子网的起始地址。
确定子网大小: 根据子网掩码,计算主机位数。例如 /26 表示有 6 位主机位,子网大小为2^6=64。
广播地址 = 网络地址 + 子网大小 - 1 也就是该子网的最后一个地址。


# 判断一个子网掩码是不是合法
255.255.255.241 不是一个合法的子网掩码,原因在于它违反了子网掩码的二进制结构规则:
合法的子网掩码必须满足以下条件:
1、是一个32位二进制数。
2、前面是连续的 1,后面是连续的 0。
中间不能出现 01 的模式(即,不能有 1 后面跟着 0 再跟着 1)。

255.255.255.241 将其转换为二进制:
11111111.11111111.11111111.11110001
问题出在最后一组 11110001,它不是连续的1后跟连续的0,出现了01,违反规则。


# 延伸
系统如何判断一个目的ip是否和自己是同一个网段?
将目的ip和自己的子网掩码进行与运算,得出目标网络地址和自己的网络地址比较。
一样则为同一个网段,不一样则交由网关路由出去。

# 根据要求的主机数量,推算出子网掩码。
例如一个网络地址块:192.168.100.0/24 需要将其划分为多个子网,每个子网要求 可用IP数量不少于30个主机地址。完成以下任务:

要求:
1 推算出每个子网的子网掩码(CIDR 表示法)。
2 列出每个子网的:网络地址、广播地址、可用 IP 范围。
3 计算最多可以划分出多少个这样的子网。

1、 需要 2^x - 2 >= 30,2^4=16-2=14 不符合,2^5=32-2=30 符合,2^6=64-2=62 不符合(超过30个太多)。
2^5即主机位是5个0,二进制表示,即 11111111.11111111.11111111.11100000,CIDR表示为 /27,十进制为 255.255.255.224

根据每个子网的ip数量(32)倍数算出每个子网的开始ip、结束ip。

      网络地址                            广播地址
0倍	192.168.100.0/27    192.168.100.0 ~ 192.168.100.31
1倍	192.168.100.32/27   192.168.100.32 ~ 192.168.100.63
2倍	192.168.100.64/27   192.168.100.64 ~ 192.168.100.95
3倍	192.168.100.96/27   192.168.100.96 ~ 192.168.100.127
4倍	192.168.100.128/27  192.168.100.128 ~ 192.168.100.159
5倍	192.168.100.160/27  192.168.100.160 ~ 192.168.100.191
6倍	192.168.100.192/27  192.168.100.192 ~ 192.168.100.223
7倍	192.168.100.224/27  192.168.100.224 ~ 192.168.100.255

共8个网段,每个网段的网络地址+1,广播地址-1,之间的数就是每个网段的可用ip范围。

2025-08-15
发表者 Venus
自建docker镜像加速已关闭评论

自建docker镜像加速

registry是docker提供的搭建自己私库的程序,但是一般用harbor做私库比较方便。
这里将registry配置为代理缓存模式,解决国内无法拉取官网镜像的问题。
registry 运行在香港服务器中。

# 拉取镜像
docker pull dqzboy/mirror-hub:latest

# 打tag
docker tag dqzboy/mirror-hub:latest mirror:latest

# 指定挂载路径,可以将一块独立硬盘挂载到/mnt/docker提高可用空间。
docker run -dit --name hub --restart=always -v /mnt/docker:/var/lib/registry -p 5000:5000 mirror:latest

容器内会加载 /etc/distribution/config.yml 配置文件,里面定义了代理官方地址。

# auth_basic 认证,生成认证文件,root为账号。防止未授权访问。
htpasswd -c ./registry_auth root

# nginx反向代理
server
{
	listen 80;
	listen 443 ssl;
	http2 on;
	server_name hub.rootop.org;

	ssl_certificate     /etc/letsencrypt/live/hub.rootop.org/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/hub.rootop.org/privkey.pem;
	ssl_session_timeout 5m;
	ssl_protocols TLSv1.2 TLSv1.3;
	ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
	ssl_prefer_server_ciphers on;
	add_header Strict-Transport-Security "max-age=604800; includeSubdomains; preload";
	
	location /
	{
		auth_basic "Proxy Docker Hub";
		auth_basic_user_file /home/software/openresty/nginx/conf/vhost/registry_auth;
		proxy_pass http://127.0.0.1:5000;
		proxy_set_header   host $host;
		proxy_set_header   Cookie $http_cookie;
		proxy_set_header   scheme $scheme;
	}


	access_log  /var/log/nginx/hub.rootop.org.log;
	error_log   /var/log/nginx/hub.rootop.org_error.log;
}

# 登录,实际为nginx中认证,不会走到docker官方认证。
docker login hub.rootop.org

登录信息会保存在 /root/.docker/config.json 中,以base64编码保存账号密码。


# 指定域名拉取镜像
docker pull hub.rootop.org/library/nginx:latest

# 本地docker设置镜像地址,免去前面输入域名。
[root@docker-server ~]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://hub.rootop.org"]
}

[root@docker-server ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
b1badc6e5066: Pull complete 
a2da0c0f2353: Pull complete 
e5d9bb0b85cc: Pull complete 
14a859b5ba24: Pull complete 
716cdf61af59: Pull complete 
14e422fd20a0: Pull complete 
c3741b707ce6: Pull complete 
Digest: sha256:33e0bbc7ca9ecf108140af6288c7c9d1ecc77548cbfd3952fd8466a75edefe57
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest


# 补充
Docker Hub 把镜像组织成多个“命名空间”,例如:
nginx/nginx:由 nginx 官方维护
myuser/myapp:自己上传的镜像
library/ubuntu:Docker 官方维护的基础镜像

而 library 是 Docker Hub 的默认命名空间,专门用于存放官方镜像。
Docker 客户端在执行 docker pull ubuntu时,会自动补全为 docker pull docker.io/library/ubuntu
只有在拉取 Docker Hub 的官方维护的镜像时才会自动加上 library。

2025-08-11
发表者 Venus
Centos7下NetworkManager网络配置文件问题已关闭评论

Centos7下NetworkManager网络配置文件问题

系统:centos7
目的:使用networkmanager管理网络服务

# 关闭传统network服务
[root@localhost ~]# systemctl stop network
[root@localhost ~]# systemctl disable network

# 开启NetworkManager
[root@localhost ~]# systemctl start NetworkManager
[root@localhost ~]# systemctl enable NetworkManager

# 设置ip并重启生效
[root@localhost ~]# nmcli connection modify ens33 ipv4.addresses 192.168.6.202/24 ipv4.gateway 192.168.6.1 ipv4.dns 114.114.114.114
[root@localhost ~]# nmcli connection down ens33 
[root@localhost ~]# nmcli connection up ens33

# 查看NetworkManager配置文件加载的网络插件
[root@localhost ~]# cat /etc/NetworkManager/NetworkManager.conf |grep plugin
#plugins=ifcfg-rh,ibft

# 查看NetworkManager日志,打印加载的网络插件
[root@localhost ~]# journalctl -u NetworkManager | grep plugin
8月 11 10:46:17 localhost.localdomain NetworkManager[693]: <info> [1754880377.5586] settings: Loaded settings plugin: SettingsPluginIfcfg ("/usr/lib64/NetworkManager/1.18.8-1.el7/libnm-settings-plugin-ifcfg-rh.so")

# 插件类型区别
ifcfg-rh,配置文件位置 /etc/sysconfig/network-scripts/ifcfg-<interface>
keyfile, 配置文件位置 /etc/NetworkManager/system-connections/*.nmconnection

在almalinux9下,网络配置文件会放在 /etc/NetworkManager/system-connections/ 下。
[root@localhost system-connections]# cat /etc/NetworkManager/NetworkManager.conf | grep plugin
#plugins=keyfile,ifcfg-rh
这俩插件都会加载,默认会使用keyfile。

但是在centos7中,默认会用ifcfg-rh类型。
所以在centos7中虽然使用了NetworkManager服务管理网络,但是实际还会写入传统的 /etc/sysconfig/network-scripts/ifcfg-xxx; 中。
/etc/NetworkManager/system-connections下是空。