我想过一个非常有意思的东西:在docker里面运行docker,然后在docker里运行的docker中再运行一个docker,接着在docker里运行的docker里运行的docker中再开一个docker..接着迭代100次会发生什么

结合这篇文章:https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/ 以及自己的经验与实践总结出下文.

“If you want the short solution without the details, just scroll to the bottom of this article. ☺”

Bad

如果你在docker中运行了docker,会导致一下问题:

1.当你使用-privileged的时候会导致一个在内部docker与外部docker之间的安全配置无法合并的冲突,是关于LSM (Linux Security Modules)的

2.外部docker运行在正常的文件系统中,但内部docker运行在写时拷贝的文件系统,会直接导致无法运行或者因为命名空间的问题影响其他container

Solution

其实基本上来说是不存在需要在docker中跑docker这种需求的,你想要的只是在docker中启动一个docker的container来运行你的程序,并不关心这个container在哪个docker进程中.下面提供一种方式可以让你在docker内部调用这个docker程序开启新的container帮助你完成工作:

1
docker run -v /var/run/docker.sock:/var/run/docker.sock ...

这样你程序所在的container中已经有权限访问docker的socket,因此可以用docker run启动同胞兄弟而不是子容器

1
2
3
4
5
6
7
8
9
/ # docker ps
➜  ~ docker run -v /var/run/docker.sock:/var/run/docker.sock -ti docker
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
8c84704e890e        docker              "docker-entrypoint..."   2 seconds ago       Up 1 second                             brave_lichterman
/ # docker run -v /var/run/docker.sock:/var/run/docker.sock -ti docker
/ # docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
34dcf16326c2        docker              "docker-entrypoint..."   3 seconds ago       Up 2 seconds                            inspiring_mcnulty
8c84704e890e        docker              "docker-entrypoint..."   37 seconds ago      Up 36 seconds                           brave_lichterman

Practice

使用上述Solution打包一个docker镜像

构建打包镜像的环境

网上实在没有找到包含docker+aws+packer的ubuntu docker镜像,以下是dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
FROM ubuntu:14.04

# install docker
RUN apt-get update \
    && apt-get -y install ca-certificates \
      curl \
      openssl \
      unzip

ENV DOCKER_BUCKET get.docker.com
ENV DOCKER_VERSION 1.13.0
ENV DOCKER_SHA256 fc194bb95640b1396283e5b23b5ff9d1b69a5e418b5b3d774f303a7642162ad6

RUN set -x \
  && curl -fSL "https://${DOCKER_BUCKET}/builds/Linux/x86_64/docker-${DOCKER_VERSION}.tgz" -o docker.tgz \
  && echo "${DOCKER_SHA256} *docker.tgz" | sha256sum -c - \
  && tar -xzvf docker.tgz \
  && mv docker/* /usr/local/bin/ \
  && rmdir docker \
  && rm docker.tgz \
  && docker -v

# install aws
RUN apt-get install -y python-pip groff-base
RUN pip install awscli

# install packer
RUN curl -OL#\
 https://releases.hashicorp.com/packer/0.12.2/packer_0.12.2_linux_amd64.zip &&\
 unzip packer_0.12.2_linux_amd64.zip -d /usr/local/bin/

# copy file
WORKDIR /build
COPY infrastructure infrastructure
COPY pipeline/test/env_packet/packet4testEnv.sh /usr/local/bin

ENTRYPOINT ["packet4testEnv.sh"]

然后添加打包脚本

1
2
3
4
5
6
7
8
echo "----------------------------------build packet environment"
docker build -t packer_aws_env -f ./pipeline/test/env_packet/Dockerfile .
echo "----------------------------------tag image"
docker tag packer_aws_env $ECR_REPOSITORY:sf-test-packet
echo "----------------------------------aws login"
aws ecr get-login | bash
echo "----------------------------------push to ecr"
docker push $ECR_REPOSITORY:sf-test-packet

结合packer与ecr构建并上传镜像

外层docker环境

1
2
3
4
5
6
7
8
9
10
11
12
echo "----------------------------------pull docker image from ecr"
aws ecr get-login | bash
docker pull $ECR_REPOSITORY:sf-test-packet

echo "----------------------------------run packer in docker and packet for test environment"
docker run --rm \
 -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
 -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
 -e AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION \
 -e ECR_LOGIN_SERVER=$ECR_LOGIN_SERVER \
 -e ECR_REPOSITORY=$ECR_REPOSITORY \
 $ECR_REPOSITORY:sf-test-packet

内层docker环境

1
"run_command": ["-d", "-i", "-t", "-v", "/var/run/docker.sock:/var/run/docker.sock", "", "/bin/bash"]

Comments