Docker in Docker 实战

Docker in Docker 实战

在容器化部署中,经常需要在容器内再运行容器。本文详细介绍 Docker-in-Docker 的两种实现方式及其完整配置过程。

一、两种实现方案对比

实现方式 原理 特点 网络视角
DooD (Docker-outside-of-Docker) 将宿主机的 /var/run/docker.sock 挂载到主容器,主容器的 docker 命令实际操作宿主机守护进程 轻量、性能好,但隔离性弱,主容器拥有宿主机 Docker 的"生杀大权" 子容器是宿主机上主容器的"兄弟",共享宿主机网络命名空间
DinD (Docker-in-Docker) 主容器内运行完整的独立 Docker 守护进程(通常使用 docker:dind 镜像) 隔离性强、更安全,但需要 --privileged 特权模式,资源开销大 子容器是完全的"孙子辈",运行在独立网络命名空间中

方案选择 :DooD 方式与直接在宿主机创建容器区别不大,本文采用 DinD 方案 ,以 log_viewer_deployer 模块为例进行实战演示。


二、环境准备:在容器中安装 Docker

2.1 基础安装步骤

bash 复制代码
# 更新软件源
sudo apt-get update

# 安装前置依赖
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 添加 Docker 官方软件源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Docker 全家桶
sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 给当前用户添加 Docker 权限
sudo usermod -aG docker $USER

# 验证安装
docker --version
docker compose version

2.2 国内源加速(可选)

如果在国内,建议使用阿里云镜像源:

