Compare commits

...

3 commits

Author SHA1 Message Date
fb59f0f19d Design Overview update
Some checks are pending
Build & Upload tux-dock / build (push) Waiting to run
2025-11-24 11:40:31 -05:00
22df65add9 Document docker interaction tweaks 2025-11-24 11:37:58 -05:00
be664b331e Improve docker interaction flows 2025-11-24 11:36:30 -05:00
2 changed files with 62 additions and 10 deletions

View file

@ -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. - 🔹 **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. - 🔹 **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. - 🔹 **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. - 🔹 **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 containers assigned IP. - 🔹 **Get container IP address** — cleanly retrieves and displays only the containers assigned IP.
- 🔹 **Run detached commands** — execute background jobs inside a container without attaching an interactive shell. - 🔹 **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. - 🔹 **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: private:
static void runCommand(const std::string& cmd); static void runCommand(const std::string& cmd);
std::vector<std::pair<std::string, std::string>> getContainerList() const; std::vector<std::pair<std::string, std::string>> getContainerList() const;
/* NEW helper retrieves all images */
std::vector<std::pair<std::string, std::string>> getImageList() const;
std::string selectContainer(const std::string& prompt); std::string selectContainer(const std::string& prompt);
}; };
``` ```
@ -133,6 +136,7 @@ private:
- `showContainerIP` — display a containers IP address. - `showContainerIP` — display a containers IP address.
- `runCommand` — helper to invoke shell commands. - `runCommand` — helper to invoke shell commands.
- `getContainerList` — retrieve Docker container IDs and names for selection menus. - `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. - `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. This makes the codebase **extensible** — adding new Docker features like `docker logs` or `docker stats` requires only a small new method.

View file

@ -106,21 +106,71 @@ string DockerManager::selectContainer(const string& prompt) {
// ---------------- Docker Actions ---------------- // ---------------- Docker Actions ----------------
void DockerManager::pullImage() { void DockerManager::pullImage() {
const vector<string> 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; string image;
cout << "Enter Docker image to pull (e.g., alpine): "; if (choice >= 1 && choice <= static_cast<int>(images.size())) {
image = images[choice - 1];
} else if (choice == static_cast<int>(images.size()) + 1) {
cout << "Enter custom Docker image name: ";
cin >> image; cin >> image;
} else {
cout << "Invalid selection. Aborting.\n";
return;
}
cout << "Pulling image: " << image << "\n";
runCommand("docker pull " + image); runCommand("docker pull " + image);
} }
void DockerManager::runContainerInteractive() { void DockerManager::runContainerInteractive() {
// Get list of available images
auto images = getImageList();
string image; 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<int>(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; int portCount;
cout << "How many port mappings? "; cout << "How many port mappings? ";
cin >> portCount; cin >> portCount;
vector<string> ports; vector<string> ports;
for (int i = 0; i < portCount; ++i) { for (int i = 0; i < portCount; ++i) {
string port; string port;
@ -129,14 +179,11 @@ void DockerManager::runContainerInteractive() {
cin >> port; cin >> port;
ports.push_back("-p " + port); ports.push_back("-p " + port);
} }
string portArgs; string portArgs;
for (const auto& p : ports) portArgs += p + " "; for (const auto& p : ports) portArgs += p + " ";
cout << "\nPort Forwarding Explanation:\n" cout << "\nPort Forwarding Explanation:\n"
<< " '-p hostPort:containerPort' exposes the containers port to the host.\n" << " '-p hostPort:containerPort' exposes the containers port to the host.\n"
<< " Example: '-p 8080:80' allows access via http://localhost:8080\n\n"; << " Example: '-p 8080:80' allows access via http://localhost:8080\n\n";
runCommand("docker run -it " + portArgs + image + " /bin/sh"); runCommand("docker run -it " + portArgs + image + " /bin/sh");
} }
@ -380,3 +427,4 @@ int main() {
} }
} }
} }