Container Service 3.x / XNAT 1.10 - Container mounts empty folders (Path Translation issue? (Docker-compose setup))

96 views
Skip to first unread message

Pasquale

unread,
May 18, 2026, 5:31:51 PMMay 18
to xnat_discussion

Hi everyone,

I'm having a critical issue configuring the Container Service on a fresh XNAT 1.10 instance running inside a Docker-compose environment. Whenever a container is launched from an Image Scan context, the container runs successfully but the mounted folder inside the container is completely empty (total 0).

Looking at the Container Report in XNAT, the path translation between XNAT and the host is not happening at all. Both xnat-host-path and container-host-path are resolving to the exact same internal XNAT container path, instead of being translated to the physical host path and they are also wrong.

From the Container Report:

  • xnat-host-path: /data/xnat/archive/test/arc001/0/SCANS/1/DICOM

  • container-host-path: /data/xnat/archive/test/arc001/0/SCANS/1/DICOMPasted image.png

 while the real files are  /mnt/disk1/data/xnat/archive/test/arc001/Patient_43_CT_1/SCANS/4/secondary

Host permissions on /mnt/disk1/data/xnat have already been opened up to 777 to rule out permission issues).

Container Service Settings configured via UI:
  • XNAT Path Prefix: /data/xnat

  • Server Path Prefix: /mnt/disk1/data/xnat

the test   json i have used is

{
  "name": "gctd",
  "label": "GCTD",
  "description": "Run GCTD on DICOM resource from XNAT",
  "version": "1.0",
  "schema-version": "1.0",
  "image": "gctd:latest",
  "type": "docker",
  "command-line": "bash -c 'echo === CONTROLLO FILE === && ls -la /input/secondary && echo === CONTEGGIO FILE === && find /input/secondary -type f | wc -l && sleep 30'",
  "mounts": [
    {
      "name": "dicom-in",
      "writable": false,
      "path": "/input/secondary"
    }
  ],
  "environment-variables": {},
  "ports": {},
  "inputs": [],
  "outputs": [],
  "xnat": [
    {
      "name": "gctd-scan-wrapper",
      "label": "GCTD on Scan",
      "description": "Run GCTD on a Scan's secondary resource",
      "contexts": [
        "xnat:imageScanData"
      ],
      "external-inputs": [
        {
          "name": "scan",
          "label": "Scan",
          "description": "The XNAT Scan",
          "type": "Scan",
          "required": true,
          "load-children": true
        }
      ],
      "derived-inputs": [
        {
          "name": "dicom-files",
          "label": "Secondary Files",
          "type": "Resource",
          "matcher": "@.label == 'secondary'",
          "required": true,
          "provides-files-for-command-mount": "dicom-in",
          "load-children": true,
          "derived-from-wrapper-input": "scan",
          "derived-from-xnat-object-property": "resources",
          "multiple": false
        }
      ],
      "output-handlers": []
    }
  ],
  "container-labels": {},
  "generic-resources": {},
  "ulimits": {},
  "secrets": [],
  "visibility": "public"
}

but all i get is  from stdout
=== INPUT ROOT ===
total 0
drwxr-xr-x. 2 root root 6 May 15 12:58 .
drwxr-xr-x. 1 root root 19 May 15 12:58 ..
=== RECURSIVE ===
/input
=== SECONDARY ===
=== DEEP SECONDARY FILES === and from stderr.log
ls: cannot access '/input/secondary': No such file or directory why it doesn't find the files?

Thanks in advance for any help!


Timothy Olsen

unread,
May 18, 2026, 6:59:20 PM (14 days ago) May 18
to xnat_di...@googlegroups.com
We gave a team member trying to reproduce this now.  Give us some time to have a look.

Tim

Timothy R Olsen 

Founder, President



--
You received this message because you are subscribed to the Google Groups "xnat_discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to xnat_discussi...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/xnat_discussion/b9030770-62b8-470e-918a-de577c5c048fn%40googlegroups.com.

