Skip to content

Commit

Permalink
Add workingDir parameter to DockerApp
Browse files Browse the repository at this point in the history
Docker containers run by default under /. Additionally, when we ensure
and create a new user in the container, we run under /home/r ("r" is the
new user). Both of these options make it impossible to retrieve anything
from the working directory after execution finishes though, which is why
we need a new parameter that lets users specify under which directory
the container command will run (and thus they can also map it from the
host system).

This commit adds support for a new workingDir parameter in DockerApps.
Its value defaults to "/", and is only taken into account when the image
from which the container is started doesn't already contain a value for
its WorkingDir specification. We take care that this preference is
obeyed both when we internally create a new user, as well as when we
don't A new unit test checks that this is working as expected.

This work is part of LIU-53.

Signed-off-by: Rodrigo Tobar <rtobar@icrar.org>
  • Loading branch information
rtobar committed Apr 19, 2021
1 parent ea54ebb commit e8dbc6a
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
16 changes: 14 additions & 2 deletions daliuge-engine/dlg/apps/dockerapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ class DockerApp(BarrierAppDROP):
`initialize` time, meaning that the docker images will become available at
the time the physical graph (which this application is part of) is deployed.
Docker containers also need a command to be run in them, which should be
an available program inside the image.
an available program inside the image. Optionally, users can provide a
working directory (in the container) under which the command will run
via the `workingDir` parameter.
**Input and output**
Expand Down Expand Up @@ -247,6 +249,15 @@ def initialize(self, **kwargs):
logger.debug("Took %.2f [s] to pull image '%s'", (end-start), self._image)
else:
logger.debug("Image '%s' found, no need to pull it", self._image)

# Check if the image specifies a working directory
# If it doesn't use the one provided by the user
inspection = c.api.inspect_image(self._image)
logger.debug("Docker Image inspection: %r", inspection)
self.workdir = inspection.get('ContainerConfig', {}).get('WorkingDir', None)
if not self.workdir:
self.workdir = self._getArg(kwargs, 'workingDir', '/')

c.api.close()

self._containerIp = None
Expand Down Expand Up @@ -327,7 +338,7 @@ def run(self):
createUserAndGo = "id -u {0} &> /dev/null || adduser --uid {0} r; ".format(uid)
for dirname in set([os.path.dirname(x.path) for x in dockerOutputs.values()]):
createUserAndGo += 'chown -R {0}.{0} "{1}"; '.format(uid, dirname)
createUserAndGo += "cd; su -l $(getent passwd {0} | cut -f1 -d:) -c /bin/bash -c '{1}'".format(uid, utils.escapeQuotes(cmd, doubleQuotes=False))
createUserAndGo += "su -l $(getent passwd {0} | cut -f1 -d:) -c /bin/bash -c 'cd {1}; {2}'".format(uid, self.workdir, utils.escapeQuotes(cmd, doubleQuotes=False))

cmd = createUserAndGo

Expand All @@ -351,6 +362,7 @@ def rm(container):
volumes=binds,
user=user,
environment=env,
working_dir=self.workdir
)
self._containerId = cId = container.id
logger.info("Created container %s for %r", cId, self)
Expand Down
12 changes: 12 additions & 0 deletions daliuge-engine/test/apps/test_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,15 @@ def test_additional_bindings(self):
# Cleanup
os.unlink(tempFile)
shutil.rmtree(tempDir)

def _test_working_dir(self, ensureUserAndSwitch):
a = DockerApp('a', 'a', workingDir='/mydir', image='ubuntu:14.04', command='pwd > %o0', ensureUserAndSwitch=ensureUserAndSwitch)
b = FileDROP('b', 'b')
a.addOutput(b)
with DROPWaiterCtx(self, b, 100):
a.execute()
self.assertEqual(b'/mydir', droputils.allDropContents(b).strip())

def test_working_dir(self):
self._test_working_dir(True)
self._test_working_dir(False)

0 comments on commit e8dbc6a

Please sign in to comment.