diff --git a/README.md b/README.md index 48bb193..fb0cf50 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,13 @@ It offers a clean, interactive menu for common Docker operations like pulling im - ๐Ÿ”น **Interactive container management** โ€” start, stop, remove, or attach to containers with simple numbered menus. - ๐Ÿ”น **Port mapping made clear** โ€” automatically prompts for and explains host โ†” container port bindings. -- ๐Ÿ”น **Image operations** โ€” pull, list, and delete Docker images. +- ๐Ÿ”น **Image operations** โ€” pull, list, and delete Docker images; curated pull list (Debian, Ubuntu, Rocky Linux, Alpine) plus a custom entry to grab common bases without retyping them. - ๐Ÿ”น **Script-to-image workflow** โ€” turn a bash setup script into a Dockerfile and build the resulting image in one go. - ๐Ÿ”น **Quick MySQL setup** โ€” spin up a MySQL container with version, password, and port configuration in seconds. - ๐Ÿ”น **Get container IP address** โ€” cleanly retrieves and displays only the containerโ€™s assigned IP. - ๐Ÿ”น **Run detached commands** โ€” execute background jobs inside a container without attaching an interactive shell. - ๐Ÿ”น **Modern C++ design** โ€” built with classes, minimal dependencies, and clear abstractions. +- ๐Ÿ”น **Interactive run flow** โ€” lists pulled images with numeric selection, allows entering a custom image name, and keeps the port-mapping explanation in place before launching `/bin/sh`. --- @@ -112,6 +113,8 @@ public: private: static void runCommand(const std::string& cmd); std::vector> getContainerList() const; + /* NEW helper โ€“ retrieves all images */ + std::vector> getImageList() const; std::string selectContainer(const std::string& prompt); }; ``` @@ -133,6 +136,7 @@ private: - `showContainerIP` โ€” display a containerโ€™s IP address. - `runCommand` โ€” helper to invoke shell commands. - `getContainerList` โ€” retrieve Docker container IDs and names for selection menus. +- `getImageList` โ€” gather local Docker image IDs and names for menus and reporting. - `selectContainer` โ€” present a menu to pick a container interactively. This makes the codebase **extensible** โ€” adding new Docker features like `docker logs` or `docker stats` requires only a small new method. diff --git a/main.cpp b/main.cpp index a4e1020..6f8bea1 100644 --- a/main.cpp +++ b/main.cpp @@ -106,21 +106,71 @@ string DockerManager::selectContainer(const string& prompt) { // ---------------- Docker Actions ---------------- void DockerManager::pullImage() { + const vector images = {"debian:stable", "ubuntu:noble", "rockylinux:9.3", "alpine:latest"}; + + cout << "\nSelect Docker image to pull:\n"; + for (size_t i = 0; i < images.size(); ++i) cout << i + 1 << ". " << images[i] << "\n"; + cout << images.size() + 1 << ". Enter custom image\n"; + cout << "Choose an option (1-" << images.size() + 1 << "): "; + + int choice; + cin >> choice; + string image; - cout << "Enter Docker image to pull (e.g., alpine): "; - cin >> image; + if (choice >= 1 && choice <= static_cast(images.size())) { + image = images[choice - 1]; + } else if (choice == static_cast(images.size()) + 1) { + cout << "Enter custom Docker image name: "; + cin >> image; + } else { + cout << "Invalid selection. Aborting.\n"; + return; + } + + cout << "Pulling image: " << image << "\n"; runCommand("docker pull " + image); } void DockerManager::runContainerInteractive() { + // Get list of available images + auto images = getImageList(); string image; - cout << "Enter Docker image to run interactively (e.g., alpine): "; - cin >> image; - + + if (images.empty()) { + cout << "No Docker images found. Please pull an image first.\n"; + return; + } + + // Display available images + cout << "\nAvailable Docker Images:\n"; + int idx = 1; + for (const auto& img : images) { + cout << idx++ << ". " << img.second << " (" << img.first.substr(0, 12) << ")\n"; + } + + // Prompt user to select or enter custom image + cout << idx << ". Enter custom Docker image name\n"; + cout << "Choose an option (1-" << images.size() << " or " << idx << "): "; + + int choice; + cin >> choice; + + if (choice >= 1 && choice <= static_cast(images.size())) { + // User selected an existing image + image = images[choice - 1].second; + } else if (choice == idx) { + // User wants to enter custom image name + cout << "Enter custom Docker image name: "; + cin >> image; + } else { + cout << "Invalid selection. Aborting.\n"; + return; + } + + // Continue with port mapping int portCount; cout << "How many port mappings? "; cin >> portCount; - vector ports; for (int i = 0; i < portCount; ++i) { string port; @@ -129,14 +179,11 @@ void DockerManager::runContainerInteractive() { cin >> port; ports.push_back("-p " + port); } - string portArgs; for (const auto& p : ports) portArgs += p + " "; - cout << "\nPort Forwarding Explanation:\n" << " '-p hostPort:containerPort' exposes the containerโ€™s port to the host.\n" << " Example: '-p 8080:80' allows access via http://localhost:8080\n\n"; - runCommand("docker run -it " + portArgs + image + " /bin/sh"); } @@ -380,3 +427,4 @@ int main() { } } } +