Bin Zhang

unread,
May 18, 2026, 7:41:05 PM (14 days ago) May 18
to xnat_di...@googlegroups.com
Hi Pasquale,

You can try this:

The Server Path Prefix must be the absolute path on the Docker host, not inside any container.

  With the default xnat-docker-compose, the archive lives on the host at:
  <your-checkout-of-xnat-docker-compose>/xnat-data/archive
  and that directory is bind-mounted into the xnat-web container as /data/xnat/archive. So the prefixes should be:

  - XNAT Path Prefix: /data/xnat
  - Server Path Prefix: /path/to/xnat-docker-compose/xnat-data   ← note: ends in xnat-data, not xnat

  Quick way to confirm: after re-launching, run docker inspect <container-id> --format '{{json .Mounts}}' — Source should be an absolute host path that actually
   exists. Separately, the arc001/0/SCANS/1 in your report looks suspicious (the 0/1 aren't matching your real session label Patient_43_CT_1 and scan 4); worth
  double-checking that the scan you're launching the command against is the one whose data you expect.
 

  Bin



--

Bin Zhang 

Software Engineer
Consulting, Support ,and XNAT Development
"Making XNAT Work for you!"

Bin Zhang

unread,
May 18, 2026, 8:12:42 PM (14 days ago) May 18
to xnat_di...@googlegroups.com
  Hi Pasquale,
 
  Quick follow-up on my previous reply — My local reproduction was using the stock xnat-docker-compose setup, where the archive lives on the
  host at <compose-dir>/xnat-data/archive. My "use xnat-data" suggestion doesn't apply here.

Sorry for the confusion.

Bin

Bin Zhang

unread,
May 18, 2026, 10:10:44 PM (14 days ago) May 18
to xnat_di...@googlegroups.com
Hi Pasquale,
 
  To narrow this down, I'd like to walk through a clean test scenario step by step. Could you share the following?

  1. Your docker-compose volumes

 Example:
  volumes:
    - /mnt/disk1/data/xnat:/data/xnat
  or whatever your actual mapping is.

  2. List of installed plugins and versions.
 
  3. Create a clean test project. In the UI, create a new project called something like cstest.

     
  4. Using the UI's Compressed Uploader to upload your test data.  Note down:
  - The session label XNAT assigned it
  - The scan ID
  - The resource label(s) — probably just DICOM

  5. Verify the archive layout on disk
  find /mnt/disk1/data/xnat/archive/cstest -type d

  6. Run your container command against the clean scan and send us the result (container-report, etc.).
 
  Thanks,
  Bin

Pasquale

unread,
May 19, 2026, 9:26:17 AM (13 days ago) May 19
to xnat_discussion
weird, i thought i had answered but the message doesn't appear.
anyway
1)the mount points are 
      - /mnt/disk1/data/xnat/archive:${XNAT_ROOT}/archive
      - /mnt/disk1/data/xnat/build:${XNAT_ROOT}/build
      - /mnt/disk1/data/xnat/cache:${XNAT_ROOT}/cache

2)the plugins installed are just 
container-service-3.8.0-fat.jar  ohif-viewer-3.7.2.jar

