0

I created a stand-alone application with Python3 that accepts a file as input, however I am not able to let it work properly. Once installed on my system I run the application as myapp -accounts ./accounts.yaml.

Now, I am trying to replicate this behaviour on a Docker container: I would like to do something like docker run --name myapp myapplatest -accounts ./accounts.yaml where the file accounts.yaml is stored in the local folder. However, I am still receiving this error:

Traceback (most recent call last):
  File "/usr/local/bin/myapp", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.7/dist-packages/myapp/main.py", line 17, in main
    with open(args.accounts, "r") as acc:
FileNotFoundError: [Errno 2] No such file or directory: '/usr/local/lib/python3.7/dist-packages/myapp/accounts.yaml'

Here it is the latest part of the Dockerfile I created for the app

RUN mkdir /home/myapp
WORKDIR /home/myapp
RUN apt install -y python3-pip 
COPY . .
RUN python3 -m pip install --upgrade pip
RUN python3 -m pip install -r requirements.txt
RUN python3 -m pip install .

ENTRYPOINT ["myapp"] CMD[""]

The cli.py used to catch the args is

def full_path(string: str):
    script_dir = os.path.dirname(__file__)
    return  os.path.normpath(os.path.join(script_dir, string))

def myapp_args(parser: argparse.ArgumentParser):
    parser.add_argument("-accounts", type=full_path, default="../accounts.yaml",
                        help="Specify the Yaml file containing the accounts information")
    return parser.parse_args()

The main.py just calls the parser

def main():
    parser = argparse.ArgumentParser()
    args = myapp_args(parser)
    with open(args.accounts, "r") as acc:
        accounts = yaml.safe_load(acc)

The setup.py contains the following line of code to install correctly the package

    include_package_data=True,
    entry_points={
        'console_scripts': [
            'myapp = myapp.main:main',
        ],
    },

I tried to run docker sharing a folder that contains the file accounts.yaml but with no success docker run --name myapp --mount type=bind,source="$(pwd)"/accounts.yaml,target=/home/myapp/accounts.yml myapp:latest -accounts ./accounts.yaml But I always have the same error. What could it be? I do not understand why it looks for the file in the /usr/lib... while I am calling the command in the WORKDIR.

EDIT

I think to have misexplained the question. I have no problems passing the file into the container. If I enter into it and list the files, the account.yaml is there, in the project root:

 docker run --name myapp -it --entrypoint sh --mount type=bind,source="$(pwd)"/accounts.yaml,target=/home/myapp/accounts.yaml myapp:latest
# ls
Dockerfile   README.md      myapp           myapp.png  requirements.txt  sonar-project.properties
MANIFEST.in accounts.yaml      setup.py
# exit

However, the error is the first one I posted in the questions: the program looks for the file in the /usr/local/lib... rather than the project root where it is invoked.

net_programmer
  • 360
  • 1
  • 2
  • 11
  • The problem is that you are passing the string parameter "../accounts.yaml" to the script in the container, not the actual file. Maybe this answer is useful for your case (if you want to avoid using docker cp): https://stackoverflow.com/a/60315076/7257731 – Samuel O.D. May 22 '23 at 11:53
  • A Docker container runs in an isolated filesystem and by design it can't normally access files on the host. Since most MacOS and LInux systems ship with Python preinstalled, you'll probably find this easier to run from a plain-Python virtual environment without involving Docker. – David Maze May 22 '23 at 13:03

0 Answers0