dockerfile 复制代码
# Dockerfile 中使用
RUN curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \
    && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \
    && apt-get update \
    && apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \
    && rm -rf /var/lib/apt/lists/*

三、核心问题:启动 Docker 守护进程

3.1 问题现象

安装完成后,在主容器中构建子容器时报错:

复制代码
ERROR: failed to connect to the docker API at unix:///var/run/docker.sock;
check if the path is correct and if the daemon is running:
dial unix /var/run/docker.sock: connect: no such file or directory

3.2 问题分析

观察发现 /var/run 路径下没有 docker.sock 文件,原因是 Docker 守护进程(dockerd)未启动

3.3 解决方案

在 Docker Compose 配置文件中通过 command 启动 dockerd 服务:

yaml 复制代码
services:
  log_viewer:
    container_name: log_dind
    image: log:v2.0.0
    privileged: true
    ports:
      - "2400:2400"
      - "2401:2401"
      - "2402:2402"
    restart: always
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /tmp/.X11-unix:/tmp/.X11-unix
      - ./code:/root/code
      - /data/log:/root/log
      - /home:/root/home
      - docker_data:/var/lib/docker
    environment:
      - DISPLAY
      - QT_X11_NO_MITSHM=1
      - TZ=Asia/Shanghai
      - CONTAINER_TIMEZONE=Asia/Shanghai
    tty: true
    command: >
      sh -c "
      echo 'Starting dockerd...';
      dockerd > /var/log/docker.log 2>&1 &
      DOCKERD_PID=$$!;
      echo 'Waiting for Docker daemon to be ready...';
      while ! docker info >/dev/null 2>&1; do sleep 1; done;
      echo 'Docker is ready. Executing run.sh...';
      sh /root/code/run.sh;
      echo 'run.sh finished. Waiting for dockerd to exit...';
      wait $$DOCKERD_PID;
      "

volumes:
  docker_data:

关键点

  • privileged: true - 必须授予特权模式
  • 后台启动 dockerd 并等待其就绪
  • 使用 docker_data 卷持久化 Docker 数据

四、完整 Dockerfile 示例

dockerfile 复制代码
FROM ubuntu:22.04

# 安装基础工具
RUN apt-get update && apt-get install -y \
    git \
    vim \
    wget \
    tzdata \
    ntp \
    net-tools \
    sudo \
    ssh \
    python3.10 \
    python3-pip \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common \
    lsb-release \
    && rm -rf /var/lib/apt/lists/*

# 使用阿里云镜像源安装 Docker
RUN curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \
    && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \
    && apt-get update \
    && apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \
    && rm -rf /var/lib/apt/lists/*

五、子容器网络配置

5.1 子容器 Dockerfile SSH 配置

dockerfile 复制代码
# 修改 SSH 端口为 2401
RUN sed -i 's/#Port 22/Port 2401/' /etc/ssh/sshd_config

# 允许 root 登录
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

5.2 网络模式选择

子容器必须使用 host 网络模式

yaml 复制代码
services:
  sub_container:
    image: sub_image:v1.0.0
    network_mode: host  # 关键配置

六、调试命令参考

bash 复制代码
# 进入主容器
docker exec -it log_dind bash

# 构建子容器
cd /root/code/sub_docker/task_spliter_deploy
./build_container.sh

# 查看网络监听端口
netstat -tlnp

# SSH 连接报错时清理已知主机
ssh-keygen -f "/home/lx/.ssh/known_hosts" -R "[127.0.0.1]:2400"

# 查看 SSH 端口配置
cat /etc/ssh/sshd_config | grep Port

# 手动启动 SSH 服务(如服务意外停止)
/usr/sbin/sshd

七、踩坑记录:SSH 服务中断问题

问题现象

子容器构建后,主容器的 2400 端口停止监听,导致无法从宿主机访问主容器:

复制代码
tcp  0  0  0.0.0.0:2401  0.0.0.0:*  LISTEN  8282/sshd  # 只有子容器端口

临时解决

在主容器中手动执行:

bash 复制代码
/usr/sbin/sshd

执行后 2400端口恢复监听:

复制代码
tcp  0  0  0.0.0.0:2400  0.0.0.0:*  LISTEN  17027/sshd  # 主容器 SSH 恢复
tcp  0  0  0.0.0.0:2401  0.0.0.0:*  LISTEN  8282/sshd   # 子容器 SSH

待解决问题

疑问:为什么子容器构建后主容器的 sshd 服务会中断?

可能的原因:

  1. 子容器使用 host 网络模式时,端口冲突导致服务重启
  2. 子容器内的某些操作影响了宿主进程
  3. 资源竞争导致服务异常

八、总结:DinD 配置要点

主容器配置

  • ✅ 镜像构建时安装 Docker 和 Docker Compose
  • ✅ 启动命令行中运行 dockerd 服务(否则 /var/run/docker.sock 不存在)
  • ✅ 设置 privileged: true 授予特权
  • ✅ 配置端口映射:"2400:2400", "2401:2401"
  • ✅ 挂载 Docker 数据卷:docker_data:/var/lib/docker

子容器配置

  • ✅ 使用 network_mode: host 共享网络命名空间
  • ✅ 修改 SSH 端口避免冲突
  • ✅ 配置 SSH 允许 root 登录

网络架构示意

复制代码
宿主机
├── 主容器 (log_dind)
│   ├── dockerd (独立守护进程)
│   ├── SSH (2400 端口 → 映射到宿主机 2400)
│   └── 子容器
│       ├── SSH (2401 端口,host 模式)
│       └── 应用服务
└── 其他容器

参考资料

相关推荐
一水鉴天2 小时前
整体设计的自动化部署完整方案 20260311 之3 加三个附件 readme/addon/plugin(豆包助手)
运维·自动化
悟空空心2 小时前
linux创建普通只读用户
linux·运维·chrome
小小小米粒2 小时前
k8s网络通信ip申请如何层级同步进行pod网络层级网络访问请求路由流程
linux·运维·服务器
lcx_defender2 小时前
【Docker】Docker配置Redis单机模式
redis·docker·容器
Cyber4K2 小时前
【妙招系列】在Linux中测试自己邮箱是否可接收邮件?
linux·运维·python
wanhengidc2 小时前
云手机 数据信息资源共享
大数据·运维·服务器·游戏·智能手机
星夜落月2 小时前
给自己搭一个私人阅读空间:FreshRSS 部署手记
运维·服务器·网络·rss
航Hang*2 小时前
第2章:进阶Linux系统——第1节:配置与管理Samba服务器
linux·运维·服务器·笔记·学习