3)the xml of the scans says
<xnat:experiments>
<xnat:experiment ID="XNAT_E00008" project="cstest_id" label="Patient_43_CT_1" session_type="cstest_id" modality="CT" UID="1.3.6.1.4.1.9590.100.1.2.353403882610824775603148430584220749936" study_id="1" xsi:type="xnat:ctSessionData">
<xnat:date>2021-01-28</xnat:date>
<xnat:time>15:15:15</xnat:time>
<xnat:subject_ID>XNAT_S00008</xnat:subject_ID>
<xnat:prearchivePath>
/data/xnat/prearchive/cstest_id/20260519_101528492/Patient_43_CT_1
</xnat:prearchivePath>
<xnat:scans>
<xnat:scan ID="4" type="unknown" UID="1.3.6.1.4.1.9590.100.1.2.331396631611887636527774122321664610373" project="cstest_id" xsi:type="xnat:scScanData">
<xnat:image_session_ID>XNAT_E00008</xnat:image_session_ID>
<xnat:quality>usable</xnat:quality>
<xnat:modality>CT</xnat:modality>
<xnat:frames>0</xnat:frames>
<xnat:file label="secondary" file_count="463" file_size="243280338" URI="/data/xnat/archive/cstest_id/arc001/Patient_43_CT_1/SCANS/4/secondary/scan_4_secondary_catalog.xml" format="DICOM" content="secondary" xsi:type="xnat:resourceCatalog"/>
</xnat:scan>
</xnat:scans>
<xnat:dcmPatientId>Patient_43_CT_1</xnat:dcmPatientId>
<xnat:dcmPatientName>Patient_43</xnat:dcmPatientName>
</xnat:experiment>
</xnat:experiments>
</xnat:Subject>
 

4)the folder created by xnat is  /mnt/disk1/data/xnat/archive/cstest_id
drwxr-x---.  3 root root   20 May 19 10:08 cstest_id

5)stdout.log says 

=== INPUT ROOT ===
total 0
drwxr-xr-x. 2 root root 6 May 15 12:58 .
drwxr-xr-x. 1 root root 19 May 15 12:58 ..
=== RECURSIVE ===
/input
=== SECONDARY ===
=== DEEP SECONDARY FILES ===
6)stderr.log says
ls: cannot access '/input/secondary': No such file or directory

the report says
Screenshot From 2026-05-19 13-19-10.png
Screenshot From 2026-05-19 13-21-25.png

Bin Zhang

unread,
May 19, 2026, 10:06:47 AM (13 days ago) May 19
to xnat_di...@googlegroups.com
  Hi Pasquale,
 
  Just a few quick things to clarify:

  1. The container report in the screenshots is from May 15 on project test (container id 24, workflow 74) — that's before you created cstest_id. We need the
  container report from the new cstest_id test run, not the old one. Could you grab that one?

  2. A couple of architecture questions:
  - Is XNAT (xnat-web) and the docker daemon that runs the sibling containers on the same physical machine (https://xnat2.epic.test) ?
  - Is /mnt/disk1 a local disk on that machine, or a mount from elsewhere (NFS, etc.)?
 
  3. Beyond the volumes changes, did you modify anything else in the stock docker-compose.yml? Any tweaks to networks, environment, the docker.sock line,
  ports, or the Dockerfile would help us match your setup.

  4. The most important one — could you paste the raw JSON of:
  curl -u admin:pass https://xnat2.epic.test/xapi/docker/server | jq .
  The full response, not a screenshot of the UI form. We specifically need the exact stored values for path-translation-xnat-prefix,
  path-translation-docker-prefix, and host.

  5. And on the docker host, for the container generated by the cstest_id test run:

  docker inspect <container-id> --format '{{json .Mounts}}'
  This shows what the docker daemon actually got asked to mount (Source path), independent of what CS reports.

  That should give us enough to give a definitive answer. Thanks!

  Cheers,
  Bin

Moore, Charlie

unread,
May 19, 2026, 10:36:43 AM (13 days ago) May 19
to xnat_di...@googlegroups.com
Also, how is the input being set? The screenshots show an input for scan of "/archive/experiments/XNAT_E00002/scans/1" while your XML had a session with an ID of XNAT_E00008 and a scan 4.

Thanks,
Charlie

From: xnat_di...@googlegroups.com <xnat_di...@googlegroups.com> on behalf of Bin Zhang <b...@xnatworks.io>
Sent: Tuesday, May 19, 2026 9:06 AM
To: xnat_di...@googlegroups.com <xnat_di...@googlegroups.com>
Subject: Re: [XNAT Discussion] Container Service 3.x / XNAT 1.10 - Container mounts empty folders (Path Translation issue? (Docker-compose setup))
 

 


The materials in this message are private and may contain Protected Healthcare Information or other information of a sensitive nature. If you are not the intended recipient, be advised that any unauthorized use, disclosure, copying or the taking of any action in reliance on the contents of this information is strictly prohibited. If you have received this email in error, please immediately notify the sender via telephone or return mail.

Pasquale

unread,
May 19, 2026, 12:21:38 PM (13 days ago) May 19
to xnat_discussion
oh right. i didn't realize the date was different, i mixed the screenshots. 
the error i get now is a simple line at the top that says 

Processing Exception


gctd-scan-wrapper:

Failed (Command resolution)


Start Time: 2026-05-19 15:22:21.408

[Dismiss]

2) yes same machine
2.1) it's a ordinary directory 


