在Docker容器中访问Docker

时间:2019-07-17 07:01:43

标签: docker docker-compose

我有一个非常特定的开发环境用例。在某些代码中,我启动了一个容器以刮取页面并检索在容器中运行的服务(Gitlab)的令牌。

现在,我希望对运行此代码的代码进行Dockerize。具体来说,是这样的:

out, err := exec.Output("docker", "run", "--net=host", "--rm", "-e", "URL=http://127.0.0.1:8081", "-e", "USER=root", "-e", "PWD=adminadmin", "some image")

但是,在容器中运行此代码时,显然我的代码会抛出panic: exec: "docker": executable file not found in $PATH,因为在容器中无法识别docker

如何在Docker容器中安装Docker?我可以以某种方式与主机绑定吗?这种情况应该发生在Dockerfile中,还是可以通过我用来旋转它的docker-compose.yml文件来定义这种行为?

我在OSX上。 which docker的输出为/usr/local/bin/docker

3 个答案:

答案 0 :(得分:2)

是的,有可能,它在docker中被称为docker或DinD。

甚至不必介意自己安装docker-docker的official dind image带有广泛的标签。

答案 1 :(得分:0)

所以,我刚在docker for windows的Mac上尝试过:

docker-compose.yaml:

version: '3'
services:
  app:
    image: ubuntu:16.04
    volumes:
      - /usr/local/bin/docker:/usr/local/bin/docker
      - /var/run/docker.sock:/var/run/docker.sock
    command: docker version

执行:

MAC-MINI:try guest$ docker-compose up
Starting try_app_1 ... done
Attaching to try_app_1
app_1  | Client: Docker Engine - Community
app_1  |  Version:           18.09.2
app_1  |  API version:       1.39
app_1  |  Go version:        go1.10.8
app_1  |  Git commit:        6247962
app_1  |  Built:             Sun Feb 10 04:11:44 2019
app_1  |  OS/Arch:           linux/amd64
app_1  |  Experimental:      false
app_1  |
app_1  | Server: Docker Engine - Community
app_1  |  Engine:
app_1  |   Version:          18.09.2
app_1  |   API version:      1.39 (minimum version 1.12)
app_1  |   Go version:       go1.10.6
app_1  |   Git commit:       6247962
app_1  |   Built:            Sun Feb 10 04:13:06 2019
app_1  |   OS/Arch:          linux/amd64
app_1  |   Experimental:     false
try_app_1 exited with code 0

使用docker守护进程和主机的docker客户端似乎都可以。

如果您打算使用从主机挂载的docker client,也可以使用静态二进制文件,请参见how to install static binary

更新:

此外,我尝试运行一个真实的容器,而不仅仅是像下面的docker version

services:
  app:
    image: ubuntu:16.04
    volumes:
      - /usr/local/bin/docker:/usr/local/bin/docker
      - /var/run/docker.sock:/var/run/docker.sock
    command: docker run --rm hello-world

It's still ok as next:

$ docker-compose up
Recreating try_app_1 ... done
Attaching to try_app_1
app_1  | Unable to find image 'hello-world:latest' locally
app_1  | latest: Pulling from library/hello-world
app_1  | 1b930d010525: Pulling fs layer
app_1  | 1b930d010525: Download complete
app_1  | 1b930d010525: Pull complete
app_1  | Digest: sha256:6540fc08ee6e6b7b63468dc3317e3303aae178cb8a45ed3123180328bcc1d20f
app_1  | Status: Downloaded newer image for hello-world:latest
app_1  |
app_1  | Hello from Docker!
app_1  | This message shows that your installation appears to be working correctly.
app_1  |
app_1  | To generate this message, Docker took the following steps:
app_1  |  1. The Docker client contacted the Docker daemon.
app_1  |  2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
app_1  |     (amd64)
app_1  |  3. The Docker daemon created a new container from that image which runs the
app_1  |     executable that produces the output you are currently reading.
app_1  |  4. The Docker daemon streamed that output to the Docker client, which sent it
app_1  |     to your terminal.
app_1  |
app_1  | To try something more ambitious, you can run an Ubuntu container with:
app_1  |  $ docker run -it ubuntu bash
app_1  |
app_1  | Share images, automate workflows, and more with a free Docker ID:
app_1  |  https://hub.docker.com/
app_1  |
app_1  | For more examples and ideas, visit:
app_1  |  https://docs.docker.com/get-started/
app_1  |
try_app_1 exited with code 0

根据@PierreB的建议进行的第二次更新,以添加有关如何使用静态二进制文件的更多信息:

  1. https://download.docker.com/下载,选择一个适合您目标映像的软件包,例如,如果目标映像是linux,则从here下载。

  2. 将二进制文件解包到当前文件夹,您会看到名称为docker的Docker客户端,它是一个独立的二进制文件。

  3. 将docker-compose.yaml更改为next,以将该静态二进制文件从主机安装到容器:

    services:
      app:
        image: ubuntu:16.04
        volumes:
          - ./docker:/usr/local/bin/docker
          - /var/run/docker.sock:/var/run/docker.sock
        command: docker run --rm hello-world
    

答案 2 :(得分:0)

这里发生了2种不同的事情:

  • 您将需要在golang容器内安装一个docker客户端
  • 您将需要一个可访问的docker守护程序(服务器)

为了在运行中的容器中安装客户端,您似乎使用了基于debian的golang映像,您可以:apt-get update && apt-get install -yq docker

在这一点上,如果您尝试执行docker run命令,您将得到类似:

docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.

这意味着您现在必须为Docker客户端提供一个工作的docker服务器。如Efrat Levitan's answer中所述,可以通过运行另一个容器(称为服务)并运行dind(docker中的docker)来完成此操作。然后,您将必须定义变量DOCKER_HOST: tcp://<docker_server_address>:2375/。地址将取决于您的设置以及如何启动容器。

另一种方法可以替换主机docker套接字(不建议这样做,因为它可能会导致数据损坏)。

要了解其中的含义,您可能需要阅读Jérôme Petazzoni's article有关docker中的docker的信息。