基于containerd的AKS集群中运行Docker命令的解决方案咨询
在AKS containerd运行时环境中实现Docker-in-Docker的可行方案
问题背景
我们在私有AKS集群(版本v1.22)中部署了Azure DevOps代理,流水线包含基于Dockerfile构建自定义镜像、推送镜像及docker-compose启停等Docker相关任务。但当前AKS仅支持containerd运行时,无Docker运行时支持,导致应用构建完全停滞。
尝试在VSTS代理的Dockerfile中添加Docker安装配置(如下代码),但Docker服务无法正常启动,咨询在AKS容器内实现Docker-in-Docker的可行方案:
现有VSTS代理Dockerfile
FROM ubuntu:18.04 # To make it easier for build and release pipelines to run apt-get, # configure apt to not require confirmation (assume the -y argument by default) ENV DEBIAN_FRONTEND=noninteractive RUN echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ curl \ wget \ jq \ git \ iputils-ping \ libcurl4 \ libicu60 \ libunwind8 \ netcat \ telnet \ libssl1.0 \ python \ python3 \ openjdk-11-jdk-headless \ gnupg \ make \ && rm -rf /var/lib/apt/lists/* RUN curl -LsS https://aka.ms/InstallAzureCLIDeb | bash \ && rm -rf /var/lib/apt/lists/* #Instal Helm ARG HELM_VERSION="v3.7.2" ARG HELM_LOCATION="https://get.helm.sh" ARG HELM_FILENAME="helm-${HELM_VERSION}-linux-amd64.tar.gz" RUN set -x && \ wget ${HELM_LOCATION}/${HELM_FILENAME} && \ echo Verifying ${HELM_FILENAME}... && \ echo Extracting ${HELM_FILENAME}... && \ tar zxvf ${HELM_FILENAME} && mv /linux-amd64/helm /usr/local/bin/ && \ rm ${HELM_FILENAME} && rm -r /linux-amd64 #install kubectl ENV KUBECTL_VERSION="v1.18.9" RUN set -x && \ curl --retry 5 --retry-connrefused -LO "https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" && \ chmod +x kubectl && \ mv kubectl /usr/local/bin/kubectl #install node RUN curl -sL https://deb.nodesource.com/setup_11.x | bash - RUN apt-get -y install nodejs RUN npm install #install maven 3.8.6 RUN mkdir -p /usr/share/maven /usr/share/maven/ref \ && echo "Downlaoding maven" \ && curl -fsSL -o /tmp/apache-maven.tar.gz https://apache.osuosl.org/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.tar.gz \ \ && echo "Unziping maven" \ && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \ \ && echo "Cleaning and setting links" \ && rm -f /tmp/apache-maven.tar.gz \ && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn # 6- Define environmental variables required by Maven, like Maven_Home directory and where the maven repo is located ENV MAVEN_HOME /usr/share/maven ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2" ENV JAVA_HOME /usr/lib/jvm/java-11-openjdk-amd64 #install docker daemon inside docker RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg RUN 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" | tee /etc/apt/sources.list.d/docker.list > /dev/null RUN apt-get update RUN apt-get install docker-ce docker-ce-cli containerd.io -y # Can be 'linux-x64', 'linux-arm64', 'linux-arm', 'rhel.6-x64'. ENV TARGETARCH=linux-x64 WORKDIR /azp COPY ./vstsagent/ . COPY ./start.sh . COPY ./docker.sh . RUN chmod +x start.sh docker.sh CMD ["./docker.sh"] ENTRYPOINT ["./start.sh"]
启动脚本docker.sh
#!/bin/bash echo "DOCKER STARTS HERE" service docker start docker version docker ps echo "DOCKER ENDS HERE"
可行解决方案
方案1:配置特权模式的Docker-in-Docker(DinD)
在AKS容器内运行DinD必须启用特权模式,同时调整启动逻辑确保Docker daemon正常初始化:
- Pod部署时添加SecurityContext配置:
securityContext: privileged: true capabilities: add: ["SYS_ADMIN"]
- 修改Docker启动脚本docker.sh:
替换service docker start为直接启动dockerd并等待就绪:
#!/bin/bash echo "DOCKER STARTS HERE" # 后台启动Docker daemon dockerd & # 等待daemon初始化完成 sleep 10 # 验证Docker状态 docker version docker ps echo "DOCKER ENDS HERE"
- Dockerfile中添加存储驱动配置:
在安装Docker后添加一行配置overlay2驱动:
RUN echo '{ "storage-driver": "overlay2" }' > /etc/docker/daemon.json
方案2:挂载宿主Docker套接字(非特权模式)
如果特权模式不符合安全规范,可以尝试挂载AKS节点的Docker套接字(需确认节点已安装Docker daemon):
- 在Pod配置中添加卷挂载:
volumes: - name: docker-sock hostPath: path: /var/run/docker.sock containers: - name: azp-agent volumeMounts: - mountPath: /var/run/docker.sock name: docker-sock
- 此方式无需在代理容器内启动Docker daemon,仅保留Docker CLI即可,可简化Dockerfile中相关安装步骤。
方案3:使用Kaniko替代Docker构建
Kaniko是无daemon的镜像构建工具,完美适配containerd运行时,无需特权:
- 在Azure DevOps流水线中替换Docker构建任务为Kaniko任务
- Kaniko直接读取Dockerfile构建镜像并推送至镜像仓库,完全不依赖Docker daemon
- 代理容器无需安装Docker,大幅减少镜像体积和配置复杂度
问题排查总结
当前Docker服务无法启动的核心原因:
- 容器未以特权模式运行,缺少启动Docker daemon的必要权限
service docker start在容器环境中无法可靠初始化daemon,直接使用dockerd命令更稳定- 未配置overlay2存储驱动,导致daemon启动失败
内容的提问来源于stack exchange,提问作者Vowneee
相关产品推荐
相关产品推荐