3)
services:

  xnat-web:
    container_name: xnat-web
    build:
      context: ./xnat
      args:
        XNAT_VERSION: ${XNAT_VERSION}
        XNAT_SMTP_ENABLED: ${XNAT_SMTP_ENABLED}
        XNAT_SMTP_HOSTNAME: ${XNAT_SMTP_HOSTNAME}
        XNAT_SMTP_PORT: ${XNAT_SMTP_PORT}
        XNAT_SMTP_AUTH: ${XNAT_SMTP_AUTH}
        XNAT_SMTP_USERNAME: ${XNAT_SMTP_USERNAME}
        XNAT_SMTP_PASSWORD: ${XNAT_SMTP_PASSWORD}
        XNAT_SMTP_START_TLS: ${XNAT_SMTP_START_TLS}
        XNAT_DATASOURCE_DRIVER: ${XNAT_DATASOURCE_DRIVER}
        XNAT_DATASOURCE_URL: ${XNAT_DATASOURCE_URL}
        XNAT_DATASOURCE_USERNAME: ${XNAT_DATASOURCE_USERNAME}
        XNAT_DATASOURCE_PASSWORD: ${XNAT_DATASOURCE_PASSWORD}
        TOMCAT_XNAT_FOLDER: ${TOMCAT_XNAT_FOLDER}
        XNAT_ROOT: ${XNAT_ROOT}
        XNAT_HOME: ${XNAT_HOME}
        XNAT_EMAIL: ${XNAT_EMAIL}
    ports:
      - 8080:8080
      - 8443:8443
    networks:
      - xnat-network
    volumes:
      - ./xnat/plugins:${XNAT_HOME}/plugins
      - ./xnat-data/home/logs:${XNAT_HOME}/logs

      - /mnt/disk1/data/xnat/archive:${XNAT_ROOT}/archive
      - /mnt/disk1/data/xnat/build:${XNAT_ROOT}/build
      - /mnt/disk1/data/xnat/cache:${XNAT_ROOT}/cache
      - ./xnat/xnat-conf.properties:${XNAT_HOME}/conf/xnat-conf.properties
      - ./xnat/server.xml:/usr/local/tomcat/conf/server.xml
      - ./xnat-data/home/config/auth:${XNAT_HOME}/config/auth # keycloack (not active right now)
      - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      - xnat-db
    environment:
      - CATALINA_OPTS=-Xms${XNAT_MIN_HEAP} -Xmx${XNAT_MAX_HEAP} -Dxnat.home=${XNAT_HOME}
      - XNAT_HOME=${XNAT_HOME}
      - XNAT_SITE_URL=${XNAT_SITE_URL}
      - XNAT_USE_FORWARD_HEADERS=${XNAT_USE_FORWARD_HEADERS}
      - XNAT_PORT=443


  xnat-db:
    container_name: xnat-db
    image: postgres:${PG_VERSION}
    expose:
      - 5432
    networks:
      - xnat-network
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
      #
      - ./postgres/XNAT.sql:/docker-entrypoint-initdb.d/XNAT.sql
    environment:
      - POSTGRES_PASSWORD=${XNAT_DATASOURCE_ADMIN_PASSWORD}
      - POSTGRES_DB=${XNAT_DATASOURCE_NAME}
      # variables for the sql script
      - XNAT_DATASOURCE_USERNAME=${XNAT_DATASOURCE_USERNAME}
      - XNAT_DATASOURCE_PASSWORD=${XNAT_DATASOURCE_PASSWORD}

  xnat-nginx:
    container_name: xnat-nginx
    image: nginx:${NGINX_VERSION}
    volumes:
      - ../certs:/etc/nginx/ssl:ro
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
    ports:
      - 80:80
      - 443:443
    networks:
      - xnat-network
    depends_on:
      - xnat-web
    links:
      - xnat-web

