docker开启远程服务(含鉴权,jekins用法,一键脚本)
·
#!/bin/bash
set -euo pipefail
# --- 配置变量 ---
CERT_DIR="/etc/docker/certs"
DAEMON_JSON="/etc/docker/daemon.json"
DOCKER_SERVICE="/lib/systemd/system/docker.service"
CA_DAYS=3650
CERT_DAYS=3650
CA_PASSWORD=""
SERVER_IP=""
# --- 颜色和格式化函数 ---
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
info() { echo -e "${GREEN}[INFO] $*${NC}"; }
warning() { echo -e "${YELLOW}[WARNING] $*${NC}"; }
error() { echo -e "${RED}[ERROR] $*${NC}"; exit 1; }
# --- 依赖检查 ---
check_dependencies() {
info "检查依赖工具..."
if ! command -v openssl &> /dev/null; then
error "未找到 'openssl'。请先安装 OpenSSL (例如: sudo apt install openssl 或 sudo yum install openssl)。"
fi
if ! command -v docker &> /dev/null; then
error "未找到 'docker'。请先安装 Docker Engine。"
fi
if [ "$(id -u)" -ne 0 ]; then
error "脚本需要 root 权限运行。请使用 sudo 执行。"
fi
}
# --- 一次性输入并验证CA密码 ---
input_ca_password() {
info "请设置CA证书密码(将用于签名服务器/客户端证书,后续无需重复输入)..."
read -s -p "输入CA密码: " CA_PASSWORD
echo
local CONFIRM_PASSWORD
read -s -p "再次输入CA密码确认: " CONFIRM_PASSWORD
echo
if [ "$CA_PASSWORD" != "$CONFIRM_PASSWORD" ]; then
error "两次输入的密码不一致!请重新运行脚本。"
fi
if [ -z "$CA_PASSWORD" ]; then
error "CA密码不能为空!"
fi
info "CA密码设置成功。"
}
# --- 自动获取服务器IP ---
get_server_ip() {
local ip=$(ip route get 1 | awk '{print $7; exit}' 2>/dev/null)
if [[ -n "$ip" && "$ip" != "127.0.0.1" ]]; then echo "$ip"; return; fi
ip=$(ip -o -4 addr list | grep -v '127.0.0.1' | awk '{print $4}' | cut -d/ -f1 | head -n 1 2>/dev/null)
if [[ -n "$ip" ]]; then echo "$ip"; return; fi
ip=$(hostname -I | awk '{print $1}' 2>/dev/null)
if [[ -n "$ip" && "$ip" != "127.0.0.1" ]]; then echo "$ip"; return; fi
echo ""
}
# --- 生成TLS证书 ---
generate_certs() {
info "开始生成 TLS 证书..."
if [ -d "$CERT_DIR" ]; then
warning "证书目录 $CERT_DIR 已存在,将被删除并重新生成。"
rm -rf "$CERT_DIR" || error "无法删除旧证书目录 $CERT_DIR"
fi
mkdir -p "$CERT_DIR" || error "无法创建证书目录 $CERT_DIR"
cd "$CERT_DIR" || error "无法进入证书目录 $CERT_DIR"
info "生成 CA 根证书 (有效期 $CA_DAYS 天)..."
openssl req -x509 -newkey rsa:4096 -keyout ca-key.pem -out ca.pem -days "$CA_DAYS" -sha256 -passin pass:"$CA_PASSWORD" -passout pass:"$CA_PASSWORD" -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=DevOps/CN=Docker-CA" || error "生成 CA 证书失败。"
info "生成服务器证书 (IP: $SERVER_IP, 有效期 $CERT_DAYS 天)..."
openssl genrsa -out server-key.pem 4096 || error "生成服务器私钥失败。"
openssl req -subj "/CN=$SERVER_IP" -sha256 -new -key server-key.pem -out server.csr || error "生成服务器证书请求失败。"
echo "subjectAltName=IP:$SERVER_IP,IP:127.0.0.1" > extfile.cnf || error "创建服务器证书扩展文件失败。"
openssl x509 -req -days "$CERT_DAYS" -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -passin pass:"$CA_PASSWORD" -CAcreateserial -out server-cert.pem -extfile extfile.cnf || error "生成服务器证书失败。"
info "生成客户端证书 (有效期 $CERT_DAYS 天)..."
openssl genrsa -out client-key.pem 4096 || error "生成客户端私钥失败。"
openssl req -subj "/CN=client" -new -key client-key.pem -out client.csr || error "生成客户端证书请求失败。"
echo "extendedKeyUsage=clientAuth" > extfile-client.cnf || error "创建客户端证书扩展文件失败。"
openssl x509 -req -days "$CERT_DAYS" -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -passin pass:"$CA_PASSWORD" -CAcreateserial -out client-cert.pem -extfile extfile-client.cnf || error "生成客户端证书失败。"
info "清理临时文件和设置权限..."
rm -f server.csr client.csr extfile.cnf extfile-client.cnf ca.srl || true
chmod 0600 ca-key.pem server-key.pem client-key.pem || error "设置私钥文件权限失败。"
chmod 0644 ca.pem server-cert.pem client-cert.pem || error "设置证书文件权限失败。"
}
# --- 配置Docker守护进程 (关键修复) ---
configure_docker_daemon() {
info "开始配置 Docker 守护进程..."
# 1. 处理 systemd 服务文件中的 hosts 冲突
info "检查并处理 Docker systemd 服务文件中的 'fd://' 或 '-H' 参数冲突..."
# 备份服务文件(如果还没有备份的话)
if [ ! -f "$DOCKER_SERVICE.bak" ]; then
cp "$DOCKER_SERVICE" "$DOCKER_SERVICE.bak" || error "无法备份 Docker systemd 服务文件。"
info "已创建 Docker 服务文件备份: $DOCKER_SERVICE.bak"
fi
# 关键修复:使用 sed 移除 ExecStart 中的 'fd://' 和所有 '-H' 参数
# 这个命令会查找以 'ExecStart=/usr/bin/dockerd' 开头的行,
# 并替换掉 'fd://' 以及任何 '-H' 开头的参数,只保留 '--containerd=...'
sed -i 's/\(ExecStart=\/usr\/bin\/dockerd\)\(.*\)/\1 --containerd=\/run\/containerd\/containerd.sock/' "$DOCKER_SERVICE" || error "修改 Docker systemd 服务文件失败。"
info "Docker systemd 服务文件已修改,移除了冲突的 'hosts' 相关参数。"
# 2. 配置 daemon.json
if [ -f "$DAEMON_JSON" ]; then
warning "Docker 配置文件 $DAEMON_JSON 已存在,将被备份为 $DAEMON_JSON.bak。"
cp "$DAEMON_JSON" "$DAEMON_JSON.bak" || error "无法备份旧配置文件。"
fi
cat > "$DAEMON_JSON" << EOF
{
"tlsverify": true,
"tlscacert": "$CERT_DIR/ca.pem",
"tlscert": "$CERT_DIR/server-cert.pem",
"tlskey": "$CERT_DIR/server-key.pem",
"hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}
EOF
info "Docker 守护进程配置文件 ($DAEMON_JSON) 已更新。"
}
# --- 重启Docker服务 ---
restart_docker_service() {
info "重启 Docker 服务..."
systemctl daemon-reload || error "执行 systemctl daemon-reload 失败。"
systemctl restart docker || error "重启 Docker 服务失败。请检查日志 (journalctl -u docker) 获取详细信息。"
systemctl enable docker || error "设置 Docker 开机自启失败。"
info "等待 Docker 服务稳定(5秒)..."
sleep 5
if ! systemctl is-active --quiet docker; then
error "Docker 服务启动失败!"
fi
info "Docker 服务已成功启动。"
}
# --- 验证配置 ---
verify_configuration() {
info "开始验证 TLS 配置..."
if docker --tlsverify --tlscacert="$CERT_DIR/ca.pem" --tlscert="$CERT_DIR/client-cert.pem" --tlskey="$CERT_DIR/client-key.pem" -H "tcp://$SERVER_IP:2376" info &> /dev/null; then
info "连接成功!Docker TLS 配置验证通过。"
info "====================================="
info "= Docker TLS 配置信息(Jenkins用) ="
info "====================================="
info "Docker Host URI: tcp://$SERVER_IP:2376"
info "TLS CA Certificate: $CERT_DIR/ca.pem"
info "TLS Client Certificate: $CERT_DIR/client-cert.pem"
info "TLS Client Key: $CERT_DIR/client-key.pem"
info "====================================="
else
error "连接失败!请检查证书配置或Docker日志。"
fi
}
# --- 主脚本入口 ---
main() {
info "===== Docker TLS 安全配置工具 ====="
check_dependencies
input_ca_password
info "自动检测服务器IP地址..."
SERVER_IP=$(get_server_ip)
if [ -z "$SERVER_IP" ]; then
error "无法自动检测到有效IP地址,请手动指定。"
fi
info "检测到的服务器IP地址为: $SERVER_IP"
generate_certs
configure_docker_daemon
restart_docker_service
verify_configuration
info "===== 配置完成! ====="
}
# 启动主程序
main "$@"
这里需要创建一个sh脚本,保存为如docker.sh
chomd +x docker.sh
./docker.sh
运行后效果如下

Docker 默认通过 unix:///var/run/docker.sock 本地套接字通信,无网络层面的身份验证和数据加密,若暴露在公网或不安全网络中,可能导致未授权访问、容器被篡改、数据泄露等风险。
TLS(Transport Layer Security)配置的核心是通过「证书认证」实现双向身份验证和通信加密
docker --tlsverify --tlscacert=ca.pem --tlscert=client-cert.pem --tlskey=client-key.pem -H tcp://服务器IP:2376 info,若输出 Docker 系统信息,说明 TLS 通信正常
一般情况下也用不到这个,jekins推荐直接将宿主docker挂载最方便。
直接用这个unix:///var/run/docker.sock
去连接宿主机的docker服务
如何需要配置需要先cat三个文件
cat /etc/docker/certs/client-key.pem
cat /etc/docker/certs/client-cert.pem
cat /etc/docker/certs/ca.pem
正确配置以后可以直接使用jekins连接
注意需要配置凭证类型如图

成功连接后如下图

更多推荐

所有评论(0)