强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Alpine Linux 完全指南 / 第 15 章:生产最佳实践

第 15 章:生产最佳实践

Alpine Linux 在生产环境中的部署规范、Docker 最佳实践和安全基线。

15.1 服务器部署规范

系统初始化清单

步骤操作优先级
1系统更新 apk update && apk upgrade必须
2设置时区 setup-timezone Asia/Shanghai必须
3创建管理员用户必须
4配置 SSH 密钥认证必须
5禁用 root 密码登录必须
6配置防火墙必须
7安装 Fail2Ban推荐
8配置 NTP 时间同步推荐
9设置日志轮转推荐
10配置监控告警推荐

自动化部署脚本

cat > /usr/local/bin/prod-init << 'SCRIPT'
#!/bin/sh
set -e

echo "=== Alpine Production Init ==="

# 1. 系统更新
echo "[1/10] Updating system..."
apk update && apk upgrade

# 2. 安装基础工具
echo "[2/10] Installing base packages..."
apk add --no-cache \
    bash bash-completion \
    vim htop tmux \
    curl wget \
    openssh \
    sudo \
    chrony \
    logrotate \
    fail2ban

# 3. 时区配置
echo "[3/10] Setting timezone..."
setup-timezone Asia/Shanghai

# 4. 创建管理员用户
echo "[4/10] Creating admin user..."
ADMIN_USER="admin"
adduser -D -s /bin/bash "$ADMIN_USER"
addgroup "$ADMIN_USER" wheel
echo '%wheel ALL=(ALL) ALL' > /etc/sudoers.d/wheel
chmod 440 /etc/sudoers.d/wheel

# 5. SSH 配置
echo "[5/10] Configuring SSH..."
cat > /etc/ssh/sshd_config << 'SSHEOF'
Port 22
PermitRootLogin prohibit-password
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
X11Forwarding no
AllowAgentForwarding no
SSHEOF

# 6. 防火墙
echo "[6/10] Configuring firewall..."
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
/etc/init.d/iptables save

# 7. NTP
echo "[7/10] Configuring NTP..."
rc-update add chronyd
rc-service chronyd start

# 8. 内核参数
echo "[8/10] Tuning kernel parameters..."
cat >> /etc/sysctl.conf << 'SYSEOF'
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.ip_local_port_range = 1024 65535
vm.swappiness = 10
fs.file-max = 2097152
SYSEOF
sysctl -p

# 9. 日志轮转
echo "[9/10] Configuring logrotate..."
cat > /etc/logrotate.d/messages << 'LOGEOF'
/var/log/messages {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
}
LOGEOF

# 10. 启动服务
echo "[10/10] Starting services..."
rc-update add sshd default
rc-service sshd start

echo "=== Production init complete! ==="
echo "Please add your SSH public key to /home/$ADMIN_USER/.ssh/authorized_keys"
SCRIPT
chmod +x /usr/local/bin/prod-init

15.2 Docker 最佳实践

Dockerfile 规范

# 1. 使用明确的版本标签
FROM alpine:3.20

# 2. 元数据标签
LABEL maintainer="team@example.com"
LABEL version="1.2.3"
LABEL description="Production API Server"

# 3. 安全:创建非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# 4. 安装依赖:单层 + --no-cache
RUN apk add --no-cache \
    ca-certificates \
    tini \
    && update-ca-certificates

# 5. 设置工作目录
WORKDIR /app

# 6. 先复制依赖文件(利用缓存)
COPY go.mod go.sum ./
RUN go mod download

# 7. 复制源码并构建
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app/server .

# 8. 多阶段构建:生产镜像
FROM alpine:3.20
RUN apk add --no-cache ca-certificates tini
COPY --from=builder /app/server /usr/local/bin/server

# 9. 非 root 用户运行
USER appuser

# 10. 暴露端口
EXPOSE 8080

# 11. 健康检查
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
    CMD wget -qO- http://localhost:8080/health || exit 1

# 12. 使用 tini 作为 PID 1
ENTRYPOINT ["tini", "--"]
CMD ["server"]

Docker Compose 生产配置

version: "3.8"