networks:
  xnat-network:
    name: xnat-network


4)
{
  "id": 2,
  "name": "Local socket",
  "host": "unix:///var/run/docker.sock",
  "cert-path": "",
  "backend": "docker",
  "path-translation-xnat-prefix": "/data/xnat",
  "path-translation-docker-prefix": "/mnt/disk1/data/xnat",
  "pull-images-on-xnat-init": false,
  "container-user": "",
  "auto-cleanup": true,
  "swarm-constraints": [],
  "status-email-enabled": true,
  "gpu-vendor": "",
  "archive-pvc-name": "",
  "build-pvc-name": "",
  "combined-pvc-name": "",
  "archive-path-translation": "",
  "build-path-translation": "",
  "combined-path-translation": "",
  "kubernetes-tolerations": [],
  "ping": true,
  "swarm-mode": false
}

Bin Zhang

unread,
May 19, 2026, 2:49:02 PM (13 days ago) May 19
to xnat_di...@googlegroups.com
  Hi Pasquale,

  A few quick checks:

  1. About the "Processing Exception", is there anything in the log? Could you paste the contents of:
  /data/xnat/home/logs/containers-services-commandresolution.log
  around the failure time (2026-05-19 15:22:21) — the raw text, not a screenshot. The stacktrace will tell us which step of the resolution failed.
 
  2. Are you still running the exact gctd-scan-wrapper JSON you posted in your first email (matcher @.label == 'secondary', mount path /input/secondary), or has
   it been edited since? To be certain:
  curl -u admin:pass "https://xnat2.epic.test/xapi/commands" | jq '.[] | select(.xnat[]?.name == "gctd-scan-wrapper")'

  3. Looking at everything you've shared, I don't see anything wrong with the configuration — docker server path translation, volumes, the wrapper definition,
  the uploaded data all look correct. One minor note: your compose doesn't bind-mount prearchive to the host, so anything still in prearchive will be lost on
  container restart — not related to the current failure, but worth knowing.

  Thanks,
  Bin

Pasquale

unread,
May 20, 2026, 8:07:17 AM (12 days ago) May 20
to xnat_discussion
2026-05-19 15:22:20,241 [http-nio-8080-exec-86] ERROR org.nrg.containers.services.impl.CommandResolutionServiceImpl - Error searching through json with search string "$.resources"
com.jayway.jsonpath.PathNotFoundException: No results for path: $['resources']
2026-05-19 15:22:21,559 [stagingQueueListener-2413] ERROR org.nrg.containers.services.impl.CommandResolutionServiceImpl - Error searching through json with search string "$.resources"
com.jayway.jsonpath.PathNotFoundException: No results for path: $['resources']
2026-05-19 15:22:21,559 [stagingQueueListener-2413] ERROR org.nrg.containers.services.impl.CommandResolutionServiceImpl - Could not resolve command
org.nrg.containers.exceptions.CommandResolutionException: Missing values for required input: dicom-files.
at org.nrg.containers.services.impl.CommandResolutionServiceImpl$CommandResolutionHelper.resolve(CommandResolutionServiceImpl.java:451)
at org.nrg.containers.services.impl.CommandResolutionServiceImpl$CommandResolutionHelper.access$200(CommandResolutionServiceImpl.java:274)
at org.nrg.containers.services.impl.CommandResolutionServiceImpl.resolve(CommandResolutionServiceImpl.java:266)
at org.nrg.containers.services.impl.ContainerServiceImpl.consumeResolveCommandAndLaunchContainer(ContainerServiceImpl.java:594)
at org.nrg.containers.jms.listeners.ContainerStagingRequestListener.onRequest(ContainerStagingRequestListener.java:51)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:169)
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:119)
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:110)
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:84)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:331)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:270)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1237)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1127)
at java.base/java.lang.Thread.run(Thread.java:1583)
2026-05-19 16:21:19,631 [http-nio-8080-exec-97] ERROR org.nrg.containers.services.impl.CommandResolutionServiceImpl - Error searching through json with search string "$.resources"
com.jayway.jsonpath.PathNotFoundException: No results for path: $['resources']

