docker进阶---docker底层实践2025
本文详细介绍了Docker的安装配置与优化方案。内容分为两个主要部分: Docker安装: 提供了在线安装的完整步骤(系统工具安装、GPG密钥配置、阿里云镜像源设置) 包含离线安装方案(二进制包下载、systemd服务配置、安装脚本生成) 系统级优化: 设计了7个systemd配置文件(代理、资源限制、安全加固、日志、性能、可靠性、containerd优化) 每个配置文件都有详细注释说明其作用和安
·
一、安装 docker
1.在线安装
# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
# step 2: 信任 Docker 的 GPG 公钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Step 3: 写入软件源信息
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Step 4: 安装Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# apt-cache madison docker-ce
# docker-ce | 17.03.1~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# docker-ce | 17.03.0~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# Step 2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.1~ce-0~ubuntu-xenial)
# sudo apt-get -y install docker-ce=[VERSION]
systemd Docker 服务优化配置
完整配置目录结构
/etc/systemd/system/docker.service.d/
├── 10-proxy.conf # 网络代理配置
├── 20-limits.conf # 资源限制保护
├── 30-security.conf # 安全加固
├── 40-logging.conf # 日志优化
├── 50-performance.conf # 性能调优
├── 60-reliability.conf # 可靠性增强
└── 70-containerd.conf # containerd 专项优化
1. 10-proxy.conf (网络代理配置)
# /etc/systemd/system/docker.service.d/10-proxy.conf
# Purpose: 配置 Docker 守护进程的网络代理,用于受限网络环境
# SRE Note: 企业环境中必须配置,避免因网络问题导致服务中断
# Safety: 使用 NO_PROXY 保护内部网络,防止代理环路
[Service]
# 代理服务器配置 (替换为实际值)
Environment="HTTP_PROXY=http://proxy.corp.example.com:8080/"
Environment="HTTPS_PROXY=http://proxy.corp.example.com:8080/"
# 免代理列表 - 关键内部网络和域名
Environment="NO_PROXY=\
127.0.0.1,\
localhost,\
172.17.0.0/16,\ # Docker 默认网桥
10.0.0.0/8,\ # 企业内网
192.168.0.0/16,\ # 本地网络
.docker.internal,\ # Docker 内部通信
.zjx521,\ # 企业域名
cluster.local,\ # K8s 集群域名 (兼容性考虑)
metadata.google.internal # GCP 元数据服务
"
# 验证命令: systemctl show docker --property=Environment
2. 20-limits.conf (资源限制保护)
# /etc/systemd/system/docker.service.d/20-limits.conf
# Purpose: 保护 dockerd 进程本身不被资源耗尽
# SRE Note: 基于 64GB RAM 服务器计算,避免 infinity 导致系统级故障
# Formula:
# LimitNOFILE = 容器数 × 1024 × 1.5 (安全系数)
# LimitNPROC = 容器数 × 256 × 1.2 (安全系数)
[Service]
# 文件描述符限制 (支持 1000 容器 × 1024 连接)
LimitNOFILE=1572864 # 1.5M = 1000 × 1024 × 1.5
# 进程数限制 (支持 1000 容器 × 256 进程)
LimitNPROC=307200 # 300K = 1000 × 256 × 1.2
# 任务总数限制 (cgroup v2 任务数)
TasksMax=16384 # 16K 任务,足够支撑大规模部署
# 内存保护 (防止 OOM kill)
MemoryAccounting=yes
MemoryLimit=32G # 32GB 内存限制,保留宿主机资源
# CPU 保护 (避免 dockerd 占用过多 CPU)
CPUAccounting=yes
CPUQuota=800% # 8 核 CPU 配额,保留 20% 给系统
# 验证命令: cat /proc/$(pgrep dockerd)/limits
3. 30-security.conf (安全加固)
# /etc/systemd/system/docker.service.d/30-security.conf
# Purpose: 最小权限原则,减少攻击面
# SRE Note: 安全基线要求,防止容器逃逸
# Reference: CIS Docker Benchmark v1.6.0
[Service]
# 丢弃不必要的 capabilities
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SYS_CHROOT CAP_SETFCAP
# 禁止权限提升
NoNewPrivileges=yes
# 文件系统保护
ProtectSystem=strict # /usr, /boot, /etc 只读
ProtectHome=yes # /home, /root, /run/user 不可见
PrivateTmp=yes # 私有 /tmp 目录
ProtectControlGroups=yes # cgroup 文件系统只读
ProtectKernelTunables=yes # /proc/sys, /sys 只读
ProtectKernelModules=yes # 内核模块操作禁止
# 网络隔离
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictRealtime=yes # 禁止实时调度
# IPC 隔离
PrivateIPC=yes
# 验证命令: systemctl show docker --property=CapabilityBoundingSet --property=NoNewPrivileges
4. 40-logging.conf (日志优化)
# /etc/systemd/system/docker.service.d/40-logging.conf
# Purpose: 防止日志爆炸,确保系统稳定性
# SRE Note: 生产环境常见故障点,日志文件过大导致磁盘耗尽
# Strategy: 限制日志大小 + 轮转 + 优先级控制
[Service]
# 日志级别控制 (生产环境推荐 info)
Environment="DOCKER_LOG_LEVEL=info"
# systemd 日志限制
LogsDirectoryMaxFiles=10
LogsDirectoryMode=0755
# journald 集成优化
LogRateLimitIntervalSec=30s
LogRateLimitBurst=1000
# 防止日志洪水攻击
StandardOutput=journal
StandardError=journal
SyslogLevel=info
# 验证命令: journalctl -u docker --since "1 hour ago" --no-pager | wc -l
5. 50-performance.conf (性能调优)
# /etc/systemd/system/docker.service.d/50-performance.conf
# Purpose: 优化 dockerd 启动和服务性能
# SRE Note: 基于大规模集群经验,减少服务中断时间
# Metrics: 目标启动时间 < 5s,恢复时间 < 30s
[Service]
# 启动超时优化 (避免卡在启动阶段)
TimeoutStartSec=300 # 5 分钟启动超时
TimeoutStopSec=120 # 2 分钟停止超时
# 优雅关闭配置
KillMode=mixed # 先 SIGTERM,再 SIGKILL
KillSignal=SIGTERM
SendSIGKILL=yes
SendSIGHUP=yes # 通知子进程重载
# 重启策略 (自动恢复)
Restart=on-failure
RestartSec=5s # 5 秒后重启
StartLimitInterval=60s # 60 秒内
StartLimitBurst=5 # 最多重启 5 次
# 调度优化
Nice=-5 # 提高进程优先级
IOSchedulingClass=realtime
IOSchedulingPriority=2 # IO 优先级
# 验证命令: systemctl show docker --property=TimeoutStartSec --property=Restart
6. 60-reliability.conf (可靠性增强)
# /etc/systemd/system/docker.service.d/60-reliability.conf
# Purpose: 确保 dockerd 高可用,减少服务中断
# SRE Note: 要求 99.99% 可用性,必须配置
# Principle: 预防性配置 + 快速恢复
[Service]
# 心跳检测 (systemd 层面)
WatchdogSec=30s # 30 秒心跳超时
# 环境变量控制 (便于调试)
Environment="DOCKER_OPTS=--live-restore --iptables=false"
# 依赖关系优化
Requires=containerd.service
After=containerd.service network-online.target
# 资源分配保障
CPUShares=1024 # 保证 CPU 份额
BlockIOWeight=1000 # IO 权重
# 故障隔离
Slice=system.slice # 放入系统 slice
Delegate=yes # 委托 cgroup 管理给 dockerd
# 验证命令: systemctl show docker --property=WatchdogSec --property=Requires
7. 70-containerd.conf (containerd 专项优化)
# /etc/systemd/system/docker.service.d/70-containerd.conf
# Purpose: 优化 containerd 作为 Docker 默认运行时
# SRE Note: Docker 23.0+ 默认使用 containerd,必须专门优化
# Compatibility: 确保与 containerd 1.7+ 兼容
[Service]
# containerd 通信优化
Environment="CONTAINERD_NAMESPACE=moby"
Environment="CONTAINERD_SNAPSHOTTER=overlayfs"
# gRPC 超时配置
Environment="CONTAINERD_GRPC_MAX_RECV_MSG_SIZE=16777216" # 16MB
Environment="CONTAINERD_GRPC_MAX_SEND_MSG_SIZE=16777216" # 16MB
# 连接池优化
Environment="CONTAINERD_GRPC_CONNECTION_TIMEOUT=30s"
Environment="CONTAINERD_GRPC_KEEPALIVE_TIME=60s"
# 存储优化 (与 dockerd 协同)
Environment="DOCKER_STORAGE_OPTS=--storage-opt dm.basesize=50G"
# 验证命令: ctr -n moby version && ctr -n moby containers list
部署脚本 (一键应用所有优化)
#!/bin/bash
# deploy-docker-systemd-optimizations.sh
# 2025 标准 Docker systemd 优化部署脚本
set -euo pipefail
IFS=$'\n\t'
echo " 开始部署 Docker systemd 优化配置..."
# 1. 创建配置目录
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo chown root:root /etc/systemd/system/docker.service.d
sudo chmod 755 /etc/systemd/system/docker.service.d
# 2. 部署所有配置文件
cat <<'EOF' | sudo tee /etc/systemd/system/docker.service.d/10-proxy.conf
# ... (上面的 10-proxy.conf 内容) ...
EOF
cat <<'EOF' | sudo tee /etc/systemd/system/docker.service.d/20-limits.conf
# ... (上面的 20-limits.conf 内容) ...
EOF
cat <<'EOF' | sudo tee /etc/systemd/system/docker.service.d/30-security.conf
# ... (上面的 30-security.conf 内容) ...
EOF
cat <<'EOF' | sudo tee /etc/systemd/system/docker.service.d/40-logging.conf
# ... (上面的 40-logging.conf 内容) ...
EOF
cat <<'EOF' | sudo tee /etc/systemd/system/docker.service.d/50-performance.conf
# ... (上面的 50-performance.conf 内容) ...
EOF
cat <<'EOF' | sudo tee /etc/systemd/system/docker.service.d/60-reliability.conf
# ... (上面的 60-reliability.conf 内容) ...
EOF
cat <<'EOF' | sudo tee /etc/systemd/system/docker.service.d/70-containerd.conf
# ... (上面的 70-containerd.conf 内容) ...
EOF
# 3. 设置正确权限
sudo chmod 644 /etc/systemd/system/docker.service.d/*.conf
sudo chown root:root /etc/systemd/system/docker.service.d/*.conf
# 4. 重载 systemd 配置
echo " 重载 systemd 配置..."
sudo systemctl daemon-reload
# 5. 重启 Docker 服务
echo " 重启 Docker 服务..."
sudo systemctl restart docker
# 6. 验证配置
echo " 验证配置是否生效..."
sleep 5
# 7. 健康检查
echo " 执行健康检查..."
if sudo docker info >/dev/null 2>&1; then
echo " Docker 服务健康"
else
echo " Docker 服务异常,请检查日志"
sudo journalctl -u docker --since "5 minutes ago" --no-pager
exit 1
fi
# 8. 验证关键限制
echo " 验证关键限制设置..."
docker_pid=$(pgrep dockerd || echo "0")
if [ "$docker_pid" -ne 0 ]; then
echo "PID: $docker_pid"
echo "文件描述符限制: $(cat /proc/$docker_pid/limits | grep 'Max open files' | awk '{print $3}')"
echo "进程数限制: $(cat /proc/$docker_pid/limits | grep 'Max processes' | awk '{print $3}')"
echo "Capabilities: $(sudo systemctl show docker --property=CapabilityBoundingSet --value)"
fi
echo " Docker systemd 优化配置部署完成!"
echo " 配置文件位置: /etc/systemd/system/docker.service.d/"
echo " 验证命令: systemctl cat docker | grep -A 10 '\[Service\]'"
验证清单 (检查表)
# 1. 配置文件权限检查
ls -la /etc/systemd/system/docker.service.d/
# 应该显示: -rw-r--r-- 1 root root
# 2. systemd 配置合并验证
systemctl cat docker | grep -A 20 '\[Service\]'
# 3. 进程限制验证
docker_pid=$(pgrep dockerd)
cat /proc/$docker_pid/limits | grep -E "(open files|processes|tasks)"
# 4. 安全特性验证
systemctl show docker --property=CapabilityBoundingSet --property=NoNewPrivileges --property=ProtectSystem
# 5. 服务状态验证
systemctl status docker --no-pager
# 6. 容器创建测试
docker run --rm alpine echo " 配置生效,容器可正常创建"
# 7. 日志验证
journalctl -u docker -f --since "1 minute ago" # 观察实时日志
关键注意事项:
1.变量替换:
# 10-proxy.conf 中必须替换实际代理地址
Environment="HTTP_PROXY=http://YOUR_PROXY_IP:PORT/"
2.硬件适配:
# 20-limits.conf 需要根据服务器规格调整
# 公式: LimitNOFILE = (预期容器数 × 1024 × 1.5)
# 例如: 200 容器 → 200 × 1024 × 1.5 = 307,200
3.安全审计:
# 部署后运行安全审计
docker bench security --version 1.6.0
4.监控集成:
# 添加到 Prometheus node exporter
echo "docker_fd_usage $(ls -l /proc/$(pgrep dockerd)/fd | wc -l)" > /var/lib/prometheus/node_exporter/docker.prom
5.变更管理:
# 所有配置变更必须通过 GitOps
git commit -m "feat(docker): apply SRE 2025 systemd optimizations"
git push origin main
daemon.json 优化
cat /etc/docker/daemon.json
{
"live-restore": true,
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.xuanyuan.me",
"https://docker.1ms.run",
"https://docker-0.unsee.tech",
"https://docker.hlmirror.com"
],
"insecure-registries": [],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Soft": 65536,
"Hard": 65536
}
},
"features": {
"buildkit": true
},
"proxies": {
"http-proxy": "http://YOUR_PROXY_IP:YOUR_PROXY_PORT",
"https-proxy": "http://YOUR_PROXY_IP:YOUR_PROXY_PORT",
"no-proxy": "localhost,127.0.0.0/8,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8"
}
}
这套配置是 2025 标准的实现,它:
- 分层清晰:每个文件专注单一职责
- 防御性设计:避免 infinity,设置合理限制
- 可观测性:内置验证和监控点
- 自动化友好:一键部署脚本
- 安全优先:遵循最小权限原则
- containerd 优化:适配 Docker 新架构
2.离线安装(二进制安装)
cat > package_docker_offline.sh <<'EOF1'
#!/bin/bash
# package_docker_offline.sh - 用于为离线环境打包 Docker 安装文件
set -euo pipefail # 启用错误处理
# --- 配置区 ---
DOCKER_VERSION="28.5.2"
# URL="https://download.docker.com/linux/static/stable/" # 官方源通常更稳定用于打包
URL="https://mirrors.aliyun.com/docker-ce/linux/static/stable/" # 国内源,打包时使用
# 输出目录和包名
OUTPUT_DIR="docker-offline-package"
ARCH=$(uname -m)
case $ARCH in
x86_64) DOCKER_ARCH="x86_64" ;;
aarch64) DOCKER_ARCH="aarch64" ;;
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
esac
PACKAGE_NAME="docker-offline-${DOCKER_VERSION}-${ARCH}"
# --- 函数区 ---
# 简单的彩色输出函数 (打包阶段用)
color() {
local RES_COL=60
local MOVE_TO_COL="\\033[${RES_COL}G"
local SETCOLOR_SUCCESS="\\033[1;32m"
local SETCOLOR_FAILURE="\\033[1;31m"
local SETCOLOR_WARNING="\\033[1;33m"
local SETCOLOR_NORMAL="\\E[0m"
echo -ne "$1"
printf "%s" "$MOVE_TO_COL"
echo -n "["
if [[ "$2" == "success" || "$2" == "0" ]]; then
echo -ne "$SETCOLOR_SUCCESS"
echo -n " OK "
elif [[ "$2" == "failure" || "$2" == "1" ]]; then
echo -ne "$SETCOLOR_FAILURE"
echo -n "FAILED"
else
echo -ne "$SETCOLOR_WARNING"
echo -n "WARNING"
fi
echo -e "$SETCOLOR_NORMAL]"
}
echo "[*] Preparing packaging environment..."
mkdir -p "${OUTPUT_DIR}/${PACKAGE_NAME}"
cd "${OUTPUT_DIR}"
# 1. 下载 Docker 二进制
echo "[*] Downloading Docker ${DOCKER_VERSION} (${DOCKER_ARCH})..."
if wget --progress=bar:force:noscroll "${URL}${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz" -O "${PACKAGE_NAME}/docker-${DOCKER_VERSION}.tgz"; then
color "Docker binary downloaded" "success"
else
color "Failed to download Docker binary" "failure"
exit 1
fi
# 2. 下载补全脚本
echo "[*] Downloading Docker bash completion..."
if wget -q -O "${PACKAGE_NAME}/docker_completion" "https://raw.githubusercontent.com/docker/cli/master/contrib/completion/bash/docker"; then
color "Docker completion downloaded" "success"
else
color "Failed to download Docker completion" "warning" # 不致命
fi
# 3. 创建 systemd 服务文件 (优化版)
echo "[*] Creating systemd service file..."
cat > "${PACKAGE_NAME}/docker.service" <<'EOF2'
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/local/bin/dockerd -H unix:///var/run/docker.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 230.
StartLimitBurst=3
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
[Install]
WantedBy=multi-user.target
EOF2
color "Systemd service file created" "success"
# 4. 创建 daemon.json 配置模板 (包含优化项)
echo "[*] Creating daemon.json template with optimizations..."
# 注意:在模板中使用占位符,安装时替换
cat > "${PACKAGE_NAME}/daemon.json" <<'EOF3'
{
"live-restore": true,
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.xuanyuan.me",
"https://docker.1ms.run",
"https://docker-0.unsee.tech",
"https://docker.hlmirror.com"
],
"insecure-registries": [],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Soft": 65536,
"Hard": 65536
}
},
"features": {
"buildkit": true
},
"proxies": {
"http-proxy": "http://YOUR_PROXY_IP:YOUR_PROXY_PORT",
"https-proxy": "http://YOUR_PROXY_IP:YOUR_PROXY_PORT",
"no-proxy": "localhost,127.0.0.0/8,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8"
}
}
EOF3
color "daemon.json template created" "success"
# 5. 创建安装脚本 (离线安装时运行)
echo "[*] Creating offline installation script..."
cat > "${PACKAGE_NAME}/install_docker_offline.sh" <<'INSTALL_SCRIPT_EOF'
#!/bin/bash
# install_docker_offline.sh - 离线安装 Docker 的脚本
set -euo pipefail
if [[ $EUID -ne 0 ]]; then
echo "Error: This script must be run as root." >&2
exit 1
fi
# --- 检测操作系统 ---
OS_ID=""
if [ -f /etc/os-release ]; then
. /etc/os-release
OS_ID=$ID
elif command -v lsb_release >/dev/null 2>&1; then
OS_ID=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
elif [ -f /etc/redhat-release ]; then
OS_ID="rhel"
elif [ -f /etc/debian_version ]; then
OS_ID="debian"
fi
# --- 安装依赖 ---
install_dependencies() {
echo "[*] Installing dependencies (wget, curl, bash-completion)..."
case "$OS_ID" in
ubuntu|debian)
apt-get update
apt-get install -y wget curl bash-completion
;;
centos|rhel|rocky|almalinux|anolis|fedora)
if command -v dnf &> /dev/null; then
dnf install -y wget curl bash-completion
else
yum install -y wget curl bash-completion
fi
;;
*)
echo "Warning: Unsupported OS '$OS_ID'. Please install wget, curl, and bash-completion manually."
;;
esac
}
# --- 安装 Docker ---
install_docker() {
echo "[*] Installing Docker..."
tar xf "docker-${DOCKER_VERSION}.tgz"
cp docker/* /usr/local/bin/
# Install systemd service
cp docker.service /lib/systemd/system/docker.service
systemctl daemon-reload
# Install completion
mkdir -p /etc/bash_completion.d
cp docker_completion /etc/bash_completion.d/docker
echo "[+] Docker binary and service installed."
}
# --- 配置 Docker ---
config_docker() {
echo "[*] Configuring Docker..."
mkdir -p /etc/docker
# 直接使用打包好的 daemon.json 模板
cp daemon.json /etc/docker/daemon.json
# --- 可选:尝试探测并替换为最优镜像源 ---
# (在离线环境中可能不适用,但保留逻辑供参考)
# BEST_MIRROR=""
# for mirror in "https://docker.m.daocloud.io" "https://docker.hlmirror.com"; do
# if curl -s -m 3 -f "$mirror" > /dev/null 2>&1; then
# BEST_MIRROR="$mirror"
# break
# fi
# done
# if [ -n "$BEST_MIRROR" ]; then
# sed -i "s|https://docker.m.daocloud.io|${BEST_MIRROR}|g" /etc/docker/daemon.json
# echo "[+] Docker configured with mirror: $BEST_MIRROR"
# else
# echo "[-] Could not probe a better mirror, using default list."
# fi
echo "[+] Docker configured with default settings (including mirrors and proxy placeholder)."
echo " Please edit /etc/docker/daemon.json to adjust mirrors or configure proxy."
}
# --- 启动 Docker ---
start_docker() {
echo "[*] Starting Docker service..."
systemctl enable --now docker > /dev/null 2>&1
if docker version > /dev/null 2>&1; then
echo "[+] Docker service started successfully."
else
echo "[-] Failed to start Docker service."
exit 1
fi
}
# --- Main Execution ---
# Get Docker version from the package filename or the tgz file
DOCKER_VERSION=$(basename docker-*.tgz | sed 's/docker-\(.*\)\.tgz/\1/')
install_dependencies
install_docker
config_docker
start_docker
echo "[*] Docker ${DOCKER_VERSION} installation complete!"
echo " Configuration file: /etc/docker/daemon.json"
echo " Please review and adjust the configuration as needed."
INSTALL_SCRIPT_EOF
chmod +x "${PACKAGE_NAME}/install_docker_offline.sh"
color "Installation script created" "success"
# 6. 打包
echo "[*] Creating offline package ${PACKAGE_NAME}.tar.gz..."
tar -czf "${PACKAGE_NAME}.tar.gz" "${PACKAGE_NAME}"
echo "[+] Offline package created: ${OUTPUT_DIR}/${PACKAGE_NAME}.tar.gz"
echo " To install offline, transfer this file to the target machine and run:"
echo " tar -xzf ${PACKAGE_NAME}.tar.gz && cd ${PACKAGE_NAME} && sudo ./install_docker_offline.sh"
cd ..
EOF1
说明
daemon.json模板:现在包含了你要求的多个镜像源 (registry-mirrors) 和一个占位符形式的代理配置 (proxies)。用户解压后安装,会得到这个默认配置,然后可以根据自己的网络环境进行修改。install_docker_offline.sh(离线安装脚本):这个脚本被打包进离线包中。它在目标机器上运行时,会:- 安装依赖 (
wget,curl,bash-completion)。 - 解压并安装 Docker 二进制和服务。
- 直接复制打包好的
daemon.json到/etc/docker/。 - 启动 Docker 服务。
- 安装依赖 (
使用流程
- 在有网络的机器上:运行
bash package_docker_offline.sh。它会生成docker-offline-package/docker-offline-${VERSION}-${ARCH}.tar.gz。 - 在离线机器上:
tar -xzf docker-offline-${VERSION}-${ARCH}.tar.gz cd docker-offline-${VERSION}-${ARCH} sudo ./install_docker_offline.sh - (可选) 安装后:用户编辑
/etc/docker/daemon.json来启用代理或调整镜像源。
二、容器化思维(Docker 原生视角)
1.容器的本质:隔离的进程,不是轻量 VM
技术深度解析:
- 进程视角 vs VM 视角:容器本质是带隔离属性的 Linux 进程,共享宿主机内核,而非完整的操作系统虚拟化
Linux Namespace 机制深度剖析
| 隔离类型 | 功能描述 | 系统调用参数 | 内核版本 | 典型用途 | 安全性考量 | SRE 关注点 |
|---|---|---|---|---|---|---|
| MNT Namespace (Mount) | 提供文件系统挂载点的隔离能力,每个命名空间拥有独立的挂载视图 | CLONE_NEWNS |
2.4.19 | 容器中独立的文件系统视图(如 /proc, /sys),避免影响宿主机 |
需注意 bind mount 可能穿透边界,需限制 |
控制容器访问敏感路径,防止误操作破坏宿主机文件系统 |
| PID Namespace (Process ID) | 实现进程 ID 的隔离,使容器内的进程 PID 从 1 开始,不与宿主机冲突 | CLONE_NEWPID |
2.6.24 | 避免进程号冲突,简化调试与监控 | 子命名空间中的进程无法直接被宿主机 kill 或 ps 查看,需通过 nsenter |
进程生命周期管理需明确,避免僵尸进程堆积 |
| IPC Namespace (Inter-Process Communication) | 隔离进程间通信资源,如信号量、消息队列、共享内存等 | CLONE_NEWIPC |
2.6.19 | 多个容器间通信互不干扰,提升安全性和稳定性 | 共享内存若未清理可能造成内存泄漏 | 监控 IPC 资源使用情况,确保无资源泄露 |
| Net Namespace (Network) | 提供网络栈隔离,包括网络设备、IP 地址、端口、路由表等 | CLONE_NEWNET |
2.6.29 | 每个容器拥有独立网络栈,支持多网卡、防火墙规则 | 网络策略需严格控制,防止横向渗透 | 网络策略(如 CNI、iptables)必须自动化且可审计;关注网络性能与延迟 |
| UTS Namespace (UNIX Timesharing System) | 隔离主机名(hostname)和域名(domain name) | CLONE_NEWUTS |
2.6.19 | 容器可自定义主机名,便于服务发现与日志识别 | 主机名变更不影响系统稳定性,但需统一规范 | 日志系统应支持基于 hostname 的过滤,便于排查 |
| User Namespace (User) | 实现用户和组 ID 的映射隔离,提升权限控制粒度 | CLONE_NEWUSER |
3.8 | 容器内 root 用户映射为宿主机非特权用户,增强安全性 | 需配置正确的 UID/GID 映射,否则可能引发权限问题 | 推荐启用 user namespace 以降低攻击面;配合 seccomp 和 AppArmor 使用 |
Linux Control Groups (cgroups)
1. 本质定位:分布式系统的"资源熔断器"
核心观点:
"Cgroups 不是资源限制工具,而是系统韧性的基础设施。它通过硬性隔离防止单点故障扩散至全局,是保障 SLO/SLI 的最后一道防线。"
- 历史意义:
Google 2006 年发起(原名 process containers),2007 年因命名冲突重命名为 cgroups 并合入 Linux 2.6.24 内核。
→洞察:这是 Google 将 Borg 经验反哺开源的关键一步——用内核级隔离解决多租户资源共享的熵增问题。
2. 为什么 必须掌控 cgroups?
关键:
"永不信任进程—— 所有工作负载必须运行在资源约束的沙箱中。这是 '零信任架构'起点。"
| 风险场景 | 无 cgroups 后果 | cgroups v2 应对方案 |
|---|---|---|
| 内存泄漏 | 单容器耗尽宿主机内存 → 全节点 OOM Kill | --memory="512m"• 底层映射到 cgroups v2 的 memory.max• 必须配合 --oom-score-adj=-500 (Docker 默认开启 OOM 保护) |
| CPU 饥饿 | 低优先级任务阻塞关键服务线程 | --cpus=1.5• 底层映射到 cpu.max = "150000 100000" (150% CPU)• 禁用 cpu.weight (Docker 未暴露此参数) |
| I/O 风暴 | 磁盘写满导致 etcd 延迟 → 集群脑裂 | Docker 原生不支持! • 必须通过 --device-write-bps (cgroups v1)• cgroups v2 需用 systemd 或 crun:systemd-run --scope -p IOAccounting=yes -p IOWeight=100 docker run... |
| 网络拥塞 | 恶意容器占满带宽 → API 服务超时 | Docker 原生不支持 cgroups 限速! • 通过 --network 驱动参数:docker network create --driver bridge --opt com.docker.network.driver.mtu=1400 limited-net• 生产环境必须用 CNI 插件 (如 bandwidth) |
- 与命名空间协同:


核心概念:Linux 的"孤儿院"机制
普通 Linux 系统:
systemd (PID 1) → 负责收养所有孤儿进程
→ 自动清理僵尸进程
Docker 容器(无 --init):
your-app (PID 1) → 不会收养孤儿进程
→ 僵尸进程堆积 → PID 耗尽
tini 的三个关键作用
-
当好 PID 1
- 接收系统信号(SIGTERM, SIGKILL)
- 代替你的应用处理信号
-
清理僵尸进程
- 当子进程退出时,自动调用
wait()清理 - 防止僵尸进程堆积
- 当子进程退出时,自动调用
-
优雅关闭
- 收到 SIGTERM 时,转发给你的应用
- 等待应用完成清理工作
- 最后才退出容器
"Linux 要求 PID 1 进程负责回收僵尸进程。容器默认将应用作为 PID 1,但大部分应用(如 Java/Node.js)不会实现这个功能。当子进程退出时,会变成僵尸进程,长期累积后耗尽系统 PID 资源,导致整个宿主机无法创建新进程。
--init启用 tini 作为真正的 init 系统:
- 作为 PID 1 接收所有信号
- 自动回收僵尸进程
- 将 SIGTERM 转发给应用,实现优雅关闭
这是防止系统级故障的基础防护,Google SRE 要求所有生产容器必须启用。"
预防僵尸进程 --init
-
先说结论
"这是防止僵尸进程导致系统级故障的基础防护。" -
解释机制
"Linux 要求 PID 1 进程回收僵尸进程。容器默认将应用作为 PID 1,但应用通常不处理这个责任。僵尸进程累积会耗尽 PID 资源,导致宿主机无法创建新进程。"
更多推荐

所有评论(0)