services:
  app:
    image: myapp:1.2.3
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '0.5'
          memory: 256M
        reservations:
          cpus: '0.25'
          memory: 128M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password
    networks:
      - frontend
      - backend
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 40s
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    read_only: true
    tmpfs:
      - /tmp
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE

  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
    networks:
      - backend
    deploy:
      resources:
        limits:
          memory: 512M

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./certs:/etc/nginx/certs:ro
    networks:
      - frontend
    depends_on:
      - app

networks:
  frontend:
  backend:

volumes:
  pgdata:

secrets:
  db_password:
    file: ./secrets/db_password.txt

15.3 安全基线

CIS Benchmark 配置

# 1. 文件系统加固
chmod 600 /etc/shadow
chmod 600 /etc/gshadow
chmod 644 /etc/passwd
chmod 644 /etc/group
chmod 700 /root
chmod 600 /etc/ssh/sshd_config

# 2. 禁用不需要的文件系统
cat >> /etc/modprobe.d/disable-fs.conf << 'EOF'
install cramfs /bin/true
install freevxfs /bin/true
install hfs /bin/true
install hfsplus /bin/true
install jffs2 /bin/true
install udf /bin/true
EOF

# 3. 禁用不需要的网络协议
cat >> /etc/modprobe.d/disable-net.conf << 'EOF'
install dccp /bin/true
install sctp /bin/true
install rds /bin/true
install tipc /bin/true
EOF

# 4. 设置密码策略
apk add libpwquality
cat > /etc/security/pwquality.conf << 'EOF'
minlen = 12
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
EOF

# 5. 配置审计
apk add audit
cat > /etc/audit/audit.rules << 'EOF'
-D
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k sudoers
-w /etc/ssh/sshd_config -p wa -k sshd
-a always,exit -F arch=b64 -S execve -k exec
EOF
rc-update add auditd

安全扫描脚本

cat > /usr/local/bin/security-audit << 'SCRIPT'
#!/bin/sh
echo "=== Alpine Security Audit Report ==="
echo "Date: $(date)"
echo "Hostname: $(hostname)"
echo ""

echo "--- 系统信息 ---"
echo "Alpine: $(cat /etc/alpine-release)"
echo "Kernel: $(uname -r)"
echo "Uptime: $(uptime)"
echo ""

echo "--- 用户检查 ---"
echo "Root login: $(grep '^PermitRootLogin' /etc/ssh/sshd_config 2>/dev/null || echo 'Not configured')"
echo "Password auth: $(grep '^PasswordAuthentication' /etc/ssh/sshd_config 2>/dev/null || echo 'Not configured')"
echo "Empty passwords: $(awk -F: '($2 == "") {print $1}' /etc/shadow)"
echo ""

echo "--- 文件权限 ---"
echo "World-writable files: $(find / -xdev -type f -perm -0002 2>/dev/null | wc -l)"
echo "SUID files: $(find / -xdev -type f -perm -4000 2>/dev/null | wc -l)"
echo "SGID files: $(find / -xdev -type f -perm -2000 2>/dev/null | wc -l)"
echo ""

echo "--- 网络 ---"
echo "Listening ports:"
ss -tlnp | grep LISTEN
echo ""

echo "--- 防火墙 ---"
iptables -L -n --line-numbers 2>/dev/null | head -20
echo ""

echo "--- 磁盘 ---"
df -h | grep -E '^/dev'
echo ""

echo "--- 可更新包 ---"
apk update > /dev/null 2>&1
UPDATES=$(apk version -l '<' 2>/dev/null | wc -l)
echo "Available updates: $UPDATES"
echo ""
SCRIPT
chmod +x /usr/local/bin/security-audit

15.4 监控与告警

基础监控脚本

cat > /usr/local/bin/health-check << 'SCRIPT'
#!/bin/sh
# 阈值
CPU_THRESHOLD=90
MEM_THRESHOLD=85
DISK_THRESHOLD=90

# CPU 使用率
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print int($2 + $4)}')
if [ "$CPU_USAGE" -gt "$CPU_THRESHOLD" ]; then
    logger -t health-check "ALERT: CPU usage ${CPU_USAGE}%"
fi

