Moby: 无法通过远程 API 绑定端口

创建于 2016-06-10  ·  3评论  ·  资料来源: moby/moby

我能够从 CLI 启动容器并映射它们的端口。 但是,通过远程 API 似乎不可能实现同样的事情。 在这两种情况下,我都在 Mac OS El Capitan 上使用 docker-machine 运行。

我现在已经将测试用例简化到了最低限度,它基于一个标准的 ubuntu 映像,只安装了一个包 netcat-openbsd、apt-get(并以nc运行)。

重置系统

在每次测试之前,我都会运行

eval $(docker-machine env default); docker stop $(docker ps -a -q); docker rm $(docker ps -a -q) 

...停止并删除所有以前的容器。

CLI 版本(可寻址)

以下 CLI 成功启动了可寻址服务...

docker run -it --rm -p 3000:3000 ubuntu-nc /bin/bash -c 'echo "Working" | nc -l 3000'

证明可寻址服务

我可以通过运行以下命令证明该服务可以从 docker 容器外部(在 docker-machine 分配给 VM 的 IP 上)正确映射的端口访问...

$ nc 192.168.99.100 3000
Working

NodeJS 版本(不可寻址)

尝试通过 Dockerode on Node 提供相同的服务会创建一个不可寻址的服务,尽管 Dockerode 显然将所有参数传递给 Docker,而且我显然符合https://godoc.org/github 的约定。 com/docker/engine-api/types/container#Confighttps://godoc.org/github.com/docker/engine-api/types/container#HostConfig因此提出了这个问题。

这是我试图使用的代码......

var fs = require("fs"),
    dockermachine = require("dockermachine"),
    dockerode = require("dockerode");

var createOptions = {
    Image:"ubuntu-nc",
    Tty:true,
    ExposedPorts: {
        "3000/tcp:": {},
    },
    Cmd:[
        "/bin/bash", "-c", "echo Working | nc -l 3000"
    ],
    HostConfig:{
        PortBindings: {
            "3000/tcp": [{
                "HostIP":"0.0.0.0",
                "HostPort": "3000"
            }],
        },
    },
};

dockermachine.inspect("default").then(function(info){

    var docker = new dockerode({
        host:info.Driver.IPAddress,
        port:2376,
        ca:fs.readFileSync(info.HostOptions.AuthOptions.CaCertPath),
        cert:fs.readFileSync(info.HostOptions.AuthOptions.ClientCertPath),
        key:fs.readFileSync(info.HostOptions.AuthOptions.ClientKeyPath),
    });

    docker.createContainer(createOptions, function(err, result){
        var container = docker.getContainer(result.id);

        container.attach({stream: true, stdout: true, stderr: true}, function (err, stream) {
            stream.pipe(process.stdout);
        });

        container.start(function(err, data){
            if(err) console.log(err);
        });

    });
});

NodeJS 版本肯定是在容器中运行服务

例如,我可以从它自己的容器中访问该服务......

$ docker exec -it 3dd7 /bin/bash -c "nc localhost 3000"
Working

但是,它显然不尊重已请求的外部端口映射,因此如果我从头开始重新启动上面的工作测试,然后尝试以与前面的“证明可寻址服务”相同的方式从容器外部访问服务,它报告连接失败。

$ nc -v 192.168.99.100 3000
nc: connectx to 192.168.99.100 port 3000 (tcp) failed: Connection refused

额外的调试信息

docker version的输出:

bash-3.2$ docker version
Client:
 Version:      1.10.1
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   9e83765
 Built:        Fri Feb 12 22:11:40 UTC 2016
 OS/Arch:      darwin/amd64

Server:
 Version:      1.11.2
 API version:  1.23
 Go version:   go1.5.4
 Git commit:   b9f10c9
 Built:        Wed Jun  1 21:20:08 2016
 OS/Arch:      linux/amd64

docker info的输出:

bash-3.2$ docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 3
Server Version: 1.11.2
Storage Driver: aufs
 Root Dir: /mnt/sda1/var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 7
 Dirperm1 Supported: true
Logging Driver: json-file
Plugins: 
 Volume: local
 Network: null host bridge
Kernel Version: 4.4.12-boot2docker
Operating System: Boot2Docker 1.11.2 (TCL 7.1); HEAD : a6645c3 - Wed Jun  1 22:59:51 UTC 2016
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 995.9 MiB
Name: default
ID: FWTM:2N6I:VM5L:OL4U:RD3K:HFKH:6VYP:QSV5:VHG5:ZTSW:GFOP:CDNT
Debug mode (server): true
 File Descriptors: 14
 Goroutines: 35
 System Time: 2016-06-10T13:58:19.242425997Z
 EventsListeners: 0
 Init SHA1: 
 Init Path: 
 Docker Root Dir: /mnt/sda1/var/lib/docker
Labels:
 provider=virtualbox
versio1.11

最有用的评论

好的,看起来有一个虚假的分号,比如......

ExposedPorts: {
        "3000/tcp:": {},
 },

...这导致 ExposedPorts 被默默地忽略。

很遗憾没有任何明显的错误报告,这显然要归功于 Remote API 的“开放模式模型”行为。

当属性显然旨在控制 Docker 时,我看不出这种对错误的吞咽如何成为一项功能。

所有3条评论

好的,看起来有一个虚假的分号,比如......

ExposedPorts: {
        "3000/tcp:": {},
 },

...这导致 ExposedPorts 被默默地忽略。

很遗憾没有任何明显的错误报告,这显然要归功于 Remote API 的“开放模式模型”行为。

当属性显然旨在控制 Docker 时,我看不出这种对错误的吞咽如何成为一项功能。

等等,什么? 是这样吗?...错字?
我一直在阅读这篇文章,因为我有同样的问题——无法让任何端口映射工作,没有网络 IP 地址。
(但我没有你的错字)
这里就没有什么可学的了吗?

没关系...我学到了一些东西:创建容器后,您必须在获得 IP 地址或端口映射之前“启动()”容器。

此页面是否有帮助?
0 / 5 - 0 等级