Search code examples
pythonpython-3.xdockerdocker-composeargparse

python argparse in a docker container based on ubuntu


I am struggling to find a way to pass arguments to a python script within a docker container based on ubuntu. I am working with docker-compose.yml.

Please find the example below!

docker-compose.yml

version: "3"
services:
   bcp:
      image: ubuntu:18.04
      restart: always
      tty: true
      entrypoint: ["/bin/bash", "/ingestion/bcp-entrypoint.sh"]
      volumes:
          - ./services/bcp:/ingestion/services/bcp
          - ./bcp-entrypoint.sh:/ingestion/bcp-entrypoint.sh

bcp-entrypoint.sh

apt-get update
apt-get upgrade -y
apt-get clean -y
apt-get install -y python3-pip
...

python script

required_args.add_argument("--database", metavar="str", type=str, help="database from where to extract", required=True)

The way I call the script - in container and on host machine - is python3 -m services.bcp --database foo and it works just perfect. The question is, how can I achieve the same from host machine on docker container?

Basically, I am looking for something like docker-compose exec services.bcp --database foo.

I do not want to use dockerfile! Ideally everything is based on docker-compose.


Solution

  • Here is a solution for both docker and docker compose of how to parse arguments within the docker container:

    python script

    #!/usr/bin/env python
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument("name", help="Name of person to greet")
    
    args = parser.parse_args()
    
    print(f"Hello there, {args.name}!")
    

    With a custom dockerfile (seems like the most straight-forward for this situation):

    FROM python:3.8
    
    COPY main.py .
    
    ENTRYPOINT ["./main.py"]
    

    Then build and run the containerized cli:

    # Should make the script executable to invoke directly
    $ chmod +x main.py
    
    $ docker build -t dockerized-cli .
    $ docker run -it --rm dockerized-cli -h
    usage: main.py [-h] name
    
    positional arguments:
      name        Name of person to greet
    
    optional arguments:
      -h, --help  show this help message and exit
    $ docker run -it --rm dockerized-cli Jeff
    Hello there, Jeff!
    

    With just docker-compose (Original question)

    version: "3"
    services:
      app:
        image: python:3.8
        volumes:
          - .:/opt/app
        entrypoint: ["/opt/app/main.py"]
    

    Then to run,

    $ docker-compose run app Jeff
    Hello there, Jeff!
    

    If you need to use the ubuntu:18.04 image and still can't build your own image off of it (to install python outside of the entrypoint), then you need to do what you already have which is create an entrypoint script wherein you first install python and then invoke your script. Something of note is that now your entrypoint is the entrypoint script itself and not your python CLI so you need to propogate any arguments from the shell script to your python script. Below is a simple example of how to do so - notice the bash variable "$@":

    entrypoint.sh

    #!/bin/bash
    
    # install python here...
    
    python print_args.py $@
    

    print_args.py

    import sys
    print(sys.argv)