Docker-run-to-compose conversion script

Docker-run-to-compose conversion script

This script is a graphical user interface (GUI) that automates the conversion of docker run commands into a Docker Compose YAML file.

How Docker-run-to-compose Works

The script takes a docker run command as input, parses it, and generates a corresponding docker-compose.yml file. It handles common options like port mappings, volume mounts, environment variables, and container names, ensuring that the generated file accurately reflects the original command.

For instance, given the following docker run command:

docker run -d --name my-nginx -p 8080:80 -v /my/local/data:/usr/share/nginx/html nginx

The docker-run-to-compose script would generate the following docker-compose.yml file:

version: '3.8'
services:
  my-nginx:
    image: nginx
    ports:
      - "8080:80"
    volumes:
      - /my/local/data:/usr/share/nginx/html

This file can then be used with Docker Compose to manage the container, simplifying scaling, networking, and other tasks.

To get started, create a new file with the extension .py. This is the file where you will write your Python code. Open your favorite text editor (e.g., Visual Studio Code, Sublime Text, or Notepad++) and copy the following code there:

import tkinter as tk
from tkinter import messagebox, filedialog, Menu
import yaml

def parse_docker_run(command):
    parts = command.split()
    # Начална структура за docker-compose.yml с version: '3.8' най-отгоре
    compose_dict = {
        'version': '3.8',
        'services': {}
    }
    
    service_name = 'app'
    
    i = 0
    while i < len(parts):
        if parts[i] == 'docker' and parts[i+1] == 'run':
            i += 2
            continue
        elif parts[i] == '-d':
            i += 1
            continue
        elif parts[i] == '--name':
            service_name = parts[i+1]
            i += 2
            compose_dict['services'][service_name] = {
                'image': '',
                'ports': [],
                'volumes': [],
                'environment': []
            }
            continue
        elif parts[i] == '-p':
            compose_dict['services'][service_name]['ports'].append(parts[i+1])
            i += 2
            continue
        elif parts[i] == '-v':
            compose_dict['services'][service_name]['volumes'].append(parts[i+1])
            i += 2
            continue
        elif parts[i] == '-e':
            compose_dict['services'][service_name]['environment'].append(parts[i+1])
            i += 2
            continue
        else:
            if not compose_dict['services'][service_name]['image']:
                compose_dict['services'][service_name]['image'] = parts[i]
            i += 1
    
    if not compose_dict['services'][service_name].get('ports'):
        del compose_dict['services'][service_name]['ports']
    if not compose_dict['services'][service_name].get('volumes'):
        del compose_dict['services'][service_name]['volumes']
    if not compose_dict['services'][service_name].get('environment'):
        del compose_dict['services'][service_name]['environment']
    
    return compose_dict

def convert_to_yaml(compose_dict):
    yaml_str = yaml.dump(compose_dict, default_flow_style=False)
    return yaml_str

def generate_compose():
    docker_run_command = input_text.get("1.0", "end-1c").strip()
    if not docker_run_command:
        messagebox.showerror("Error", "Please enter a docker run command.")
        return
    
    try:
        compose_dict = parse_docker_run(docker_run_command)
        compose_yaml = convert_to_yaml(compose_dict)
        
        # Ръчно добавяне на version: '3.8' най-отгоре, за да се гарантира правилното позициониране
        compose_yaml = f"version: '3.8'\n{compose_yaml}"
        
        # Показване на съдържанието на docker-compose.yml в текстовото поле
        output_text.config(state=tk.NORMAL)
        output_text.delete("1.0", tk.END)
        output_text.insert(tk.END, compose_yaml)
        output_text.config(state=tk.DISABLED)

        # Предлагане на потребителя да запази файла
        save_path = filedialog.asksaveasfilename(defaultextension=".yml", filetypes=[("YAML files", "*.yml")])
        if save_path:
            with open(save_path, 'w') as file:
                file.write(compose_yaml)
            messagebox.showinfo("Success", f"docker-compose.yml has been created at {save_path}.")
    except Exception as e:
        messagebox.showerror("Error", f"An error occurred: {str(e)}")

def paste_from_clipboard(event):
    input_text.event_generate('<<Paste>>')

def copy_to_clipboard(event):
    root.clipboard_clear()
    root.clipboard_append(output_text.get("1.0", "end-1c"))
    messagebox.showinfo("Copied", "The content has been copied to the clipboard.")

# Създаване на основния прозорец на приложението
root = tk.Tk()
root.title("Docker Run to Docker Compose Converter")

# Настройки за цветове и стилове
bg_color = "#2e3b4e"
fg_color = "#ffffff"
button_color = "#4caf50"
button_fg_color = "#ffffff"
font_bold = ("Helvetica", 10, "bold")

root.configure(bg=bg_color)

# Етикет и текстово поле за въвеждане на docker run команда
label = tk.Label(root, text="Enter Docker Run Command:", bg=bg_color, fg=fg_color, font=font_bold)
label.pack(pady=10)

input_text = tk.Text(root, height=10, width=50, bg="#1e2c3b", fg=fg_color, insertbackground=fg_color)
input_text.pack(pady=10)

# Добавяне на примерен текст
example_command = "docker run -d --name my-app -p 8080:80 -v /data:/var/www/html -e APP_ENV=production my-image"
input_text.insert(tk.END, example_command)

# Добавяне на десен бутон за поставяне на текст
input_text.bind("<Button-3>", paste_from_clipboard)

# Бутон за генериране на docker-compose.yml
convert_button = tk.Button(root, text="Generate docker-compose.yml", command=generate_compose, bg=button_color, fg=button_fg_color, font=font_bold)
convert_button.pack(pady=20)

# Текстово поле за показване на генерирания docker-compose.yml
output_text = tk.Text(root, height=15, width=50, state=tk.DISABLED, bg="#1e2c3b", fg=fg_color, insertbackground=fg_color)
output_text.pack(pady=10)

# Добавяне на десен бутон за копиране на текста в docker-compose.yml
output_text.bind("<Button-3>", copy_to_clipboard)

# Добавяне на надпис "Създадено от ChatGPT"
footer_label = tk.Label(root, text="Създадено от ChatGPT", bg=bg_color, fg=fg_color)
footer_label.pack(side=tk.BOTTOM, pady=5)

# Стартиране на основния цикъл на приложението
root.mainloop()

Save the file and give it a name like docker-run-to-compose.py

To run the provided script, you will need to have the following Python libraries installed:

Required Libraries:

  1. Tkinter: A standard Python library for creating graphical user interfaces (GUIs). It is usually included with Python by default, so you typically don’t need to install it separately.
  2. PyYAML: A Python library used to parse and generate YAML files.

Installation Instructions:

Since Tkinter is included with most Python installations, you generally only need to install PyYAML. Here’s how you can install it using pip:

pip install PyYAML

docker-run-to-compose.py
Fedya Serafiev

Fedya Serafiev

Fedya Serafiev owns the website linuxcodelab.eu. He finds satisfaction in helping people solve even the most complex technical problems. His current goal is to write easy-to-follow articles so that such problems do not arise at all.

Thank you for reading the article! If you found the information useful, you can donate using the buttons below: