实践篇:15-构建运维工具

本篇我们来构建一些常见的运维场景中可能会用到的工具镜像。将这些工具容器化,可以方便地在不同环境(如本地、CI/CD 流水线)中以一致的方式运行它们。这些镜像通常可以归类为我们在设计篇中提到的 工具层 (Tools Layer) 镜像。

Ansible 执行环境镜像

Ansible 是一个广泛使用的 IT 自动化工具,用于配置管理、应用部署、任务编排等。构建一个包含 Ansible 的 Docker 镜像,可以方便地在 CI/CD 流水线或其他自动化脚本中调用 Ansible 来执行 Playbook,而无需在宿主机上安装 Ansible 及其依赖。

新建ansible目录

mkdir -p common/tools/ansible
cd common/tools/ansible

Dockerfile 示例 (common/tools/ansible/Dockerfile):

#syntax=harbor.leops.local/library/docker/dockerfile:1

FROM harbor.leops.local/common/tools/python:3

ARG ANSIBLE_VERSION=11.5.0

LABEL org.opencontainers.image.authors="ops@leops.local"  \
      org.opencontainers.image.source="http://git.leops.local/ops/dockerfiles-base/common/tools/ansible/Dockerfile" \
      org.opencontainers.image.description="Minimal base tools for ansible applications with non-root user."

RUN \
    set -exu; \
    # 创建非root用户,增强安全性
    groupadd -r nonroot; \
    useradd -r -m -g nonroot nonroot; \
    apt-get update; \
    # 安装基础工具和SSH客户端
    apt-get install -y --no-install-recommends \
            openssl \
            openssh-client; \
    # 安装指定版本的Ansible
    pip3 install --no-cache-dir ansible==${ANSIBLE_VERSION}; \
    # 验证安装并创建基础配置
    ansible --version; \
    mkdir /etc/ansible; \
    ansible-config init --disabled -t all > /etc/ansible/ansible.cfg; \
    # 清理临时文件,减小镜像体积
    apt-get clean; \
    rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* /tmp/* /var/tmp/*; \
    truncate -s 0 /var/log/*log;

# 切换到非root用户,提高安全性
USER nonroot:nonroot

构建脚本示例 (common/tools/ansible/build.sh):

#!/bin/bash

set -e

# 配置
REGISTRY="harbor.leops.local"
IMAGE_BASE_NAME="common/tools/ansible"
VERSION="11.5.0"# Ansible版本


# 声明镜像地址数组
declare -a IMAGE_PATHS
IMAGE_PATHS+=(
    "${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION}"      # 完整版本号标签
    "${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION%.*}"   # 次版本号标签
    "${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION%%.*}"# 主版本号标签
)


build_image() {

    echo "Building and pushing image:"
    for img in "${IMAGE_PATHS[@]}"; do echo -e " $img"; done

    # 构建镜像
    docker buildx build \
      $(for img in "${IMAGE_PATHS[@]}"; do echo -n "-t $img "; done) \
      --label "org.opencontainers.image.created=$(date --rfc-3339=seconds)" \
      --build-arg "ANSIBLE_VERSION=${VERSION}" \
      --add-host nexus.leops.local=192.168.77.140 \
      --provenance=false \
      --pull \
      --push \
      .

    echo "Build complete."
}

# 参数处理
case "$1" in
    "list-tags")
        # 输出镜像标签列表
        printf '%s\n' "${IMAGE_PATHS[@]}"
        ;;
    *)
    build_image
    ;;
esac

如何使用?

# 假设你的Playbook在当前目录的playbook.yml文件中
docker run --rm -it \
  # 挂载当前目录到容器的/ansible目录
  -v $(pwd):/ansible \
  # 挂载SSH密钥,用于Ansible连接远程主机
  -v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \
  # 挂载主机清单文件
  -v $(pwd)/inventory:/etc/ansible/hosts \
  harbor.leops.local/common/tools/ansible:11.5.0 \
  # 执行playbook命令
  ansible-playbook playbook.yml -i inventory

Docker CLI 工具镜像 (用于 CI/CD)

在 CI/CD 流水线中,我们经常需要执行 Docker 命令来构建、推送或管理镜像和容器。虽然可以直接在 Runner 上安装 Docker,但有时使用一个包含 Docker CLI (和 buildx 插件) 的工具镜像会更方便、更隔离,并且能确保所有环境使用一致版本的 Docker CLI。

重要提示: 这种镜像不包含 Docker 引擎本身。它需要通过挂载宿主机的 Docker Socket (/var/run/docker.sock) 来与宿主机的 Docker 引擎通信。这种方式称为 Docker-out-of-Docker (DooD),相比 Docker-in-Docker (DinD) 通常更推荐,因为它避免了嵌套虚拟化的性能开销,并且能共享宿主机的镜像缓存。但也需要注意这种方式存在权限和安全风险,因为容器可以通过 Docker Socket 完全控制宿主机的 Docker 服务。

新建docker-cli目录

mkdir -p common/tools/docker-cli
cd common/tools/docker-cli

Dockerfile 示例 (common/tools/docker-cli/Dockerfile):

#syntax=harbor.leops.local/library/docker/dockerfile:1

FROM harbor.leops.local/common/os/debian:bullseye

ARG DOCKER_VERSION=28.1.1

LABEL org.opencontainers.image.authors="ops@leops.local"  \
      org.opencontainers.image.source="http://git.leops.local/ops/dockerfiles-base/common/tools/docker-cli/Dockerfile" \
      org.opencontainers.image.description="Docker CLI tools"

# 启用BuildKit以加速构建过程
ENV DOCKER_BUILDKIT=1

# 安装Docker CLI和buildx插件
RUN set -eux; \
    # 添加Docker官方源(这里使用阿里云镜像加速)
    echo "deb [trusted=yes] https://mirrors.aliyun.com/docker-ce/linux/debian bullseye stable" > /etc/apt/sources.list.d/docker-ce.list; \
    apt-get update; \
    # 安装Docker CLI和buildx插件,指定版本以确保一致性
    apt-get install -y -qq --no-install-recommends git docker-buildx-plugin docker-ce-cli=5:${DOCKER_VERSION}-1~debian.11~bullseye; \
    # 清理缓存文件,减小镜像体积
    apt-get clean; \
    rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* /tmp/* /var/tmp/*; \
    truncate -s 0 /var/log/*log;

构建脚本示例 (common/tools/docker-cli/build.sh):

#!/bin/bash

set -e

# 配置
REGISTRY="harbor.leops.local"
IMAGE_BASE_NAME="common/tools/docker-cli"
VERSION="28.1.1"# Docker CLI版本


# 声明镜像地址数组
declare -a IMAGE_PATHS
IMAGE_PATHS+=(
    "${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION}"      # 完整版本号标签
    "${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION%.*}"   # 次版本号标签(28.1)
    "${REGISTRY}/${IMAGE_BASE_NAME}:${VERSION%%.*}"# 主版本号标签(28)
)


build_image() {

    echo "Building and pushing image:"
    for img in "${IMAGE_PATHS[@]}"; do echo -e " $img"; done

    # 构建镜像
    docker buildx build \
      $(for img in "${IMAGE_PATHS[@]}"; do echo -n "-t $img "; done) \
      --label "org.opencontainers.image.created=$(date --rfc-3339=seconds)" \
      --build-arg "DOCKER_VERSION=${VERSION}" \
      --provenance=false \
      --pull \
      --push \
      .

    echo "Build complete."
}

# 参数处理
case "$1" in
    "list-tags")
        # 输出镜像标签列表
        printf '%s\n' "${IMAGE_PATHS[@]}"
        ;;
    *)
    build_image
    ;;
esac

如何使用 (示例: 在 CI/CD 中构建镜像)?

# 假设 CI/CD Runner 环境可以挂载 Docker Socket
docker run --rm \
  # 挂载 Docker Socket,使容器内的Docker CLI能与宿主机Docker引擎通信
  -v /var/run/docker.sock:/var/run/docker.sock \
  # 挂载项目代码 (构建上下文)
  -v $(pwd):/workspace \
  # 指定工作目录
  -w /workspace \
  harbor.leops.local/common/tools/docker-cli:28.1.1 \
  # 在容器内执行 docker build 命令
  docker build -t myapp:ci-build .

安全提示: 在生产环境中使用 DooD 模式时,建议:

  1. 使用最小权限原则,只挂载必要的目录
  2. 考虑使用 Docker 插件如docker-socket-proxy限制对 Docker Socket 的访问权限
  3. 仅在可信环境中使用此方式

transfer.sh 文件传输服务

transfer.sh 是一个简单、轻量级的文件分享服务。你可以自己部署一个实例,方便在服务器之间或与他人快速分享文件,无需复杂的文件服务器配置。这部分是部署一个独立服务,而非构建工具镜像。

部署步骤

  1. 创建数据存储目录:
mkdir -p /data/transfer/data  # data目录用于存储上传的文件
cd /data/transfer
  1. Docker Compose 配置文件 (/data/transfer/docker-compose.yml):
services:
  transfer:
    container_name: transfer
    image: dutchcoders/transfer.sh:latest
    command: --provider local --basedir /data/ --temp-path /data/
    restart: always
    ports:
      - '8085:8080' # 将容器的8080端口映射到主机的8085端口
    volumes:
      - ./data:/data # 挂载数据目录
      - '/usr/share/zoneinfo/Asia/Shanghai:/etc/localtime' # 设置正确的时区
  1. 启动服务:
docker compose up -d  # 后台运行服务
  1. 配置 Nginx 反向代理:

创建 Nginx 配置文件 /data/nginx/nginx_data/conf.d/transfer.conf:

server {
    listen 80;
    server_name transfer.leops.local;  # 服务域名,需要在DNS或hosts文件中配置

    access_log /var/log/nginx/transfer_access.log;
    error_log /var/log/nginx/transfer_error.log;

    location / {
        proxy_pass http://192.168.77.140:8085;  # transfer.sh服务地址和端口
        proxy_set_header  Host              $http_host;
        proxy_set_header  X-Real-IP         $remote_addr;
        proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Proto $scheme;

        # 关闭缓冲,适用于文件传输场景
        proxy_buffering off;
        proxy_request_buffering off;

        # 设置较长的超时时间,适合大文件传输
        proxy_send_timeout 900;
        proxy_read_timeout 900;
    }
}

创建完配置文件后,重新加载 Nginx 配置:

# 在运行 Nginx 的服务器上执行
docker exec nginx-proxy sh -c "nginx -t && nginx -s reload"

使用示例

以下是如何使用这个服务的基本示例:

# 上传文件,返回一个下载链接
curl --upload-file ./myfile.txt http://transfer.leops.local/myfile.txt

# 下载文件
wget <返回的下载链接>

# 也可以通过浏览器访问服务并上传下载文件
# 在浏览器中打开: http://transfer.leops.local

版本控制

完成配置后,记得将所有文件提交到 Git 仓库进行版本控制:

git add -A .
git commit -m "feat: add 运维工具"
git push

通过构建这些标准化的运维工具镜像,可以提高自动化脚本和 CI/CD 流水线的健壮性和可移植性。容器化工具不仅解决了环境依赖问题,还确保了工具版本的一致性和可控性,特别适合在多环境、多团队协作的企业中使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

企鹅侠客

您的打赏是我创作旅程中的关键燃

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值