the json is the same 
{
  "id": 1,

  "name": "gctd",
  "label": "GCTD",
  "description": "Run GCTD on DICOM resource from XNAT",
  "version": "1.0",
  "schema-version": "1.0",
  "image": "gctd:latest",
  "type": "docker",
  "command-line": "bash -c 'echo === CONTROLLO FILE === && ls -la /input/secondary && echo === CONTEGGIO FILE === && find /input/secondary -type f | wc -l && sleep 30'",
  "mounts": [
    {
      "name": "dicom-in",
      "writable": false,
      "path": "/input/secondary"
    }
  ],
  "environment-variables": {},
  "ports": {},
  "inputs": [],
  "outputs": [],
  "xnat": [
    {
      "id": 24,

Bin Zhang

unread,
May 20, 2026, 10:48:08 AM (12 days ago) May 20
to xnat_di...@googlegroups.com
Could you delete this line  "derived-from-xnat-object-property": "resources", and give it a try?

  
   {
     "name": "dicom-files",

     "type": "Resource",
     "matcher": "@.label == 'secondary'",
  -  "derived-from-xnat-object-property": "resources",
     "provides-files-for-command-mount": "dicom-in",
     ...
   }

Pasquale

unread,
May 20, 2026, 11:46:43 AM (12 days ago) May 20
to xnat_discussion
the container failed. i got stderr.log ls: cannot open directory '/input/secondary': Permission denied probably because the project folder is created automatically with root? drwxr-x---.  3 root root   20 May 19 10:08 cstest_id

is there a way to obtain a json of the report so that i can copy and paste it?
 the container history ends with 

175

Finalizing

system

undefined

2026-05-20T15:31:04.286+0000

2026-05-20T15:31:04.286+0000

undefined

Processing finished. Uploading files.

176

Failed

system

undefined

2026-05-20T15:31:04.371+0000

2026-05-20T15:31:04.371+0000

2

Non-zero exit code and/or failure status from container

Bin Zhang

unread,
May 20, 2026, 12:13:03 PM (12 days ago) May 20
to xnat_di...@googlegroups.com
  Hi Pasquale,
 
  Good progress — your CS resolution and mount are now working correctly. The remaining error is purely a host-side filesystem permission issue, unrelated to
  XNAT or the Container Service.

  Your ls output shows:

 
  drwxr-x---.  3 root root   20 May 19 10:08 cstest_id

  The archive directories are mode 750 and owned by root:root, so the user inside your gctd container (which presumably isn't root, or isn't in the root group)
  gets Permission denied on the bind-mounted /input/secondary.

  As a quick test, manually chmod the relevant directories and files so non-root users can read/traverse them, including all parent directories up the chain.
  For example:

  # As root on the XNAT host
  sudo chmod -R o+rX /mnt/disk1/data/xnat/archive/cstest_id

  # And make sure every parent dir is at least o+x (traversable)
  sudo chmod o+x /mnt/disk1/data/xnat /mnt/disk1/data/xnat/archive

  You can try the ls command with other users(non-root), and it should work.

  Then re-launch the container and confirm ls -la /input/secondary works from inside. That isolates the issue to permissions and confirms nothing else is wrong
  with the wrapper or path translation.

  Once that's confirmed, the long-term fix is at the process that creates those archive directories with mode 750 — most likely the umask of the Tomcat/XNAT
  service (RHEL-family systemd defaults to UMask=0027, which yields exactly 750 for new directories). Setting UMask=0022 on the service (or adding umask 0022 to
   whatever script starts Tomcat) should make future directories 755 by default. But please verify with the chmod test first.
 
  Best,
  Bin

Pasquale

unread,
May 20, 2026, 12:56:08 PM (12 days ago) May 20
to xnat_discussion
yes they finally appear. thank you! 
"=== CONTROLLO FILE ===
total 239132
drwxr-xr-x. 2 root root 49152 May 19 10:15 .
drwxr-xr-x. 3 root root 23 May 20 16:37 ..
-rw-r--r--. 1 root root 525442 May 19 10:15 1.3.6.1.4.1.9590.100.1.2.353403882610824775603148430584220749936-4-1-dojtfq.dcm
-rw-r--r--. 1 root root 525442 May 19 10:15 1.3.6.1.4.1.9590.100.1.2.353403882610824775603148430584220749936-4-10-1to4z43.dcm
-rw-r--r--. 1 root root 525444 May 19 10:15 1.3.6.1.4.1.9590.100.1.2.353403882610824775603148430584220749936-4-100-p4azr6.dcm
-rw-r--r--. 1 root root 525444 May 19 10:15 1.3.6.1.4.1.9590.100.1.2.353403882610824775603148430584220749936-4-101-1elprw4.dcm
-rw-r--r--. 1 root root 525444 May 19 10:15 1.3.6.1.4.1.9590.100.1.2.353403882610824775603148430584220749936-4-102-19wz4cf.dcm " etc

now the issue is just setting the umask in the docker-compose.yml?

Pasquale

unread,
May 20, 2026, 1:35:06 PM (12 days ago) May 20
to xnat_discussion

I checked the actual runtime environment inside the Docker container.

The Tomcat/XNAT Java process  is running with umask 0022, not 0027.

Manual directory creation inside the mounted XNAT paths produces 755 as expected:

mkdir /data/xnat/home/umask-test ls -ld /data/xnat/home/umask-test drwxr-xr-x

However, the archive directories created by XNAT are still being created as 750.

Bin Zhang

unread,
May 20, 2026, 2:29:07 PM (12 days ago) May 20
to xnat_di...@googlegroups.com
  Hi Pasquale,
 
  This is clearly a Linux system configuration issue, not an XNAT one — XNAT's code doesn't set directory permissions explicitly anywhere, so the 750 has to be
  coming from your host's filesystem layer.

  My main suspicion is /mnt/disk1 itself. Could you try two quick tests?

  1. Create a directory directly under /mnt/disk1 and see what mode it gets:
 
  # On the host
  mkdir /mnt/disk1/perm-test
  ls -ld /mnt/disk1/perm-test
  rm -rf /mnt/disk1/perm-test

  # Then the same from inside the XNAT container
  docker compose exec xnat-web mkdir /data/xnat/archive/perm-test
  docker compose exec xnat-web ls -ld /data/xnat/archive/perm-test
  docker compose exec xnat-web rm -rf /data/xnat/archive/perm-test

  If those come out as 750, then /mnt/disk1 is forcing it (via mount options, default ACL, or filesystem type) — independent of XNAT or umask.

  2. As a clean isolation test, change your docker-compose volume mapping so the archive lives under /data/... on the host instead of /mnt/disk1/..., and see if
   new archive directories created via XNAT come out 755 there.

  I don't have a native Linux host available to reproduce this.
  Best,
  Bin

Pasquale

unread,
May 21, 2026, 4:10:54 PM (11 days ago) May 21
to xnat_discussion
you were absolutely right. now it works. it was a permission issue . thanks
Reply all
Reply to author
Forward
0 new messages