How to log persistent from a application running in docker

Hi,

we are running a C++ application on a verdin board in a docker container
and I currently try to implement the logging feature for the c++ application.

I have the following docker-compose

version: "3.9"
services:
  servicename-debug:
    build:
      context: .
      dockerfile: Dockerfile.debug
    volumes:
      - type: bind
        source: ./logs
        target: /tmp/logs
    image: ${LOCAL_REGISTRY}:5002/servicename-debug:${TAG}
    privileged: true
    ports:
      - 6502:6502

I assumed that, this should create a folder inside the docker container called /tmp/logs which is mapped to the TorizonCore folder ./logs.
So, the logs should persist a restart.

But the problem is fopen_s() always returns error 13 (permission denied)! (mode=“a”, Creates the file if it doesn’t exist.)
image

So I assume the docker container does not have the rights to create a file in a TorizonCore folder.
How can this be fixed?

The user permissions for the tmp folder on TorizonCore are drwxrwxrwt
image

The user permissions in the docker container:

The Hard/Software is:

Software summary
------------------------------------------------------------
Bootloader:               U-Boot
Kernel version:           5.15.129-6.4.0+git.67c3153d20ff #1-TorizonCore SMP PREEMPT Wed Sep 27 12:30:36 UTC 2023
Kernel command line:      root=LABEL=otaroot rootfstype=ext4 quiet logo.nologo vt.global_cursor_default=0 plymouth.ignore-serial-consoles splash fbcon=map:3 ostree=/ostree/boot.1/torizon/460c0c1dde52ce6a4fd14e6ff7399ad1c879175a9ffa047acbb97523d9376591/0
Distro name:              NAME="TorizonCore"
Distro version:           VERSION_ID=6.4.0-build.5
Hostname:                 verdin-imx8mp-xxxxxxxx
------------------------------------------------------------

Hardware info
------------------------------------------------------------
HW model:                 Toradex Verdin iMX8M Plus WB on Verdin Development Board
Toradex version:          0058 V1.0D
Serial number:            xxxxxxxx
Processor arch:           aarch64
------------------------------------------------------------

To reproduce the problem just create a python project in vscode with the following main.py

#!python3

def run():
    file_path = "/tmp/new_file.txt"
    # Open the file in append mode
    try:
        with open(file_path, 'a+') as file:
            file.seek(0)
            num_lines = len(file.readlines())
            # Write content to the file
            file.write("The application started the {} time.\n".format(num_lines + 1))
            print(f"File '{file_path}' created successfully and text added.")
    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    run()

Debug python local → everything works
Debug Torizon ARMv8 → error 13 (Permission denied)
To the docker-compose.yml I just added
image

How can this be fixed ???
I think it is currently not possible to save persistent data on the host if using the docker environment.

Hi, I’m the Toradex AI Assistant. The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


To address the issue of fopen_s() returning error 13 (permission denied) when trying to create a file in a bind-mounted directory inside a Docker container on TorizonCore, you need to ensure that the user inside the container has the appropriate permissions to write to the bind-mounted directory.

Here are a few steps to troubleshoot and resolve this issue:

  1. Check Directory Permissions on Host:
    Ensure that the ./logs directory on the host (TorizonCore) has the correct permissions to allow writing by the user inside the container.

    sudo chmod -R 777 ./logs
    

    This command will give read, write, and execute permissions to all users for the ./logs directory. Adjust the permissions as needed for your security requirements.

  2. Ensure User Permissions Inside Container:
    By default, the torizon user inside the container should have the necessary permissions. However, if your application is running as a different user, you need to ensure that this user has the appropriate permissions.

    You can add the torizon user to the necessary groups or run the container as the torizon user. Here’s how you can modify your docker-compose.yml to run the container as the torizon user:

    version: "3.9"
    services:
      servicename-debug:
        build:
          context: .
          dockerfile: Dockerfile.debug
        volumes:
          - type: bind
            source: ./logs
            target: /tmp/logs
        image: ${LOCAL_REGISTRY}:5002/servicename-debug:${TAG}
        user: torizon
        privileged: true
        ports:
          - 6502:6502
    
  3. Verify UID/GID Consistency:
    Ensure that the UID and GID of the user inside the container match those on the host. This can help avoid permission issues. You can check the UID and GID of the torizon user inside the container and ensure they match the owner of the ./logs directory on the host.

    id torizon
    

    If needed, you can change the ownership of the ./logs directory on the host to match the UID and GID of the torizon user.

    sudo chown -R <UID>:<GID> ./logs
    
  4. Debugging Permissions:
    If the above steps do not resolve the issue, you can debug the permissions by running an interactive shell inside the container and checking the permissions directly.

    docker exec -it <container_id> /bin/bash
    ls -l /tmp/logs
    touch /tmp/logs/testfile
    

    This will help you identify if there are any permission issues directly inside the container.

By following these steps, you should be able to resolve the permission denied issue and ensure that your C++ application can log persistently to the bind-mounted directory.

Please, also check if these links can help you solve your problem:

JSON File logging driver | Docker Docs.

Greetings @dan,

Using your code exactly as provided the following docker-compose file worked for me:

version: "3.9"
services:
  test-debug:
    build:
      context: .
      dockerfile: Dockerfile.debug
    image: ${LOCAL_REGISTRY}:5002/test-debug:${TAG}
    volumes:
      - type: bind
        source: /home/torizon/tmp
        target: /tmp
    ports:
      - ${DEBUG_SSH_PORT}:${DEBUG_SSH_PORT}
      - ${DEBUG_PORT1}:${DEBUG_PORT1}

With this the code runs in VSCode debug without any errors. After the code exits I can see the new file created via the volume bind-mount on my device:

torizon@verdin-imx8mp-06849059:~$ cat tmp/new_file.txt
The application started the 1 time.

Perhaps in your case the issue was using a relative file-path with ./. Sometimes relative paths don’t have the expected effect with containers and volumes.

Best Regards,
Jeremias

You’re correct,

this works:

    - type: bind
      source: /tmp
      target: /tmp

Glad we were able to help out here.