Prageeth
Prageeth

Reputation: 249

Need to run docker run command inside python script

My Docker Command is:

docker run --rm wappalyzer/cli https://wappalyzer.com

When I run my python script:

#!/usr/bin/python
from subprocess import call
import json
import os
import docker

docker run --rm wappalyzer/cli "MYURL"

it says

File "t.py", line 7
    docker run --rm wappalyzer/cli "MYURL"
             ^
SyntaxError: invalid syntax

My os is ubuntu 14.04 and I am using ubuntu terminal.

Upvotes: 23

Views: 52823

Answers (5)

Darsh Shukla
Darsh Shukla

Reputation: 389

UPDATE : 2021-03-22

We now have python-on-whales A Docker client for Python. Works on Linux, macOS, and Windows, for Python 3.7 and above.

>>> from python_on_whales import docker
>>> output = docker.run("hello-world")
>>> print(output)
Hello from Docker! This message shows that your installation appears to be 
working correctly.
>>> from python_on_whales import DockerClient
>>> docker = DockerClient(compose_files=["./my-compose-file.yml"])
>>> docker.compose.build()
>>> docker.compose.up()
...
>>> docker.compose.down()

Upvotes: 11

Gulzar
Gulzar

Reputation: 28044

Edge cases and parameterization of this answer follow.

It is also better to use subprocess.run over subprocess.call

import docker
import subprocess
import os
import time


def main():
    client, log_path = _set_up_environment()
    _run_docker_compose("docker-compose-with-rabbit.yaml", log_path)


def _run_docker_compose(docker_compose_name, log_path):
    bash_command = f"docker-compose -f {docker_compose_name}} up -d"
    _execute_shell_command(bash_command, log_path)


def _execute_shell_command(bash_command, log_path):
    with open(log_path, "w") as output:
        subprocess.run(
            bash_command,
            shell=True,  # pass single string to shell, let it handle.
            stdout=output,
            stderr=output
        )
    while not output.closed:
        time.sleep(0.1)
    print(f"{os.linesep} COMMAND {bash_command} LOG OUTPUT:")
    with open(log_path, "r") as output:
        for line in output:
            print(line)


def _create_docker_log_file():
    log_location, log_name = "logs", "output.log"
    log_path = os.path.join(os.getcwd(), log_location, log_name)
    os.makedirs(os.path.dirname(log_path), exist_ok=True)
    assert os.path.isdir(os.path.dirname(log_path))
    if not os.path.isfile(log_path):
        os.mknod(log_path)

    return log_location, log_name, log_path


def _set_up_environment():
    log_location, log_name, log_path = _create_docker_log_file()
    client = docker.from_env()
    return client, log_path

if __name__ == "__main__":
    main()


Upvotes: 3

MRebati
MRebati

Reputation: 599

You can use a pip package named docker and use it to connect to the Docker. The difference between running a command in subProcess and this solution is the format. You can manage your images, containers, and everything a CLI is capable of.

Check it out here: https://docker-py.readthedocs.io/en/stable/

Sample:

import docker
client = docker.from_env()

client.containers.run("ubuntu", "echo hello world")

# or

client.containers.run("bfirsh/reticulate-splines", detach=True)

# you can even stream your output like this:
for line in container.logs(stream=True):
   print(line.strip())

All code samples are available at the source URL I mentioned.

Upvotes: 5

Robert
Robert

Reputation: 36853

As @AndyShinn says, Python is not a shell language, but you can call to docker as if you were running a shell command:

#!/usr/bin/python
import subprocess

with open("/tmp/output.log", "a") as output:
    subprocess.call("docker run --rm wappalyzer/cli https://wappalyzer.com", shell=True, stdout=output, stderr=output)

With this approach you don't need to import docker.

Upvotes: 30

Andy Shinn
Andy Shinn

Reputation: 28543

This isn't valid Python code. If you are just looking to run a container and passing a command as an argument, you could do something like this:

#!/usr/bin/env python
import sys
import docker

image = "wappalyzer/cli"

client = docker.from_env()
client.containers.run(image,  sys.argv[1], True)

But you should read up more about Python and running processes from Python if that is what you are after. Python is not a shell language and you can't just use shell commands inline.

Upvotes: 14

Related Questions