diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index dfb2dd8..c8a8b85 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -8,7 +8,7 @@ on: jobs: build: - runs-on: [docker] + runs-on: [self-hosted] env: BRANCH: ${{ github.ref_name }} COMMIT: ${{ github.sha }} diff --git a/README.md b/README.md index da37e7c..48bb193 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,12 @@ 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; curated pull list (Debian, Ubuntu, Rocky Linux, Alpine) plus a custom entry to grab common bases without retyping them. +- ๐Ÿ”น **Image operations** โ€” pull, list, and delete Docker images. - ๐Ÿ”น **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`. --- @@ -114,8 +113,6 @@ private: static void runCommand(const std::string& cmd); std::vector> getContainerList() const; std::string selectContainer(const std::string& prompt); - /* NEW helper โ€“ retrieves all images */ - std::vector> getImageList() const; }; ``` @@ -136,7 +133,6 @@ 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 6f8bea1..e5b0c29 100644 --- a/main.cpp +++ b/main.cpp @@ -31,8 +31,6 @@ private: static void runCommand(const string& cmd); vector> getContainerList() const; string selectContainer(const string& prompt); - /* NEW helper โ€“ retrieves all images */ - vector> getImageList() const; }; // ---------------- Core Utility ---------------- @@ -41,24 +39,6 @@ void DockerManager::runCommand(const string& cmd) { system(cmd.c_str()); } -vector> DockerManager::getImageList() const { - vector> images; - array buffer{}; - string result; - FILE* pipe = popen("docker images --format '{{.ID}} {{.Repository}}:{{.Tag}}'", "r"); - if (!pipe) return images; - while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) { - result = buffer.data(); - stringstream ss(result); - string id, repoTag; - ss >> id >> repoTag; - if (!id.empty() && !repoTag.empty()) - images.emplace_back(id, repoTag); - } - pclose(pipe); - return images; -} - vector> DockerManager::getContainerList() const { vector> containers; array buffer{}; @@ -106,71 +86,21 @@ 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; - 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"; + cout << "Enter Docker image to pull (e.g., alpine): "; + cin >> image; runCommand("docker pull " + image); } void DockerManager::runContainerInteractive() { - // Get list of available images - auto images = getImageList(); string 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 + cout << "Enter Docker image to run interactively (e.g., alpine): "; + cin >> image; + int portCount; cout << "How many port mappings? "; cin >> portCount; + vector ports; for (int i = 0; i < portCount; ++i) { string port; @@ -179,11 +109,14 @@ 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"); } @@ -201,31 +134,10 @@ void DockerManager::startDetached() { } void DockerManager::deleteImage() { - auto images = getImageList(); - if (images.empty()) { - cout << "No Docker images found.\n"; - return; - } - - cout << "\nAvailable Images:\n"; - int idx = 1; - for (const auto& img : images) { - cout << idx++ << ". " << img.second << " (" << img.first.substr(0, 12) << ")\n"; - } - - int choice; - cout << "Select image to delete (1-" << images.size() << "): "; - cin >> choice; - - if (choice < 1 || choice > static_cast(images.size())) { - cout << "Invalid selection.\n"; - return; - } - - const string& id = images[choice - 1].first; - cout << "Deleting image: " << images[choice - 1].second - << " (ID: " << id << ") ...\n"; - runCommand("docker rmi " + id); + string image; + cout << "Enter image name or ID to delete: "; + cin >> image; + runCommand("docker rmi " + image); } void DockerManager::stopContainer() { @@ -427,4 +339,3 @@ int main() { } } } -