Sou capaz de lançar contêineres e mapear suas portas a partir da CLI. No entanto, a mesma coisa parece impossível através da API Remota. Em ambos os casos estou rodando com docker-machine no Mac OS El Capitan.
Agora simplifiquei o caso de teste para o mínimo absoluto, que é baseado em uma imagem padrão do Ubuntu com apenas um único pacote netcat-openbsd, apt-get instalado (e executado como nc
).
Antes de cada teste, eu corro
eval $(docker-machine env default); docker stop $(docker ps -a -q); docker rm $(docker ps -a -q)
...para parar e remover todos os contêineres anteriores.
A CLI a seguir abre com sucesso um serviço endereçável...
docker run -it --rm -p 3000:3000 ubuntu-nc /bin/bash -c 'echo "Working" | nc -l 3000'
Posso provar que o serviço é acessível com portas mapeadas corretamente de fora do contêiner do docker (no IP alocado à VM pela máquina do docker) executando o seguinte...
$ nc 192.168.99.100 3000
Working
A tentativa de trazer o mesmo serviço via Dockerode no Node cria um serviço que não é endereçável, mesmo que o Dockerode aparentemente passe todos os argumentos para o Docker, e eu aparentemente esteja em conformidade com as convenções de https://godoc.org/github. com/docker/engine-api/types/container#Config e https://godoc.org/github.com/docker/engine-api/types/container#HostConfig , portanto, levantando esse problema.
Este é o código que estou tentando usar...
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);
});
});
});
A versão NodeJS definitivamente executa o serviço no container
Por exemplo, posso acessar o serviço de dentro de seu próprio contêiner ...
$ docker exec -it 3dd7 /bin/bash -c "nc localhost 3000"
Working
No entanto, aparentemente, ele não respeita o mapeamento de porta externa que foi solicitado, portanto, se eu reiniciar o teste de trabalho acima do zero, tentar acessar o serviço de fora do contêiner da mesma maneira que 'Proving Addressable Service' anteriormente, ele relata uma conexão com falha.
$ nc -v 192.168.99.100 3000
nc: connectx to 192.168.99.100 port 3000 (tcp) failed: Connection refused
Saída de 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
Saída de 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
OK, parece que havia um ponto e vírgula falso como...
ExposedPorts: {
"3000/tcp:": {},
},
...o que fez com que o ExposedPorts fosse ignorado silenciosamente.
É muito lamentável não ter nenhum relatório de erro aparente, aparentemente graças ao comportamento de 'modelo de esquema aberto' da API remota.
Não consigo ver como essa ingestão de erros quando as propriedades são claramente destinadas a controlar o Docker poderia ser um recurso.
espere o que? foi isso?... um erro de digitação?
Eu tenho lido isso porque tenho o mesmo problema - não consigo fazer nenhum mapeamento de porta funcionar, nenhum endereço IP de rede.
(mas não tenho seu erro de digitação)
Não há mais nada a ser aprendido aqui?
não importa... eu aprendi uma coisa: depois de criar um container, você precisa "iniciar ()" o container antes de obter um endereço IP ou mapeamentos de porta.
Comentários muito úteis
OK, parece que havia um ponto e vírgula falso como...
...o que fez com que o ExposedPorts fosse ignorado silenciosamente.
É muito lamentável não ter nenhum relatório de erro aparente, aparentemente graças ao comportamento de 'modelo de esquema aberto' da API remota.
Não consigo ver como essa ingestão de erros quando as propriedades são claramente destinadas a controlar o Docker poderia ser um recurso.