And I wanted to have dynamic port numbers when starting a container so I could 'register' the service in Redis.
So how do you do it?
I first fiddled with using
socat
inside the startup for the service which worked, but was ugly.FYI: I ran up a vagrant ubuntu VM and installed docker 1.5 to test this.
So here's the way to do it in ruby.
# --------------------------------------------------------------------------- # Find out what our container port is # --------------------------------------------------------------------------- SVC_NAME = 'api-dummy_1' require 'socket' require 'net/http' # Create the socket to the docker host sock = Net::BufferedIO.new(UNIXSocket.new('/var/run/docker.sock')) # Go grab all the containers details request = Net::HTTP::Get.new('/containers/json') request.exec(sock, '1.1', '/containers/json') begin response = Net::HTTPResponse.read_new(sock) end while response.kind_of?(Net::HTTPContinue) response.reading_body(sock, request.response_body_permitted?) { } # Parse and loop over it trying to find our name data = JSON.parse(response.body) puts "Data received: #{data}" data.each do |container| puts "Looking at: #{container}" if container['Names'].include? "/#{SVC_NAME}" container_port = container['Ports'][0]['PublicPort'] puts "CONTAINER_PORT: #{container_port}" ENV['SVC_PORT'] = container_port.to_s break end end
Obviously you'd have to do something to handle it if you can't find the name...
And should really check the Ports array better.
The socket call returns an array something like this:
[ { "Command":"/bin/sh -c 'bundle exec foreman start'", "Created":1425423198, "Id":"5b11471046a04b64fffc2866d4eb67568221fb8c3445a326557182208559e460", "Image":"my_repo:5000/something/api-dummy_1:latest", "Names":["/api-dummy_1"], "Ports":[{"IP":"0.0.0.0","PrivatePort":5000,"PublicPort":49172,"Type":"tcp"}], "Status":"Up 1 seconds" }, { ...another one... } ]
You have to map the
/var/run/docker.sock
on running the container of course.Something like this:
#!/bin/bash export SVC_NAME=api-dummy_1 export DOCKER_HOST=tcp://127.0.0.1:2378 export REPO=10.0.0.1 # Whatever docker pull ${REPO}:5000/something/${SVC_NAME} docker kill ${SVC_NAME} docker rm ${SVC_NAME} docker run -d --env RAILS_ENV=production \ --env HOST_IP=10.0.0.2 \ --env SVC_NAME=api-dummy_1 \ --env REDIS=10.0.0.3 \ --name ${SVC_NAME} \ -p :5000 \ -v /var/run/docker.sock:/var/run/docker.sock \ ${REPO}:5000/something/${SVC_NAME}
Names and IPs to be changed of course.
Still fiddly, but it works.
YMMV.
Update:
I just realised that docker provides a
HOSTNAME
environment variable which is essentially the container id which would allow you to call /containers/#{ENV['HOSTNAME']}/json
instead of doing the loop to get the configuration for that specific id.The configuration returned is slightly different. See https://docs.docker.com/reference/api/docker_remote_api_v1.15/#inspect-a-container for details
Enjoy.
No comments:
Post a Comment