10 logging.getLogger(
"docker").setLevel(logging.INFO)
11 logging.getLogger(
"urllib3").setLevel(logging.INFO)
12 if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
19 return [
'roslaunch',
'rosrun']
24 Remotely deploys a docker container with a user specified image of a 29 >>> obj = image.DockeROSImage(roscommand, config) 35 def __init__(self, roscommand, config, dockerfile=None):
37 Initilizes the commands with the rospkg configuration and roscommands allowed in this context 39 roscommand: any of suppoorted roscommands (rosrun/roslaunch) 40 config: configuraion for rospkg and connection to docker host 44 logging.debug(
"Python Version: " + sys.version +
"\ndocker (library) Version: " + docker.__version__)
47 assert isinstance(roscommand, list),
"roscommand should be a list" 48 assert isinstance(roscommand[0], str),
"roscommand should be a list of strings" 54 raise NotImplementedError(
55 'The ros command >' + roscommand[0] +
'< is currently not supported.' 60 logging.debug(
"The config is:\n"+json.dumps(config, indent=2))
66 except rospkg.common.ResourceNotFound
as e:
69 logging.info(
'This is a system package to be installed from:\n> ' + self.
deb_package)
71 logging.info(
'Can not find package: ' + self.
rospackage)
75 if self.path.startswith(
'/opt/ros'):
77 logging.info(
'This is a system package to be installed from:\n> ' + self.
deb_package)
80 logging.info(
'This is a user package at:\n> ' + self.
path)
88 logging.info(
'Dockerfile given by user: ' + self.
dockerfile)
90 for fs
in os.walk(self.
path):
92 fname = fs[0] +
"/" + f
93 if re.match(
r".*Dockerfile.*", f):
95 logging.info(
'This package has a Dockerfile at:\n> ' + self.
dockerfile)
98 logging.info(
'This package does not have a Dockerfile')
101 logging.info(
'Using source Dockerfile:\n> ' + self.
dockerfile)
104 logging.info(
'Using default Dockerfile:\n> ' + self.
dockerfile)
107 if "registry" in config.keys():
112 assert not "__" in s,
"Double underscores lead to ambigous image names" 113 self.
name =
"__".join(self.
roscommand).replace(
'.',
'-').replace(
'~',
'-').replace(
'=',
'-')
115 logging.info(
"name: \n> " + self.
name)
116 logging.info(
"tag: \n> " + self.
tag)
123 Checking system dependencies required by ROS packages 125 out = subprocess.check_output(
133 if os.path.exists(dockerfile_fname):
134 if os.path.samefile(in_fname, dockerfile_fname):
135 logging.warning(
"Using Dockerfile without replacing (%s)"%dockerfile_fname)
138 with
open(in_fname,
'r') as in_file: 139 with open(dockerfile_fname, 'w+')
as out_file:
142 l = l.replace(
"#####DEB_PACKAGE#####", self.
deb_package)
143 l = l.replace(
"#####ROS_PACKAGE#####", self.
rospackage)
144 l = l.replace(
"#####CMD#####",
"[\""+
"\", \"".join(
152 with
open(dockerfile_fname,
'r') as dockerfile: 153 print "Dockerfile used: ############################################" 156 print "#############################################################" 161 logging_fun(
'| '+(l[
'stream'].strip()
if (
'stream' in l.keys())
else ''))
166 Compiles a baseDocker image with specific image of a rospackage 173 logging.info(
" path is " + path)
174 dockerfile_fname = self.
path +
"/Dockerfile" 175 logging.info(
" Dockerfile is at " + dockerfile_fname)
177 assert self.
deb_package,
"Debian package needs to be available" 179 dockerfile_fname =
'/tmp/tmp_Dockerfile' 183 logging.info(
"Please wait while the image is being built\n (This may take a while ...)")
184 with
open(dockerfile_fname,
'r') as dockerfile: 187 self.
image, it = self.docker_client.images.build(
190 custom_context=
False,
193 self.
logIt(logging.debug, it)
194 logging.info(
"Image was created. Tags are: " +
', '.join(self.image.tags))
195 except docker.errors.BuildError
as e:
197 self.
logIt(logging.error, it)
201 Run the Image on Host 203 logging.info(
"Starting:\n > " +
" ".join(self.
roscommand) +
" <")
204 self.docker_client.containers.run(
215 logging.info(
"Stopping:\n > " +
" ".join(self.
roscommand) +
" <")
217 cont = self.docker_client.containers.get(self.
name)
220 except Exception
as e:
224 logging.info(
"Removed:\n > " +
" ".join(self.
roscommand) +
" <")
225 except Exception
as e:
230 Push the image to a registry defined in the config 233 logging.error(
"Your config has no registry. Pushing makes no sense.")
235 stream = self.docker_client.images.push(self.
tag, stream=
True)
242 Initialize a docker client either using local or remote docker deamon. 243 When you give no parameters, the local enviornment is used. 244 So either your local deamon or the one defined in the DOCKER_HOST environment variable.(see https://dockr.ly/2zMPc17 for details) 245 (see https://dockr.ly/2zMPc17 for details) 247 ip: ip or host of the remote deamon (give None to use local environment) 248 port: port of the remote deamon 253 self.
docker_client=docker.client(
"tcp:/"+
":".join([ip.strip(), port.strip()]))
def replaceDockerfile(self, in_fname, dockerfile_fname)
def logIt(self, logging_fun, it)
def _get_allowed_roscommands()
def make_client(self, ip=None, port=None)
def __init__(self, roscommand, config, dockerfile=None)