简体   繁体   中英

How to create a Docker container that runs a python script that writes file to a location outside the container

I have a python script that I run on a Raspberry Pi that checks Gmail on a given interval and saves any attachments to a specified directory. I did not create this script and the website that I got it from doesn't seem to be active any more. All credit to knight-of-pi.org for the script.

I would like to take this script and run it in a container. I have run existing containers, but I have limited experience creating one. I am not sure I understand how I would get the python script to save the files outside of the container onto the host machine.

Here is the python script:


#!/usr/bin/env python
 
import os, sys, time, argparse

import email
from imapclient import IMAPClient

# credentials could be stored here permanently, but that's bad security.
HOSTNAME = 'smtp.gmail.com'
USERNAME = 'example@gmail.com'
PASSWORD = 'example'
MESSAGE_SUBJECT = 'example'

MAILBOX = 'Inbox'
TARGET = '/media/USBHDD1/shares/'  # this is the path where attachments are stored 
CHECK_FREQ = 3600 # in seconds

def parse_arguments(sysargs):
    """ Setup the command line options. """

    description = '''The script parseIMAPemail.py is looped and repeatedly 
    checks a mail box if a mail with a specified subject has arrived.
    If so, the emails attachment is stored. This script is a part of the tutorial 
    www.knight-of-pi.org/accessing-and-parsing-emails-with-the-raspberry-pi-and-imapclient'''

    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('-u', '--username', nargs='?', metavar='str', type=str,
                                    default=USERNAME, help='Username of the Email account',)
    parser.add_argument('-s', '--subject', nargs='?', metavar='str', type=str,
                                     default=MESSAGE_SUBJECT, help='The subject new emails should be scanned for')
    parser.add_argument('--host', nargs='?', metavar='str', type=str,
                                     default=HOSTNAME, help='Name of the IMAP host webserver')
    parser.add_argument('--pwd', nargs='?', metavar='str', type=str,
                                     default=PASSWORD, help='Password belonging to the username')

    return parser.parse_args(sysargs)

def store_attachment(part):
    """ Store attached files as they are and with the same name. """

    filename = part.get_filename()
    att_path = os.path.join(TARGET, filename)

    if not os.path.isfile(att_path) :
        fp = open(att_path, 'wb')
        fp.write(part.get_payload(decode=True))
        fp.close()
    print "Successfully stored attachment!"

def check_attachment(mail):
    """ Examine if the email has the requested subject and store the attachment if so. """

    print "["+mail["From"]+"] :" + mail["Subject"]

    for part in mail.walk():
        if part.get_content_maintype() == 'multipart':
            continue
        if part.get('Content-Disposition') is None:
            continue

        store_attachment(part)
        time.sleep(3)

def scan_emails(args, unread):
    """ Scan all unread Emails for the given Subject. """

    for msg_id, stuff in unread.iteritems():
        new_email = email.message_from_string(unread[msg_id]['RFC822'])
        
        if new_email['subject'] == args.subject:
            print "Found subject! Storing the attachment of mail id ",  msg_id
            check_attachment(new_email)

def loop(args):
    """ Main loop: log into the IMAP server and fetch all unread emails,
         which are delegated into scan_emails. """

    print('Logging into ' + args.username)
    try:
        server = IMAPClient(args.host, use_uid=True, ssl=True)
        server.login(args.username, args.pwd)   
    
        select_info = server.select_folder(MAILBOX)
        messages = server.search(['UNSEEN'])
        all_unread = server.fetch(messages, ['RFC822'])
        scan_emails(args, all_unread)
    except:
        print('oops')

    time.sleep(CHECK_FREQ)


 
if __name__ == '__main__':
    args = parse_arguments(sys.argv[1:])

    try:
        while True:
            loop(args)
    finally:
        pass


I have found lots of examples of running python scripts in a container and examples of writing files outside of containers, but getting the container to do both is confusing me. From my research I think I need to use volume command which I think is something like "-v $(pwd)/media/USBHDD1/shares/:/media/USBHDD1/shares/" in the run command, but I am not sure how to do that with calling the python script. I would appreciate any suggestion that could point me in the right direction.

Thanks.

This can be achieved with Bind Mounts .

Your Docker run should have the -v parameter like this:

docker run -it --name sample-container -v "${pwd}:/media/USBHDD1/shares" -d python:latest

${pwd} is the current relative host directory, and /media/USBHDD1/shares is the container directory.

then, when your Python code runs in your container, write the output to the /media/USBHDD1/shares directory:

with open('/media/USBHDD1/shares/[your file name here]', 'w') as f:
    f.write('example data')

These directories are synced between host and container. ie Write to host and data will be accessible to container. Write to container and data will be accessible to host.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM