Run Docker Commands in Python
Hello in this tutorial, we will create a simple python flask application and run the docker commands from the python script.
1. Introduction
Flask in python programming helps to build web applications. It is easier than Django’s framework and requires less base code to implement a simple web application. To set up the application we’ll first require to install python.
1.1 Setting up Python
If someone needs to go through the Python installation on Windows, please watch this link. You can download the Python from this link.
1.2 What is Docker & Setting up Docker
In the present world, Docker is an important term,
- Often used in CI/CD platform that packages and runs the application with its dependencies inside a container
- Is a standard for Linux Containers
- A Container is a runtime that runs under any Linux kernel and provides a private machine-like space under Linux
If someone needs to go through the Docker installation, please watch this video.
2. How to run Docker Commands in Python
I am using JetBrains PyCharm as my preferred IDE. You’re free to choose the IDE of your choice. Fig. 1 represents the project structure for this tutorial.
2.1 Creating a requirements file
Add the below code to the requirements file. The file will be responsible to download and install the packages required for this tutorial.
requirements.txt
Flask
2.2 Basic input html form
Define an HTML form in the templates
folder with two input fields responsible to accept the name and tag required for the docker pull …
command. This page will also show the success or error messages once the operation is completed.
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Index</title> </head> <body> <h1>Python Docker client implementation</h1> <hr> <p> {% with messages = get_flashed_messages() %} {% if messages %} <ul class=flashes> {% for message in messages %} <li>{{ message }}</li> {% endfor %} </ul> {% endif %} {% endwith %} </p> <form action="/" method="POST"> <label for="name">Image name:</label> <input type="text" id="name" name="name" placeholder="Enter image name"> <br> <label for="tag">Tag:</label> <input type="text" id="tag" name="tag" placeholder="Enter tag"> <input type="submit" value="Submit" /> </form> </body> </html>
2.3 List images html
Create an HTML page in the templates
folder that will show the list of docker images available in the machine. The page is accessible from the following endpoint – /images
.
images.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Images</title> </head> <body> <h2>Available images</h2> <hr> <p> <span>Total images= </span>{{data|length}} </p> <ul> {% for ele in data %} <li>{{ ele }}</li> {% endfor %} </ul> </body> </html>
2.4 Python code
The python file will expose four different endpoints responsible for interacting with the frontend pages.
/
endpoint – Responsible for showing the HTML page to the user via the HTTP GET call. The same endpoint will also be responsible to handle the HTTP POST call from the form and execute thedocker pull
command to fetch the required image from the docker repository/images
endpoint – Responsible to run thedocker images
command and show the result on theimages.html
page/remove
endpoint – Responsible to remove the image. I have skipped this functionality for users to play
main.py
import logging import os import subprocess from flask import Flask, render_template, request, redirect, flash # [logging config logging.basicConfig(format='%(asctime)s:%(levelname)s:%(filename)s:%(funcName)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=logging.INFO) # logging config] app = Flask(__name__) app.secret_key = "somesecretkey" # http://localhost:5000 @app.route('/', methods=['GET']) def index(): logging.info('Showing index page') return render_template('index.html') @app.route('/', methods=['POST']) def pull(): image_name = request.form.get("name") tag = request.form.get("tag") try: updated_tag = tag if len(tag.strip()) > 0 else 'latest' logging.info('Pulling image= [%s] with tag= [%s]', image_name, updated_tag) sub_cmd = 'docker pull {img_name}:{tag}'.format(img_name=image_name, tag=updated_tag) subprocess.run(sub_cmd, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) flash(f'{image_name} pulled successfully from Docker hub') except subprocess.CalledProcessError as error: if "repository does not exist" in error.stderr.decode("utf-8"): flash(f'{image_name} not found in Docker hub') logging.error(error) elif "not found" in error.stderr.decode("utf-8"): flash(f'{image_name} not found for {tag} tag in Docker hub') logging.error(error) else: flash('Something unexpected has occurred. Check app logs') logging.error(error) return redirect('/') # http://localhost:5000/images @app.route('/images', methods=['GET']) def images(): logging.info('Listing images') sub_cmd = 'docker images --format "Id= {{.ID}}; Name= {{.Repository}}; Tag= {{.Tag}}"' # with open('output.txt', "w") as outfile: # subprocess.run(sub_cmd, shell=True, check=True, stdout=outfile, stderr=outfile) res = subprocess.run(sub_cmd, text=True, stdout=subprocess.PIPE).stdout.splitlines() return render_template('images.html', data=res) # http://localhost:5000/remove @app.route('/remove', methods=['POST']) def remove(): raise Exception('Not yet implemented.') if __name__ == '__main__': # Development only: run "python app.py" and open http://localhost:5000 server_port = os.environ.get('PORT', '5000') app.run(debug=False, port=server_port, host='0.0.0.0')
3. Code run Docker Commands in Python demo
For localhost debugging, you can run the application by running the main.py
py file in the PyCharm IDE. The application will be started on the 5000
port number and you can hit the following url – http://localhost:5000
in the browser of your choice to display the index HTML page.
Enter the details in the input fields and click the submit button. For the demo, I have entered the image name as – hello-world
and tag as – latest
. Once the image is downloaded successfully a success message will be shown as in Fig. 3.
In case of failure, the error message will be shown on the same page. Now to verify whether the image was downloaded successfully or not I have created another endpoint available at http://localhost:5000/images
. This endpoint will trigger the docker images
command to fetch all the available images in your machine and display them on the html page as shown in Fig. 4.
Due to security reasons, only the required image is shown while others are cropped. That is all for this tutorial and I hope the article served you with whatever you were looking for. Happy Learning and do not forget to share!
4. Summary
In this tutorial, we learned about docker and created a simple python flask application to trigger the docker commands from different endpoints. You’re free to play around with this application and change it as per your needs. You can also download the source code of this tutorial from the Downloads section.
5. Download the Project
This was a tutorial on executing docker commands from the python script.
You can download the full source code of this example here: How to run Docker Commands in Python