Running Docker as Root in CommandLineTool

Hi, I am trying to run a Monte Carlo simulation in a workflow on a docker container. However, when the python script I am passing attempts to access a file on the container, it gives the message: PermissionError: [Errno 13] Permission denied: '/root/nndc_hdf5/cross_sections.xml' and fails.

I can run this python script on the same container launched from my local machine with no issues and believe it is due to the user privileges when running commands in Docker. When running directly through the container, using whoami gives the user as root. However, when running through the workflow, it gives the user ID as 1000.

Is there any way to launch the container through the commandlinetool as root user, enabling the python script to access this file?

commandlinetool:

#!/usr/bin/env cwl-runner
# A command line tool to run the basic openMC docker container

cwlVersion: v1.0
class: CommandLineTool
baseCommand: python
hints:
  DockerRequirement:
    dockerPull: openmc/openmc:develop-dagmc-libmesh
inputs:
  script:
    type: File
    inputBinding:
      position: 1
outputs:
  example_out:
    type: stdout
stdout: output.txt

.yml File

script:
  class: File
  path: ../OpenMC_Scripts/toy.py

and python script I am running

# From https://nbviewer.org/github/openmc-dev/openmc-notebooks/blob/main/pincell.ipynb
# An OpenMC python script that runs a toy problem example 


import openmc
import matplotlib.pyplot as plt # Extra to save plots produced in the process


####################
# DEFINING MATERIALS
####################

# Uranium Dioxide Fuel
uo2 = openmc.Material(name="uo2") # Create material variable with name uo2
uo2.add_nuclide('U235', 0.03)	# Add nuclides to material 
uo2.add_nuclide('U238', 0.97)
uo2.add_nuclide('O16', 2.0)
uo2.set_density('g/cm3', 10.0)	# Set density of material

# Zirchonium Casing
zirconium = openmc.Material(name="zirconium")
zirconium.add_element('Zr', 1.0) # Use of add element as elemental material
zirconium.set_density('g/cm3', 6.6)

# Water Coolant
water = openmc.Material(name="h2o") # Same process as uo2
water.add_nuclide('H1', 2.0)
water.add_nuclide('O16', 1.0)
water.set_density('g/cm3', 1.0)
water.add_s_alpha_beta('c_H_in_H2O') # So bound-atom cross section is used as thermal energies rather than free-atom


materials = openmc.Materials([uo2, zirconium, water]) # Add all materials to a group of materials

materials.export_to_xml() # Export the material data to a .xml file that the solver will use later on



####################
# DEFINING GEOMETRY
####################

# Set cylinders to define regions and then define regions from those cylinders
fuel_outer_radius = openmc.ZCylinder(r=0.39)
clad_inner_radius = openmc.ZCylinder(r=0.40)
clad_outer_radius = openmc.ZCylinder(r=0.46)
fuel_region = -fuel_outer_radius
gap_region = +fuel_outer_radius & -clad_inner_radius
clad_region = +clad_inner_radius & -clad_outer_radius

# Assign matreials and regions to cells
fuel = openmc.Cell(name='fuel')
fuel.fill = uo2
fuel.region = fuel_region

gap = openmc.Cell(name='air gap')
gap.region = gap_region

clad = openmc.Cell(name='clad')
clad.fill = zirconium
clad.region = clad_region

# Create a box around the cylinders and fill with water as coolant
pitch = 1.26
box = openmc.rectangular_prism(width=pitch, height=pitch, boundary_type='reflective')
water_region = box & +clad_outer_radius

moderator = openmc.Cell(name='moderator')
moderator.fill = water
moderator.region = water_region

# Add all cells to the overall universe and again push to .xml for use by the solver
root_universe = openmc.Universe(cells=(fuel, gap, clad, moderator))
geometry = openmc.Geometry(root_universe)
geometry.export_to_xml()



####################
# DEFINING SETTINGS
####################

# Create a point source
point = openmc.stats.Point((0, 0, 0))
source = openmc.Source(space=point)

# Set settings
settings = openmc.Settings()
settings.source = source
settings.batches = 100
settings.inactive = 10
settings.particles = 1000

# Push settings to .xml for solver
settings.export_to_xml()



####################
# DEFINING TALLIES
####################

cell_filter = openmc.CellFilter(fuel) # What space the tallies take place in

tally = openmc.Tally(1)
tally.filters = [cell_filter]

# Tell tally what to collect info on
tally.nuclides = ['U235']
tally.scores = ['total', 'fission', 'absorption', '(n,gamma)']

# Export to .xml for solver
tallies = openmc.Tallies([tally])
tallies.export_to_xml()


####################
# RUN
####################

openmc.run()

Thanks,
Will

Have you tried with the option --no-match-user in cwltool?

 --no-match-user       Disable passing the current uid to `docker run --user`
1 Like

Thanks for the quick answer! That seems to fix everything

If you can rebuild the container, I would recommend making the data files world readable within the container, it will be more portable if you want to run your CWL on a different runner in the future. Or, even better, pass the data files as inputs, then you both have more control over what data is being used, and the Docker container will be smaller.

3 Likes