# 内存使用率
MEM_USAGE=$(free | awk '/Mem:/ {printf("%.0f", $3/$2 * 100)}')
if [ "$MEM_USAGE" -gt "$MEM_THRESHOLD" ]; then
    logger -t health-check "ALERT: Memory usage ${MEM_USAGE}%"
fi

# 磁盘使用率
for line in $(df -h | grep -E '^/dev' | awk '{print $5 "|" $6}'); do
    USAGE=$(echo "$line" | cut -d'|' -f1 | tr -d '%')
    MOUNT=$(echo "$line" | cut -d'|' -f2)
    if [ "$USAGE" -gt "$DISK_THRESHOLD" ]; then
        logger -t health-check "ALERT: Disk ${MOUNT} usage ${USAGE}%"
    fi
done

# 服务检查
for svc in nginx sshd; do
    if ! rc-service "$svc" status > /dev/null 2>&1; then
        logger -t health-check "ALERT: Service $svc is down"
    fi
done
SCRIPT
chmod +x /usr/local/bin/health-check

# 定期执行
echo "*/5 * * * * /usr/local/bin/health-check" >> /etc/crontabs/root

15.5 备份策略

自动备份脚本

cat > /usr/local/bin/backup << 'SCRIPT'
#!/bin/sh
set -e

BACKUP_DIR="/backup"
RETENTION_DAYS=30
DATE=$(date +%Y%m%d_%H%M%S)
LOGFILE="/var/log/backup.log"

log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOGFILE"
}

log "Starting backup..."

# 创建备份目录
mkdir -p "$BACKUP_DIR/$DATE"

# 系统配置备份
log "Backing up system config..."
tar -czf "$BACKUP_DIR/$DATE/etc.tar.gz" /etc/

# 应用数据备份
log "Backing up application data..."
tar -czf "$BACKUP_DIR/$DATE/app.tar.gz" /opt/app/ 2>/dev/null || true

# 数据库备份
if command -v pg_dump > /dev/null 2>&1; then
    log "Backing up PostgreSQL..."
    su - postgres -c "pg_dump -Fc appdb" > "$BACKUP_DIR/$DATE/appdb.dump"
fi

if command -v mysqldump > /dev/null 2>&1; then
    log "Backing up MySQL..."
    mysqldump --single-transaction appdb > "$BACKUP_DIR/$DATE/appdb.sql"
fi

# Docker 卷备份
if command -v docker > /dev/null 2>&1; then
    log "Backing up Docker volumes..."
    for vol in $(docker volume ls -q); do
        docker run --rm -v "$vol":/data -v "$BACKUP_DIR/$DATE":/backup \
            alpine tar -czf "/backup/vol_${vol}.tar.gz" /data
    done
fi

# 清理旧备份
log "Cleaning old backups..."
find "$BACKUP_DIR" -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;

# 备份完整性检查
log "Verifying backup..."
if [ -f "$BACKUP_DIR/$DATE/etc.tar.gz" ]; then
    log "Backup completed successfully"
else
    log "ERROR: Backup verification failed"
    exit 1
fi
SCRIPT
chmod +x /usr/local/bin/backup

# 每天凌晨 3 点执行
echo "0 3 * * * /usr/local/bin/backup" >> /etc/crontabs/root

15.6 性能优化

系统调优参数

cat >> /etc/sysctl.conf << 'EOF'
# === 性能优化参数 ===

# 网络性能
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.ip_local_port_range = 1024 65535

# 文件系统
fs.file-max = 2097152
fs.nr_open = 1048576

# 内存
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.overcommit_memory = 1
EOF

# 用户限制
cat >> /etc/security/limits.conf << 'EOF'
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
EOF

15.7 本章小结

生产部署检查清单

类别检查项状态
系统最小化安装
系统自动安全更新
认证SSH 密钥认证
认证禁用 root 密码
网络防火墙配置
网络仅开放必要端口
监控系统监控
监控服务健康检查
备份自动备份
备份备份验证
Docker多阶段构建
Docker非 root 运行
Docker健康检查
Docker资源限制
安全审计日志
安全Fail2Ban

扩展阅读


上一章第 14 章:嵌入式应用 返回目录Alpine Linux 完全指南